使用AspNet Core 2.0的Google JWT身份验证 [英] Google JWT Authentication with AspNet Core 2.0

查看:789
本文介绍了使用AspNet Core 2.0的Google JWT身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将Google身份验证集成到我的ASP.NET Core 2.0 web api中,并且无法弄清楚如何让它正常工作。

我有这段代码在我的Startup.cs ConfigureServices 中:

  services.AddIdentity< ApplicationUser, IdentityRole>()
.AddDefaultTokenProviders();

services.AddAuthentication()
.AddGoogle(googleOptions =>
{
googleOptions.ClientId =配置[身份验证:Google:ClientId];
googleOptions.ClientSecret =配置[身份验证:Google:ClientSecret];
});

Configure(IApplicationBuilder应用程序,IHostingEnvironment env)

  app.UseAuthentication(); 

当我导航到授权端点时,结果是一个 302 Found ,因为它可能是重定向到某个登录端点(我从未创建过)。如何防止重定向,并让API期待令牌并在没有提供令牌的情况下返回 401

解决方案

正如Tratcher指出的那样出, AddGoogle 中间件实际上并不适用于JWT身份验证流程。在做了更多的研究之后,我意识到我最终需要的是这里描述的内容:
https://developers.google.com/identity/sign-in/web/backend-auth



所以我的下一个问题


  1. 我不能依赖标准的dotnet核心Jwt auth中间件,因为我需要将谷歌令牌验证委托给谷歌库 li>
  2. 没有将C#google验证程序列为该页面上的外部客户端库之一。

在进一步挖掘之后,我发现JWT验证支持已添加到C#此处使用此类和方法:
Google.Apis.Auth.Task< GoogleJsonWebSignature.Payload> ValidateAsync(string jwt,GoogleJsonWebSignature.ValidationSettings validationSettings)



接下来我需要弄清楚如何替换内置的JWT验证。从这个SO问题中我想出了一种方法:
ASP .NET核心JWT持票人令牌自定义验证



以下是我的自定义GoogleTokenValidator:

  public class GoogleTokenValidator:ISecurityTokenValidator 
{
private readonly JwtSecurityTokenHandler _tokenHandler;
$ b $ public GoogleTokenValidator()
{
_tokenHandler = new JwtSecurityTokenHandler();
}

public bool CanValidateToken =>真正;

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

public bool CanReadToken(string securityToken)
{
return _tokenHandler.CanReadToken(securityToken);

$ b $公共ClaimsPrincipal ValidateToken(字符串securityToken,TokenValidationParameters validationParameters,out SecurityToken validatedToken)
{
validatedToken = null;
var payload = GoogleJsonWebSignature.ValidateAsync(securityToken,new GoogleJsonWebSignature.ValidationSettings())。 //这里是我委托给Google验证

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

尝试
{
var principle = new ClaimsPrincipal();
principle.AddIdentity(new ClaimsIdentity(claims,AuthenticationTypes.Password));
退货原则;
}
catch(Exception e)
{
Console.WriteLine(e);
throw;




$ / code>

Startup.cs ,我还需要清除默认的JWT验证,并添加我自定义的一个:



<$ p $ services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options .DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

})
.AddJwtBearer(o =>
{
o.SecurityTokenValidators.Clear();
o .SecurityTokenValidators.Add(new GoogleTokenValidator());
}

方式,但这是我登陆的地方,它似乎工作正常!我做了额外的工作,我为了简单而离开这里,例如le,检查用户的数据库中是否已有用户与Google提供的索赔相匹配,因此,如果上述代码不能100%正常工作,我可能已经无意中删除了某些内容,我很抱歉。


I am trying to integrate google authentication in my ASP.NET Core 2.0 web api and I cannot figure out how to get it to work.

I have this code in my Startup.cs ConfigureServices:

services.AddIdentity<ApplicationUser, IdentityRole>()
.AddDefaultTokenProviders();

services.AddAuthentication()
.AddGoogle(googleOptions => 
 {
     googleOptions.ClientId = Configuration["Authentication:Google:ClientId"];
     googleOptions.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
});

And this in Configure(IApplicationBuilder app, IHostingEnvironment env):

 app.UseAuthentication();

When I navigate to an Authorized endpoint, the result is a 302 Found because presumably it is redirecting to some login endpoint (which I never created). How do I prevent the redirection and just have the API expect a token and return a 401 if no token is provided?

解决方案

Posting my ultimate approach for posterity.

As Tratcher pointed out, the AddGoogle middleware is not actually for a JWT authentication flow. After doing more research, I realized that what I ultimately wanted is what is described here: https://developers.google.com/identity/sign-in/web/backend-auth

So my next problems were

  1. I could not rely on the standard dotnet core Jwt auth middleware anymore since I need to delegate the google token validation to google libraries
  2. There was no C# google validator listed as one of the external client libraries on that page.

After more digging, I found this that JWT validation support was added to C# here using this class and method: Google.Apis.Auth.Task<GoogleJsonWebSignature.Payload> ValidateAsync(string jwt, GoogleJsonWebSignature.ValidationSettings validationSettings)

Next I needed to figure out how to replace the built in JWT validation. From this SO questions I came up with an approach: ASP.NET Core JWT Bearer Token Custom Validation

Here is my custom GoogleTokenValidator:

public class GoogleTokenValidator : ISecurityTokenValidator
{
    private readonly JwtSecurityTokenHandler _tokenHandler;

    public GoogleTokenValidator()
    {
        _tokenHandler = new JwtSecurityTokenHandler();
    }

    public bool CanValidateToken => true;

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

    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; // here is where I delegate to Google to validate

        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, AuthenticationTypes.Password));
            return principle;
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;

        }
    }
}

And in Startup.cs, I also needed to clear out the default JWT validation, and add my custom one:

services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

            })
            .AddJwtBearer(o =>
                {
                    o.SecurityTokenValidators.Clear();
                    o.SecurityTokenValidators.Add(new GoogleTokenValidator());
                }

Maybe there is an easier way, but this is where I landed and it seems to work fine! There was additional work I did that I left out of here for simplicity, for example, checking if there is already a user in my user's DB that matches the claims provided by google, so I apologize if the code above does not 100% work since I may have removed something inadvertently.

这篇关于使用AspNet Core 2.0的Google JWT身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆