web-dev-qa-db-ja.com

IdentityServer 4で「refresh_token」を使用する方法

IdentityServer 4で.netコアを使用しています。WebAPIと、API上の安全なエンドポイントにアクセスするMVCアプリがあります。セットアップはIdentityServerクイックスタートと非常によく似ています。

https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/6_AspNetIdentity

access_tokensの有効期限が切れているようです。refresh_tokensの再交渉方法を知りたいのですが。

次のコードを例にとります(クイックスタート here から取得):

public async Task<IActionResult> CallApiUsingUserAccessToken()
    {
        var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");

        var client = new HttpClient();
        client.SetBearerToken(accessToken);
        var content = await client.GetStringAsync("http://localhost:5001/identity");

        ViewBag.Json = JArray.Parse(content).ToString();
        return View("json");
    }

access_tokenが期限切れの場合、401応答で失敗します。 access_tokenを使用してrefresh_tokenを再ネゴシエートするための組み込みメカニズムはありますか?

10
Stephen Ellis

access_tokenを更新するための組み込みシステムはありません。ただし、IdentityModelパッケージを使用して、access_tokenで新しいrefresh_tokenをリクエストできます。

Clientには、IdentityServerでtrueに設定する必要があるプロパティAllowOfflineAccessがあります。これは、暗黙的/クライアント資格情報フローでは機能しません機能しません

  • 保護されたリソースを呼び出す前に、常にaccess_tokenを更新してください
  • 現在のaccess_tokenの有効期限を確認し、access_token(個人設定)を使用して新しいrefresh_tokenを要求することにより、期限切れが近いかどうかを確認します。
  • APIが401広告リクエストを返すのを待ちます。新しいaccess_tokenrefresh_token

このコードの前に、新しいaccess_tokenをリクエストする前に、access_tokenの有効期間を確認したり、このコードをサービスにラップしたりできます。

var discoveryResponse = await DiscoveryClient.GetAsync("IdentityServer url");
if (discoveryResponse.IsError)
{
    throw new Exception(discoveryResponse.Error);
}

var tokenClient = new TokenClient(discoveryResponse.TokenEndpoint, "ClientId", "ClientSecret");
// This will request a new access_token and a new refresh token.
var tokenResponse = await tokenClient.RequestRefreshTokenAsync(await httpContext.Authentication.GetTokenAsync("refresh_token"));

if (tokenResponse.IsError)
{
    // Handle error.
}

var oldIdToken = await httpContext.Authentication.GetTokenAsync("id_token");

var tokens = new List<AuthenticationToken>
{
    new AuthenticationToken
    {
        Name = OpenIdConnectParameterNames.IdToken,
        Value = oldIdToken
    },
    new AuthenticationToken
    {
        Name = OpenIdConnectParameterNames.AccessToken,
        Value = tokenResult.AccessToken
    },
    new AuthenticationToken
    {
        Name = OpenIdConnectParameterNames.RefreshToken,
        Value = tokenResult.RefreshToken
    }
};

var expiresAt = DateTime.UtcNow.AddSeconds(tokenResult.ExpiresIn);
tokens.Add(new AuthenticationToken
{
    Name = "expires_at",
    Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
});

// Sign in the user with a new refresh_token and new access_token.
var info = await httpContext.Authentication.GetAuthenticateInfoAsync("Cookies");
info.Properties.StoreTokens(tokens);
await httpContext.Authentication.SignInAsync("Cookies", info.Principal, info.Properties);

から取られ、わずかに変更されました: Source

12
user1336