Use JWT with OAuth Authentication in .Net-Core

2019-08-29 15:55发布

问题:

I have a custom implementation of .AddOAuth() in .Net-Core. I've created a nuget package for Authentication using Coinbase (which is basically a clone of the add google implementation plus a few custom options specific to coinbase) full source. I've looked at a few other questions on this however they don't seem to implement OAuth (e.g I cannot pass scopes) I would like to login using OAuth But I want to return to my clients a JWT.

When I try to use JWT with AddCoinbase ( which is just a derrivative of AddOAuth)

services.AddAuthentication(JWT_BEARER_AUTH)
.AddJwtBearer(cfg =>
{
    cfg.RequireHttpsMetadata = false;
    cfg.SaveToken = true;

    cfg.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidIssuer = Configuration["Tokens:Issuer"],
        ValidAudience = Configuration["Tokens:Issuer"],
        //TODO: get key from secret section
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
     };
 })
 .AddCoinbase(options => {
     options.AccessAllAccounts = true;
     options.SendLimitAmount = 1;
     options.SendLimitCurrency = "USD";
     options.SendLimitPeriod = SendLimitPeriod.day;
     options.ClientId = Configuration["Coinbase:ClientId"];
     options.ClientSecret = Configuration["Coinbase:ClientSecret"];
     COINBASE_SCOPES.ForEach(scope => options.Scope.Add(scope));
     options.SaveTokens = true;
     options.ClaimActions.MapJsonKey("urn:coinbase:avatar", "avatar_url");
 });

After I login to coinbase the external callback redirects me

[HttpGet("ExternalLoginCallback")]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
    if (remoteError != null)
    {
        //TODO: Handle remote error failure
        throw new Exception($"Error from external provider: {remoteError}");            
    }
    var info = await _signInManager.GetExternalLoginInfoAsync();
    if (info == null)
    {
        //TODO: Handle null external login info
        throw new Exception("Error: could not find user info");
    }

    // Sign in the user with this external login provider if the user already has a login.
    var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);1

    var user = await (result.Succeeded ?
            _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey)
        : this.CreateIdentityUser(info));

     await _signInManager.UpdateExternalAuthenticationTokensAsync(info);
    _logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider);

    return Redirect(returnUrl);
}

After the redirect I never receive a JSON Web Token I always receive a Cookie. How can I leverage OAuth Authentication while serving JWT to my Clients?

回答1:

OAuth is not a Json Web Token solution. OAuth 2.0 provides authorization and optionally identification (OIDC).

When you authorize via an OAuth 2.0 endpoint, you receive an Access Token and optionally an ID Token. The ID Token is a Signed JWT. The Access Token is an opaque object that is a Signed JWT for some vendor implementations but not all (Google is opaque).

After authorization you receive one or two tokens (access and ID). You can wrap them in your own JWT, sign it and then use the combined JWT any way that you want.