web-dev-qa-db-ja.com

.NET Coreを使用したFirebase Authentication(JWT)

Firebaseによって行われた認証を処理するシンプルなAPIを開発しています-後でAndroidクライアントで使用するために。

そのため、FirebaseコンソールでFacebookおよびGoogleのサインインメソッドを有効にし、それを使用してログインメソッドをテストできるサンプルhtmlページを作成しました。この次の関数はボタンによって呼び出されます。

function loginFacebook() {
        var provider = new firebase.auth.FacebookAuthProvider();
        var token = "";
        firebase.auth().signInWithPopup(provider).then(function (result) {
            var token = result.credential.accessToken;
            var user = result.user;
            alert("login OK");
            user.getToken().then(function (t) {
                token = t;
                loginAPI();
            });
        }).catch(function (error) {
            var errorCode = error.code;
            var errorMessage = error.message;
            alert(errorCode + " - " + errorMessage);
        });
    }

次に、トークンを使用して、jQueryからの単純なajax呼び出しでAPIに送信します。

function loginAPI()
{
    $.ajax({
        url: "http://localhost:58041/v1/Users/",
        dataType: 'json',
        type: 'GET',
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Accept", "application/json");
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.setRequestHeader("Authorization", "Bearer " + token);
        },
        error: function (ex) {
            console.log(ex.status + " - " + ex.statusText);
        },
        success: function (data) {
            console.log(data);
            return data;
        }
    });
}

次のステップ:APIバックエンド-.NET Coreで作成された。

スタートアップの下で、JwtBearer Auth(パッケージMicrosoft.AspNetCore.Authentication.JwtBearer):

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AutomaticAuthenticate = true,
    IncludeErrorDetails = true,
    Authority = "https://securetoken.google.com/PROJECT-ID",
    TokenValidationParameters = new TokenValidationParameters
    {  
        ValidateIssuer = true,
        ValidIssuer = "https://securetoken.google.com/PROJECT-ID",
        ValidateAudience = true,
        ValidAudience = "PROJECT-ID",
        ValidateLifetime = true,
    },
});

そして、ここにコントローラーコードがあります-[Authorize]属性:

[Authorize]
[Route("v1/[controller]")]
public class UsersController : Controller
{
    private readonly ILogger _logger;
    private readonly UserService _userService;

    public UsersController(ILogger<UsersController> logger, UserService userService)
    {
        _logger = logger;
        _userService = userService;
    }

    [HttpGet]
    public async Task<IList<User>> Get()
    {
        return await _userService.GetAll();
    }
}

APIレスポンスは200 OK(HttpContext.User.Identity.IsAuthenticatedはController内のtrueですが、そうすべきではないと思います。私の問題は、これが安全であることを完全に確信していないことです。

JWTトークンの署名部分をどのようにチェックしていますか? x509またはRS256アルゴリズムに言及しているコードサンプルをたくさん見ましたが、どこに適合しますか? IssuerSigningKeyクラスのTokenDecryptionKeyまたはTokenValidationParametersを使用して、何らかの証明書または秘密キーをチェックするべきではありませんか?私は何が欠けていますか?

問題に関する関連する知識源:

15

FirebaseはRSA256非対称キー暗号システムを使用します。つまり、公開キーと秘密キーがあります。 トークンへの署名は秘密鍵で行われ、トークンの検証は公開鍵で行われます。

次の図は、トークン署名がどのように行われるかを示しています。

enter image description here

サインインして安全なエンドポイントにアクセスする際には、次の手順が必要です。

  1. アプリケーションが起動すると(その後、定期的にも)JwtBearerMiddlewarehttps://securetoken.google.com/my-firebase-project/.well-known/openid-configurationを呼び出し、Googleの現在の公開キーにアクセスできます。公開鍵非対称暗号システムを使用している場合、公開鍵は秘密として保持されませんが、重要なことは公開されています。
  2. クライアントは、Firebaseを介して資格情報を使用してサインインします(これらはクライアント自身の資格情報であり、トークンの署名に使用されるキーとは関係ありません)。
  3. サインインが成功した場合、Firebaseはクライアント用のJWTトークンを作成します。このトークンの重要な部分は、鍵ペアの秘密鍵を使用して署名されていることです。公開キーとは対照的に、秘密キーは公開されることはなく、Googleのインフラストラクチャ内で秘密として保持されます。
  4. クライアントはJWTトークンを受け取ります。
  5. クライアントは、Apiで安全なエンドポイントを呼び出し、Authorizationヘッダーにトークンを入れます。この時点で、パイプラインのJwtBearerMiddlewareはこのトークンをチェックし、有効かどうか(Googleの秘密キーで署名されているかどうか)を確認します。ここで重要なことは、検証を行うために、Apiが秘密キーにアクセスする必要がないことです。そのためには公開鍵のみが必要です。検証後、ミドルウェアはHttpContext.User、およびそれに応じてHttpContext.User.Identity.IsAuthenticatedを取り込みます。

RSA Wikipedia page でこの概念のさらに簡単な説明を見つけることができます。また、 私のブログ投稿 でFirebase + ASP.NETに関する詳細情報を見つけることができます。

18
Mark Vincze

バックエンド側には、あなたのためのトリックを行うNugetパッケージがあります:

インストールパッケージAspNetCore.Firebase.Authentication

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  ILoggerFactory loggerFactory)
{      
app.UseFirebaseAuthentication("https://securetoken.google.com/MYPROJECTNAME", "MYPROJECTNAME");
}

対象者、発行者、署名、妥当性の検証を行います

6
Raphaël

NuGetパケットは、古いASP NET Core 1.x認証メカニズムを使用しています

認証が変更されました: https://docs.Microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x

1
xlogic