0
votes

I am creating IdentityServer4 auth with ASP.NET Identity, for React SPA and an ASP.NET Core Web API with policy-based authorization.

Take a look at this flow diagram as I am not yet able to embed images directly into the question.

So basically what I have done till now,

  1. React SPA will have "Sign in with Google" ("react-google-login" lib) on successful Google login
  2. Received response with "tokenObj" which contains IdToken and other stuff
  3. POST request, using Id token and some extra claims field, from React SPA to the IdentityServer4 endpoint
  4. Validated IdToken from IdentityServer4 controller endpoint using Google client library method Google.Apis.Auth.GoogleJsonWebSignature.ValidateAsync
  5. On successful IdToken validation Create/Get the user using ASP.NET Identity UserManager methods and,
  6. Also, the custom claim which was passed in the POST request is added for that user into DB

What I want to do now,

  1. Getting an "access_token" from the IdentityServer4, to pass it into that POST request's successful response.

Note: Don't want to pass Google provided access_token to the React SPA. Want to pass an IdentityServer4 issued access_token to the SPA. And Access token should contain that custom claim while decoded, further to process policy-based authorization in another API. I also knew about ProfileService is used to pass the custom claims inside the access token issued by IdentityServer4, so ProfileService I have implemented.

So the question is mainly focused on how to pass the new access_token issued by IdentityServer4 after validating users using Google IdToken.

Minimal working example


  public class ExternalLoginModel
     {
        public string IdToken { get; set; }
        public string UserRole { get; set; }
     }
[Route("api/[controller]")]
[ApiController]
public class ExternalAuthController : ControllerBase
{
   [HttpPost]
   [Route("google")]
   public async Task<IActionResult> AuthenticateGoogleSignin(ExternalLoginModel externalLoginModel)
        {
            Payload payload;
            var provider = "google";
            try
            {
                // currently no need to validate
                var validationSettings = new ValidationSettings
                { Audience = new[] { "YOUR_CLIENT_ID" } };
                payload = await GoogleJsonWebSignature.ValidateAsync(
                    externalLoginModel.IdToken, validationSettings);
                 // create custom claims and store claims for the user found from Google IdToken
                 // storing custom claims passed in request if user is created.
                var userRole = externalLoginModel.UserRole;
                var user = await GetOrCreateExternalLoginUser("google", 
                                                                    payload.Subject,
                                                                    payload.Email,
                                                                    userRole);

                return Ok(new
                {
                    access_token = "want_to_give_identity_server4_issued_access_token"
                });
            }
            catch
            {
                // Invalid token
            }
            return BadRequest();
        }
}
2
I have taken reference from this github.com/mickeysden/dotnet-core-react-oauth-example/blob/… But in this project, as JwtSecurityToken() is used in a similar way I want the access token from the IdentityServer4.Rahul Parmar

2 Answers

0
votes

I think you make this more complicated than it has to be.

I think the better approach is to let your SPA application ask your backend (ASP.NET Identity) to ask IdentityServer to authenticate the user. Then using external authentication, IdentityServer will ask the user to authenticate with Google.

By doing this, IdentityServer and Google will talk directly to each other. After authentication you will get the tokens back from IdentityServer and sent back to ASP.NET Identity. Using these tokens a proper session cookie can be issued to your SPA application.

This is a more secure approach to avoid the SPA application to deal with this.

To get the external authentication in place, here's a few starting points:

Besides that I think the question might need a bit more clarification? perhaps a picture of your setup could help.

Regarding your picture, you should not go from React directly to Google, instead you go via IdentityServer and then Google, like in this picture:

enter image description here

The react and Google should never interact directly. IdentityServer shields your application from Google.

0
votes

You will have to perform the below steps in order to get customs claims for an user:-

  1. Add the custom claims to the list of IdentityResource.
  2. set up the claims against the user.
  3. Add the claims in the list of allowed scopes against the client for which token has to be issued.
  4. Once you have acquired an access token from identity server using the token you can then call the user Info endpoint GET /connect/userinfo to get the list of claims set up for the user.