1

Hi I want to have users authenticate using Google and I want my API and also use their Google token to communicate on their behalf with google. Here is a diagram so far. The ???? is where I'm wondering what should I return the the client.

enter image description here

a) Should I return my own JWT and use it to authenticate all other client request? But then to communicate with google on their behalf I have to store their token which I dont want to

b) Should I return the google token to the client for them to authenticate their requests with it? Do I have a out-of-the-box middleware for authenticating their tokens again with google? Or should I write one myself?

c) Some other option?

Basically I need their google token so I can talk with google API but I dont want to store it on my end and also I dont want the client to need to send my JWT and their google token with each request.

EDIT This is my custom google token validator but this is just the validation of the google token when the client sends it with a request.

    public class CustomGoogleTokenValidator : ISecurityTokenValidator
{
    private readonly JwtSecurityTokenHandler tokenHandler;
    private readonly ILogger logger;

    public bool CanValidateToken => true;

    public int MaximumTokenSizeInBytes { get; set; } = TokenValidationParameters.DefaultMaximumTokenSizeInBytes;

    public CustomGoogleTokenValidator(ILogger logger)
    {
        tokenHandler = new JwtSecurityTokenHandler();
        this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }
    public bool CanReadToken(string securityToken)
    {
        return tokenHandler.CanReadToken(securityToken);
    }

    public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken)
    {
        validatedToken = null;


        var payload = GoogleJsonWebSignature.ValidateAsync(securityToken, new GoogleJsonWebSignature.ValidationSettings()).Result;

        // TODO VALIDATE
        //payload.Audience == "myclientid";
        //payload.Issuer == "accounts.google.com" or "https://accounts.google.com"
        //payload.ExpirationTimeSeconds > 0;

        var claims = new List<Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, payload.Name),
                new Claim(ClaimTypes.Name, payload.Name),
                new Claim(JwtRegisteredClaimNames.FamilyName, payload.FamilyName),
                new Claim(JwtRegisteredClaimNames.GivenName, payload.GivenName),
                new Claim(JwtRegisteredClaimNames.Email, payload.Email),
                new Claim(JwtRegisteredClaimNames.Sub, payload.Subject),
                new Claim(JwtRegisteredClaimNames.Iss, payload.Issuer),
            };

        try
        {
            var principle = new ClaimsPrincipal();
            principle.AddIdentity(new ClaimsIdentity(claims));
            return principle;
        }
        catch (Exception e)
        {
            this.logger.Error(e, "Error while creating claims priciple.");
            throw;
        }
    }
}

I still don't know if it's appropriate and enought to just send google token to them after I validate it on login. Like below or should I create a new jwt with claims or somethig else?

  [AllowAnonymous]
    [HttpPost("google")]
    public async Task<IActionResult> Google([FromBody]GoogleLoginDto loginDto)
    {
        try
        {
            var payload = await GoogleJsonWebSignature.ValidateAsync(loginDto.TokenId, new GoogleJsonWebSignature.ValidationSettings());

            // TODO Check if user exists if not create new one...
            var user = this.GetUsers().FirstOrDefault(u => u.Email == payload.Email);         

            return Ok(new
            {
                token = loginDto.TokenId
            });
        }
        catch (Exception ex)
        {
            BadRequest(ex.Message);
        }
        return BadRequest();
    }
Paladin
  • 21
  • 4

1 Answers1

0

In oauth, there are server roles like client, resource owner, authorization server, resource server. The resource should be protected and grant authorization like figure below: enter image description here

However, as far as I know, Google doesn't support protecting the customer's resource like web API. You can refer to the scenarios covered from below(OAuth 2.0 Overview). The most scenarios are about how to implement OAuth 2.0 authorization to access Google APIs(resource). It seems that your scenario more likes on-behalf-flow. You may check whether OAuth 2.0 for the service account to see if it fits your scenario.

And for technically, if you trust the Google's authorization server, you can verify the token as the code in your post. However in this scenario, you should verify the signature(JWT token) first ensure that the token was issued from Google, before you verify the claims. Here is an thread about verify AAD token, I answered before you can refer.

To understand concepts about OAuth 2.0 Authorization Framework, you can refer to rfc6749. And for the individually identity platform support OAuth, you need to check it on each platform(Microsoft, Google, etc.).

enter image description here

Community
  • 1
  • 1
Fei Xue
  • 14,369
  • 1
  • 19
  • 27