アクセストークンを保存するには?(Oauth 2、認証コードフロー)質問する

アクセストークンを保存するには?(Oauth 2、認証コードフロー)質問する

私が理解している限りでは、認証コード フローの目的は、認証コードをアクセス トークンと交換することです。この交換は、ページを提供するサーバーと認証サーバーの間で行われるため、実際のアクセス トークンはクライアント ユーザーに公開されません。

ページ サーバーは、アクセス トークンを取得したら、それをどのように保存すればよいでしょうか。私は、次のコード部分がある Pluralsight の例から学びました。

    public static HttpClient GetClient()
    {
        HttpClient client = new HttpClient();
        var accessToken = RequestAccessTokenAuthorizationCode();
        client.SetBearerToken(accessToken);

        client.BaseAddress = new Uri(IdentityConstants.API);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

        return client;
    }

    private static string RequestAccessTokenAuthorizationCode()
    {
        // did we store the token before?
        var cookie = HttpContext.Current.Request.Cookies.Get("ClientMVCCookie.AuthCode");
        if (cookie != null && cookie["access_token"] != null && !string.IsNullOrEmpty(cookie["access_token"]))
        {
            return cookie["access_token"];
        }

        // no token found - request one

        // we'll pass through the URI we want to return to as state
        var state = HttpContext.Current.Request.Url.OriginalString;

        var authorizeRequest = new IdentityModel.Client.AuthorizeRequest(
            IdentityConstants.AuthEndoint);

        var url = authorizeRequest.CreateAuthorizeUrl(IdentityConstants.MVCClientSecret, "code", "management secret",
            IdentityConstants.MVCAuthCodeCallback, state);

        HttpContext.Current.Response.Redirect(url);

        return null;
    }
}

これにより、各リクエストで Cookie にアクセス トークンが保存されているかどうかが確認されます。保存されていない場合はフローが開始されます。コールバックは次のようになります。

public class CallbackController : Controller
{
    // GET: STSCallback
    public async Task<ActionResult> Index()
    {
        // get the authorization code from the query string
        var authCode = Request.QueryString["code"];

        // with the auth code, we can request an access token.
        var client = new TokenClient(
            IdentityConstants.TokenEndoint,
            "mvc_client_auth_code",
             IdentityConstants.MVCClientSecretAuthCode);

        var tokenResponse = await client.RequestAuthorizationCodeAsync(
            authCode,
            IdentityConstants.MVCAuthCodeCallback);

        // we save the token in a cookie for use later on
        var cookie = Response.Cookies["ClientMVCCookie.AuthCode"];
        cookie.Expires = DateTime.Now.AddMinutes(1);
        cookie["access_token"] = tokenResponse.AccessToken;

        // get the state (uri to return to)
        var state = Request.QueryString["state"];

        // redirect to the URI saved in state
        return Redirect(state);
    }
}

アクセス トークンを Cookie に保存すると、認証コード フローの目的全体が無効になりませんか? Cookie はクライアント ブラウザーに送信され、クライアントに公開されますか? 何か見落としているのでしょうか? これがトークンを保存する正しい方法でない場合、どのように保存すればよいのでしょうか?

ベストアンサー1

OAuth の用語では、クライアントはリソース サーバーにリクエストを送信するコンポーネントです。この場合、クライアントは Web アプリケーションのサーバー (ブラウザーではありません) です。

したがって、アクセス トークンは Web アプリケーション サーバーにのみ保存する必要があります。ブラウザーはリソース サーバーに直接リクエストを送信しないため、アクセス トークンはブラウザーに公開されるべきではなく、また公開する必要もありません。代わりにブラウザーは Web アプリケーション サーバーと通信し、Web アプリケーション サーバーはアクセス トークンを使用してリソース サーバーにリクエストを送信します。

ブラウザが Web アプリケーション サーバーで自身を認証する方法は、OAuth 2.0 とは関係ありません。たとえば、通常のセッション クッキーの場合、Web アプリケーション サーバーは各セッションまたは各ユーザーをアクセス トークンに関連付ける可能性があります。

認証コードをアクセス トークンと交換するトークン要求は、Web アプリケーション サーバーによって実行され、Web アプリケーション サーバーは認可サーバーを使用して自身を認証する必要があります (共有 などを使用client_secret)。

承認コード フローにより、クライアントの認証が確実に行われるため、正当なクライアントを装った悪意のあるクライアントから保護されます。すべての Web アプリケーション クライアントにサーバー コンポーネントがあるわけではなく、リソース サーバーへの要求がブラウザーの JavaScript コードによって直接行われる場合もあります。このような状況では、ブラウザーがクライアントとなり、アクセス トークンはブラウザーによって保存される必要があります (JavaScript 変数、ローカル ストレージ、または Cookie)。この場合、クライアントを認証することはできません (ただし、TLS を使用し、サーバーを登録されたエンドポイント URL にのみリダイレクトすることで、十分なセキュリティを実現できます)。

OAuth 2.0 セキュリティに関する推奨資料:https://www.rfc-editor.org/rfc/rfc6819#section-4.3.3(RFC 6819)

おすすめ記事