Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

_signInManager.GetExternalLoginInfoAsync() always returns null with open id to azure ad

Why does the signinmanager getexternallogininfoasync method always returning null?

I am using VS2015 with the default asp.net core (not framework) project for MVC with individual user accounts (this is a requirement). The purpose of using third party login is to allow users to self register. Role based authorization will be handled by asp.net identity using the identity provided from registering through Azure AD.

Correct me if the following interpretation of the signin in manager is incorrect. This method should provide details on the external login and return a claimsprincipal object which contains the claims provided by the user by the identity provider.

I have used the following guide for setting up OpenIdConnectAuthentication in my Startup.cs (class section below)

https://azure.microsoft.com/en-us/documentation/samples/active-directory-dotnet-webapp-openidconnect/

When I launch the external login provider, it directs me to the organization login page and succeeds.

However the variable info which should be populated by the signinmanager method is null

if I put a breakpoint into the callback class the User is populated and the IsAuthenticated variable is true.

I could drive the functionality of allowing the user to register in the app myself, however, this is my first attempt at implementing third party login and I would like to understand what I am doing wrong as this point.

Startup.cs

  public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

        services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultTokenProviders();
        // Add Authentication services.
        services.AddAuthentication(sharedOptions => {
            sharedOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

        });
        //services.AddDistributedMemoryCache();
        //services.AddSession();
        services.AddMvc();

        // Add application services.
        services.AddTransient<IEmailSender, AuthMessageSender>();
        services.AddTransient<ISmsSender, AuthMessageSender>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseApplicationInsightsRequestTelemetry();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseApplicationInsightsExceptionTelemetry();

        app.UseStaticFiles();

        app.UseIdentity();

        // Configure the OWIN pipeline to use cookie auth.
        app.UseCookieAuthentication( new CookieAuthenticationOptions());



        //Add external authentication middleware below.To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
        app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
        {

            SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme,
            CallbackPath = "/signin-oidc",
            ClientId = Configuration["AzureAD:ClientId"],
            Authority = String.Format(Configuration["AzureAd:AadInstance"], Configuration["AzureAd:Tenant"]),
            ResponseType = OpenIdConnectResponseType.IdToken,
            PostLogoutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"],
            Events = new OpenIdConnectEvents
            {
                //OnRemoteFailure = OnAuthenticationFailed,
            }
        });

        //app.UseSession();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

External Login

        public IActionResult ExternalLogin(string provider, string returnUrl = null)
    {

        // Request a redirect to the external login provider.
        var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
        var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
        return Challenge(properties, provider);
    }

enter image description here

like image 718
Bill Avatar asked Oct 24 '16 21:10

Bill


3 Answers

There have been multiple reported issues with this method producing a null value in the past. This does not happen with any of the supported authentication methods that are supplied out of the box. This is a problem at least with using OAuth with azure AD and following the supplied method in the post. However, there is a workaround that still allows for the use of the default project type. Simply replace the method that produces the ExternalLoginInfo variable (info) with a roll your own ExternalLoginInfo class constructed using the User principle.

 ExternalLoginInfo info = new ExternalLoginInfo(User,
            "Microsoft",
            User.Claims.Where(x=>x.Type== "http://schemas.microsoft.com/identity/claims/objectidentifier").FirstOrDefault().Value.ToString(),
           "Microsoft" );

ASP.NET MVC 5 (VS2013 final): Facebook login with OWIN fails (loginInfo is null)

MVC 5 Owin Facebook Auth results in Null Reference Exception

http://blogs.msdn.com/b/webdev/archive/2013/10/16/get-more-information-from-social-providers-used-in-the-vs-2013-project-templates.aspx

like image 77
Bill Avatar answered Nov 18 '22 18:11

Bill


I had a similar problem using the OpenIdConnect middleware - I finally fixed it by changing ResponseType to OpenIdConnectResponseType.CodeIdToken (it was being set to 'Code').

Here's a link to my Startup.Auth.vb source:

OWIN OpenID provider - GetExternalLoginInfo() returns null

like image 2
Liam Avatar answered Nov 18 '22 19:11

Liam


In my case, I needed to explicitly pass null for cookieScheme when adding it on startup, as discussed in this github issue: https://github.com/AzureAD/microsoft-identity-web/issues/133

services.AddAuthentication(idp.LoginProvider).AddMicrosoftIdentityWebApp(
  o => {
    o.Instance = config.Instance;
    o.Domain = config.Domain;
    o.ClientId = config.ClientId;
    o.TenantId = config.TenantId;
    o.CallbackPath = config.CallbackPath;
    o.SignInScheme = IdentityConstants.ExternalScheme;
    o.SignOutScheme = IdentityConstants.ExternalScheme;
  },
  openIdConnectScheme: idp.LoginProvider,
  cookieScheme: null // YAR
);
like image 2
JohnnyFun Avatar answered Nov 18 '22 19:11

JohnnyFun



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!