How can I get the access token from IdentityServer4 for an external login user which does not even have a password?

71 Views Asked by At

I am able to call or redirect to IdentityServer endpoint "GoogleLogin" from my SPA using html anchor tag href. And then, I got redirected to Google sign-in screen, on a successful sign-in, got a callback to IdentityServer "GoogleResponse" GET endpoint with "returnUrl" pointing to my SPA, now able to create/find user using ASP NET Identity.

Internal users can access the authorised resource using IdentityServer access token but social media users not access it because of their no access token. So from here, the question is how will I get IdentityServer access token and get redirected to my SPA?

[HttpGet("GoogleLogin")]
[AllowAnonymous]
public IActionResult GoogleLogin()
{
    var properties = _signInManager.ConfigureExternalAuthenticationProperties(GoogleDefaults.AuthenticationScheme, "/api/Account/GoogleResponse");
    return Challenge(properties, GoogleDefaults.AuthenticationScheme);
}

[HttpGet("GoogleResponse")]
[AllowAnonymous]
public async Task<IActionResult> GoogleResponse()
{
    ExternalLoginInfo info = await _signInManager.GetExternalLoginInfoAsync();
    ApplicationUser user = new ApplicationUser
      {
          Email = info.Principal.FindFirst(ClaimTypes.Email).Value,
          UserName = info.Principal.FindFirst(ClaimTypes.Email).Value,
          FullName = info.Principal.FindFirst(ClaimTypes.Name).Value
      };
    var externalAccessToken = await _userManager.GetAuthenticationTokenAsync(user, GoogleDefaults.AuthenticationScheme, "access_token");

    if (info == null)
        return Ok(info);

    var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false);

    string[] userInfo = { info.Principal.FindFirst(ClaimTypes.Name).Value, info.Principal.FindFirst(ClaimTypes.Email).Value };

    if (result.Succeeded)
        return Ok(result);
    else
    {
        IdentityResult identResult = await _userManager.CreateAsync(user);
        await _userManager.AddToRoleAsync(user, "user");
        identResult = await _userManager.AddLoginAsync(user, info);

        if (identResult.Succeeded)
        {
            await _signInManager.SignInAsync(user, false);
            return Ok(identResult);
        }

        return BadRequest();
    }
}

externalAccessToken is now null here. If I get access token then I will redirect to spa with access token.

Identity server and external login provider configuration

builder.Services.AddIdentityServer(options =>
{
     options.IssuerUri = authServerUrl;
     options.Events.RaiseErrorEvents = true;
     options.Events.RaiseFailureEvents = true;
     options.Events.RaiseErrorEvents = true;
})
     .AddAspNetIdentity<ApplicationUser>()
     .AddInMemoryApiScopes(IdentityServerConfig.GetApiScopes())
     .AddInMemoryApiResources(identityServerSettings.ApiResources)
     .AddInMemoryClients(IdentityServerConfig.GetClients())
     .AddInMemoryIdentityResources(identityServerSettings.IdentityResources)
     .AddDeveloperSigningCredential();


builder.Services.AddAuthentication()
         .AddGoogle(opts =>
         {
             opts.ClientId = "clientid_code";
             opts.ClientSecret = "secret_code";
             opts.SignInScheme = IdentityConstants.ExternalScheme;
         });

builder.Services.AddAuthentication(o =>
 {
     o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
     o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
     o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
 })
     .AddJwtBearer(options =>
     {
         options.Authority = authServerUrl; // base-address of your identityserver
         options.TokenValidationParameters.ValidateAudience = false;
         options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
         options.MapInboundClaims = false;
         options.TokenValidationParameters.NameClaimType = JwtClaimTypes.Name;
         options.TokenValidationParameters.RoleClaimType = JwtClaimTypes.Role;
     });

Identity server client set

public static IEnumerable<Client> GetClients()
{
    // Clients credentials.
    return new List<Client>
        {
            new Client
            {
                ClientId = JobChaiAIClientID,
                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                AllowAccessTokensViaBrowser = true,
                RequireClientSecret = false,
                                    
                AllowedScopes = {
                    IdentityServerConstants.StandardScopes.OpenId, 
                    IdentityServerConstants.StandardScopes.Profile,
                    IdentityServerConstants.StandardScopes.Phone,
                    IdentityServerConstants.StandardScopes.Email,
                    ScopeConstants.Roles,
                    ApiName
                },
                AllowOfflineAccess = true,
                RefreshTokenExpiration = TokenExpiration.Sliding,
                RefreshTokenUsage = TokenUsage.OneTimeOnly,
            },

            new Client
            {
                //clent 2
            }
        };
    }
}
0

There are 0 best solutions below