ASP.NET Core 中的 AddOpenIdConnect 和刷新令牌
我已添加
AddOpenIdConnect到ConfigureServices我的 ASP.NET Core 3.1 Razor 應用程序的方法中。在令牌過期之前它工作得很好,然後我從 IDP 收到 401 響應。我看到了一個範例,該範例顯示了一種手動連接刷新令牌的方法。
但我很猶豫要不要這樣做。微軟的人似乎不太可能沒有考慮刷新令牌。
ASP.NET Core 3.1 是否有辦法讓刷新令牌自動更新訪問令牌?
這是我想出的。由於我找不到太多關於如何在 ASP.NET Core 中使用 cookie 刷新令牌的範例,所以我想我會在這裡發布。(我在問題中連結的那個有問題。)
這只是我試圖讓這個工作。它尚未在任何生產環境中使用。此程式碼在
ConfigureServices方法中。services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.Events = new CookieAuthenticationEvents { // After the auth cookie has been validated, this event is called. // In it we see if the access token is close to expiring. If it is // then we use the refresh token to get a new access token and save them. // If the refresh token does not work for some reason then we redirect to // the login screen. OnValidatePrincipal = async cookieCtx => { var now = DateTimeOffset.UtcNow; var expiresAt = cookieCtx.Properties.GetTokenValue("expires_at"); var accessTokenExpiration = DateTimeOffset.Parse(expiresAt); var timeRemaining = accessTokenExpiration.Subtract(now); // TODO: Get this from configuration with a fall back value. var refreshThresholdMinutes = 5; var refreshThreshold = TimeSpan.FromMinutes(refreshThresholdMinutes); if (timeRemaining < refreshThreshold) { var refreshToken = cookieCtx.Properties.GetTokenValue("refresh_token"); // TODO: Get this HttpClient from a factory var response = await new HttpClient().RequestRefreshTokenAsync(new RefreshTokenRequest { Address = tokenUrl, ClientId = clientId, ClientSecret = clientSecret, RefreshToken = refreshToken }); if (!response.IsError) { var expiresInSeconds = response.ExpiresIn; var updatedExpiresAt = DateTimeOffset.UtcNow.AddSeconds(expiresInSeconds); cookieCtx.Properties.UpdateTokenValue("expires_at", updatedExpiresAt.ToString()); cookieCtx.Properties.UpdateTokenValue("access_token", response.AccessToken); cookieCtx.Properties.UpdateTokenValue("refresh_token", response.RefreshToken); // Indicate to the cookie middleware that the cookie should be remade (since we have updated it) cookieCtx.ShouldRenew = true; } else { cookieCtx.RejectPrincipal(); await cookieCtx.HttpContext.SignOutAsync(); } } } }; }) .AddOpenIdConnect(options => { options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.Authority = oidcDiscoveryUrl; options.ClientId = clientId; options.ClientSecret = clientSecret; options.RequireHttpsMetadata = true; options.ResponseType = OidcConstants.ResponseTypes.Code; options.UsePkce = true; // This scope allows us to get roles in the service. options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("offline_access"); // This aligns the life of the cookie with the life of the token. // Note this is not the actual expiration of the cookie as seen by the browser. // It is an internal value stored in "expires_at". options.UseTokenLifetime = false; options.SaveTokens = true; });這段程式碼有兩部分:
AddOpenIdConnect:這部分程式碼為應用程序設置 OIDC。這裡的關鍵設置是:
SignInScheme:這讓 ASP.NET Core 知道您想要使用 cookie 來儲存您的身份驗證資訊。
UseTokenLifetime:據我了解,這會將 cookie 中的內部“expires_at”值設置為訪問令牌的生命週期。(不是實際的 cookie 過期,它停留在會話級別。)
SaveTokens:據我了解,這就是導致令牌保存在 cookie 中的原因。
OnValidatePrincipal: 當 cookie 被驗證時,這個部分被呼叫。在本節中,我們檢查訪問令牌是否接近或過期。如果是,那麼它會被刷新並將更新的值儲存在 cookie 中。如果無法刷新令牌,則使用者將被重定向到登錄螢幕。程式碼使用必須來自配置文件的這些值:
clientId:OAuth2 客戶端 ID。也稱為客戶端密鑰、消費者密鑰等。
clientSecret:OAuth2 客戶端密碼。也稱為消費者秘密等。
oidcDiscoveryUrl: 您的 IDP 的知名配置文件的 URL 的基本部分。如果您的 Well Known Configuration 文件位於,https://youridp.domain.com/oauth2/oidcdiscovery/.well-known/openid-configuration那麼該值將是https://youridp.domain.com/oauth2/oidcdiscovery.
tokenUrl: 指向您的 IDP 令牌端點的 URL。例如:https:/youridp.domain.com/oauth2/token
refreshThresholdMinutes:如果您等到訪問令牌即將到期,那麼您將面臨依賴訪問令牌的呼叫失敗的風險。(如果距離過期還有 5 毫秒,那麼它可能會過期,並且在您有機會刷新它之前呼叫失敗。)此設置是在過期前的分鐘數,您希望認為訪問令牌已準備好刷新。我是 ASP.NET Core 的新手。因此,我不能 100% 確定這些設置是否符合我的想法。這只是一些對我有用的程式碼,我想我會分享它。它可能適合您,也可能不適合您。