Search code examples
asp.net-coreasp.net-core-mvcidentityserver4asp.net-core-identity

Using IProfileService when sign-in by Google OAuth


I'm trying to change the IdentityServer4 AspNetIdentity sample to be able to login from both local created users and Google.

I was able to do this by adding Google authentication:

        app.UseIdentity();
        app.UseIdentityServer();

        var cookieScheme = app.ApplicationServices.GetRequiredService<IOptions<IdentityOptions>>().Value.Cookies.ExternalCookieAuthenticationScheme;

        // Add external authentication middleware below. To configure them please see http://go.microsoft.com/fwlink/?LinkID=532715
        app.UseGoogleAuthentication(new GoogleOptions
        {
            AuthenticationScheme = "Google",
            SignInScheme = cookieScheme,
            ClientId = "client_id",
            ClientSecret = "client_secret"
        });

As expected the Home view shows correct user claims:

sub
c51da331-0348-45dd-352f-08d4526f6266
name
EMAIL@gmail.com
AspNet.Identity.SecurityStamp
568a167f-a431-4f70-ba66-918f99e95eef
idp
Google
amr
external
auth_time
1486815555

When user signs in for the first time using Google account I add some information to the database and I thought I can add them to the user claims by using a custom IProfileService implementation and configuring IdentityServer to use my custom IProfileService:

         var builder = services.AddIdentityServer();
         builder.AddTemporarySigningCredential();

        builder.AddConfigurationStore(b => b.UseSqlServer(connectionString, options => options.MigrationsAssembly(migrationAssembly)));
        builder.AddOperationalStore(b => b.UseSqlServer(connectionString, options => options.MigrationsAssembly(migrationAssembly)));
        builder.AddAspNetIdentity<MyUser>();
        builder.AddProfileService<MyCustomProfileService>();

But now when I navigate to Home page the user claims remain the same and even GetProfileDataAsync method will not hit.

I appreciate if anyone can tell me what is it like this.


Solution

  • It turns out that the IdentityServer will not use IProfileService to add custom claims if it is configured to use ASP.NET Identity library unless (as mentioned by @Set) the UserInfo endpoint get called directly. The design approach is to use ASP.NET Identity mechanism for creating the claims by registering an IUserClaimsPrincipalFactory.

    In this case we can either create a custom implementation of IUserClaimsPrincipalFactory or because ASP.NET Identity will load any additional claims stored in the database, add any extra claims using AddClaimsAsync method of UserManager class.