从IdentitySever4获取刷新令牌

我有一个Blazor Web应用程序,它连接到其他Identity Server 4服务器。我可以使登录名正常工作,并将访问令牌传递回Blazor。但是,当令牌过期时,我不知道如何去获取新的访问令牌?我应该获取刷新令牌,然后获取访问令牌吗?我对这一切的工作方式感到困惑。

blazor码

services.AddAuthentication(options =>
         {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = AzureADDefaults.AuthenticationScheme;
         })
         .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
         .AddOpenIdConnect(AzureADDefaults.AuthenticationScheme,options =>
         {
            options.Authority = "https://localhost:44382";
            options.RequireHttpsMetadata = true;

            options.ClientId = "client";
            options.ClientSecret = "secret";
            options.ResponseType = "code id_token token";
            options.SaveTokens = true;

            options.Scope.Add("IdentityServerApi");
            options.Scope.Add("openid");
            options.Scope.Add("profile");
            options.Scope.Add("email");
            options.Scope.Add("roles");
            options.Scope.Add("offline_access");
         });

IdentityServer4设置

...
        new Client
         {
            ClientId = "client",ClientSecrets = { new Secret("secret".Sha256()) },AllowedGrantTypes = GrantTypes.Hybrid,AllowaccessTokensViaBrowser = true,RequireclientSecret = true,RequireConsent = false,Redirecturis = { "https://localhost:44370/signin-oidc" },PostLogoutRedirecturis = { "https://localhost:44370/signout-callback-oidc" },AllowedScopes = { "openid","profile","email","roles","offline_access",IdentityServerConstants.LocalApi.ScopeName
            },AllowedCorsOrigins = { "https://localhost:44370" },AlwaysSendClientClaims = true,AlwaysIncludeUserClaimsInIdToken = true,AllowOfflineaccess = true,accessTokenLifetime = 1,//testing
            UpdateaccessTokenClaimsOnRefresh = true
         },...

更新:

我已将客户端和服务器的代码更新为offline_access(感谢下面的更新)。我的下一个问题是,由于访问令牌过期而被拒绝后,如何在Blazor中注入刷新令牌的请求?

我有Blazor应用程序回调API(用于验证访问令牌)。

   public class APIClient : IAPIClient
   {
      private readonly HttpClient _httpClient;

      //add the bearer token to the APIClient when the client is used
      public APIClient(IHttpContextaccessor httpaccessor,HttpClient client,IConfiguration configuration)
      {
         var accessToken = httpaccessor.HttpContext.GetTokenAsync("access_token").Result;
         client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",accessToken);
         client.DefaultRequestVersion = new Version(2,0);
         client.BaseAddress = new Uri(configuration["Api_Location"]);
         _httpClient = client;
         _logger = logger;
      }

我需要在API调用中添加哪些内容以进行验证?

kangjian1207 回答:从IdentitySever4获取刷新令牌

是的,您还应该获取刷新令牌,以保持获取新的访问令牌。要从IdentityServer获取刷新令牌,您需要在客户端的“ AllowedScopes”属性中添加“ offline_access”范围。您还需要将客户端上的“ AllowOfflineAccess”属性设置为true。

此后,您需要在客户端发送的范围中包括“ offline_access”,并且您应该在响应中收到刷新令牌。

要使用刷新令牌,请使用您为代码交换发送的所有内容向令牌端点发送请求,除了将“ code”参数替换为“ refresh_token”并将“ grant_type”的值从“ code”更改为“ refresh_token” '。 IdentityServer4对此请求的响应应包含一个id_token,一个access_token和一个新的refresh_token。

,

我想我已经找到了答案(鉴于兰迪的推动)。我做了this post熟悉的事情,在我的APIClient中创建了通用方法。

      public async Task<T> SendAsync<T>(HttpRequestMessage requestMessage)
      {
         var response = await _httpClient.SendAsync(requestMessage);
         //test for 403 and actual bearer token in initial request
         if (response.StatusCode == HttpStatusCode.Unauthorized &&
             requestMessage.Headers.Where(c => c.Key == "Authorization")
                     .Select(c => c.Value)
                     .Any(c => c.Any(p => p.StartsWith("Bearer"))))
         {
            var pairs = new List<KeyValuePair<string,string>>
            {
                new KeyValuePair<string,string>("grant_type","refresh_token"),new KeyValuePair<string,string>("refresh_token",_httpAccessor.HttpContext.GetTokenAsync("refresh_token").Result),string>("client_id","someclient"),string>("client_secret","*****")
            };

            //retry do to token request
            using (var refreshResponse = await _httpClient.SendAsync(
                new HttpRequestMessage(HttpMethod.Post,new Uri(_authLocation + "connect/token"))
                {
                   Content = new FormUrlEncodedContent(pairs)})
               )
            {
               var rawResponse = await refreshResponse.Content.ReadAsStringAsync();
               var x = Newtonsoft.Json.JsonConvert.DeserializeObject<Data.Models.Token>(rawResponse);
               var info = await _httpAccessor.HttpContext.AuthenticateAsync("Cookies");

               info.Properties.UpdateTokenValue("refresh_token",x.Refresh_Token);
               info.Properties.UpdateTokenValue("access_token",x.Access_Token);
               _httpClient.DefaultRequestHeaders.Clear();
               _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",x.Access_Token);

               //retry actual request with new tokens
               response = await _httpClient.SendAsync(new HttpRequestMessage(requestMessage.Method,requestMessage.RequestUri));

            }
         }
         if (typeof(T).Equals(typeof(HttpResponseMessage)))
            return (T)Convert.ChangeType(response,typeof(T));
         else
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync());
      }

我不喜欢我必须打电话给AuthenticateAsync。但是,这似乎是我发现可以访问UpdateTokenValue方法以删除然后重新添加新访问令牌的方法。

本文链接:https://www.f2er.com/3135822.html

大家都在问