web-dev-qa-db-ja.com

AspNet Core2.0を使用したGoogleJWT認証

Google認証をASP.NETCore 2.0 Web APIに統合しようとしていますが、それを機能させる方法がわかりません。

Startup.cs ConfigureServicesにこのコードがあります:

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

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

そしてこれはConfigure(IApplicationBuilder app, IHostingEnvironment env)にあります:

_ app.UseAuthentication();
_

Authorizedエンドポイントに移動すると、結果は_302 Found_になります。これは、おそらくログインエンドポイント(作成したことはない)にリダイレクトされているためです。リダイレクトを防ぎ、トークンが提供されていない場合にAPIにトークンを期待させ、_401_を返すようにするにはどうすればよいですか?

6
Mikeyg36

後世のための私の究極のアプローチを投稿します。

Tratcherが指摘したように、AddGoogleミドルウェアは実際にはJWT認証フロー用ではありません。さらに調査を行った後、私が最終的に望んでいたのは、ここで説明されているものであることに気付きました: https://developers.google.com/identity/sign-in/web/backend-auth

だから私の次の問題は

  1. Googleトークンの検証をGoogleライブラリに委任する必要があるため、標準のdotnet core Jwtauthミドルウェアに依存できなくなりました
  2. そのページの外部クライアントライブラリの1つとしてリストされているC#googleバリデーターはありませんでした。

さらに掘り下げた後、このクラスとメソッドを使用して、JWT検証サポートがC#に追加されたことがわかりました ここGoogle.Apis.Auth.Task<GoogleJsonWebSignature.Payload> ValidateAsync(string jwt, GoogleJsonWebSignature.ValidationSettings validationSettings)

次に、組み込みのJWT検証を置き換える方法を理解する必要がありました。これからSO質問私はアプローチを思いついた: ASP.NET Core JWT Bearer Token Custom Validation

これが私のカスタム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;

        }
    }
}

そしてStartup.cs、デフォルトのJWT検証をクリアし、カスタム検証を追加する必要もありました。

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());
                }

もっと簡単な方法があるかもしれませんが、これは私が着陸した場所であり、うまく機能しているようです!簡単にするためにここから省略した追加の作業がありました。たとえば、ユーザーのDBに、Googleが提供するクレームに一致するユーザーが既に存在するかどうかを確認するため、上記のコードが100%機能しない場合はお詫びします。不注意で何かを削除した可能性があります。

17
Mikeyg36

Google OpenID Connectトークンの検証を処理するために NuGetパッケージ を公開しました。

このパッケージは、 Microsoft.AspNetCore.Authentication.JwtBearer のMicrosoftのJWT検証および認証ハンドラーに依存しており、ホストされたドメインに関する検証がいくつか追加されています。

UseGoogleに単一のパブリック拡張メソッドJwtBearerOptionsが含まれており、他の依存関係なしでGoogle OpenIDConnectトークンを検証するようにハンドラーを構成できます。

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(jwt => jwt.UseGoogle(
        clientId: "<client-id-from-Google-API-console>",
        hostedDomain: "<optional-hosted-domain>"));

ソースを確認したい場合は、それを見つけることができます ここ

12
khellang