簡體   English   中英

從后台刷新 OKTA 訪問令牌

[英]Refreshing OKTA Access Tokens from background

我有 .NET 5.0 Blazor 服務器應用程序和 openiD OKTA 已集成。 我們的訪問令牌將在 1 小時后過期,之后需要刷新它。 我在 UI 中使用 cookie,在后端使用 accesstoken。 我目前為訪問令牌刷新所做的是,在 1 小時后,路由到 controller 操作以手動刷新令牌,如下所示。

正如我所提到的,我使用 cookie 並驗證每次都會觸發的 CookieAuthenticationEvent 中的令牌。 下面是中間件部分配置。

.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, displayName: 

    "epd_local",
                   options =>
                   {
    
                       options.Cookie.Name = "epd_local";
                       options.Cookie.HttpOnly = false;
                       options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
                       options.Cookie.IsEssential = true;
    
    
                       options.Events = new CookieAuthenticationEvents
                       {
                           // this event is fired everytime the cookie has been validated by the cookie middleware,
                           // so basically during every authenticated request
                           // the decryption of the cookie has already happened so we have access to the user claims
                           // and cookie properties - expiration, etc..
                           OnValidatePrincipal = context =>
                           {

                          //HERE VALIDATING TOKEN

經過上述驗證,如果失敗,路由到下面的端點。

public IActionResult Refresh([FromQuery] string returnUrl)
        {
            var authProps = new AuthenticationProperties
            {
                IsPersistent = true,
                ExpiresUtc = <<new time>>,
                RedirectUri = returnUrl ?? GlobalVariables.OktaCallBackURI // Url.Content("~")
            };

            return Challenge(authProps);
        }

這里的問題是這種方法會刷新屏幕並且會丟失當時添加的條目。 有沒有更好的方法在不影響屏幕的情況下在后台刷新訪問令牌? 身份驗證后,我也獲得了刷新令牌和訪問令牌,但不確定這對這里有何幫助?

我通過在啟動 class 中注冊 OpenId 事件來改進實現。在事件處理程序 OnTokenValidated 中,要設置的主要屬性是context.Properties.AllowRefresh = true 設置此屬性后令牌自動刷新,無需手動路由。

options.Events = new OpenIdConnectEvents
                    {
                        // this makes signout working
                        OnRedirectToIdentityProviderForSignOut = OnRedirectToIdentityProviderForSignOut,
                        OnRedirectToIdentityProvider = OnRedirectToIdentityProvider,
                        OnRemoteSignOut = context =>
                    {

                        context.Response.Redirect("GlobalVariables.OktaCallBackURI +/logout");
                        context.HandleResponse();
                        return Task.CompletedTask;
                    },
                        OnRemoteFailure = context =>
                        {

                        
                            context.HandleResponse();
                            return Task.CompletedTask;

                        },
                        OnAuthenticationFailed = context =>
                        {

                            context.HandleResponse();
                            return Task.CompletedTask;
                        },
                        OnAccessDenied = context =>
                        {

                            
                            context.HandleResponse();
                            return Task.CompletedTask;
                        },
                        OnTokenValidated = context =>
                        {
                                        
                            try
                            {
                                if (context is not null && context.Principal is not null && context.Principal.Identity is not null)
                                {
                                    var identity = (ClaimsIdentity)context.Principal.Identity;
                                    List<Claim> addToken = new();
                                    if (context?.TokenEndpointResponse is not null && context?.TokenEndpointResponse?.AccessToken is not null)
                                    {
                                        addToken.Add(new Claim("access_token", context?.TokenEndpointResponse?.AccessToken));
                                    }
                                    if (context?.TokenEndpointResponse is not null && context?.TokenEndpointResponse?.RefreshToken is not null)
                                    {
                                        addToken.Add(new Claim("refresh_token", context?.TokenEndpointResponse?.RefreshToken));
                                    }

                                    if (addToken.Count > 0)
                                    {
                                        identity.AddClaims(addToken);
                                    }
                                    // so that we don't issue a session cookie but one with a fixed expiration
                                    context.Properties.IsPersistent = true;
                                    context.Properties.AllowRefresh = true;

                                    // align expiration of the cookie with expiration of the
                                
                                    var accessToken = new JwtSecurityToken(context.TokenEndpointResponse.AccessToken);
                                    
                                }
                                else
                                {
                                    //hk todo 
                                    //redirect
                                }
                            }
                            catch
                            {

                            }

                            return Task.CompletedTask;
                        },
                        OnTicketReceived = context =>
                        {
                            // If your authentication logic is based on users then add your logic here
                            return Task.CompletedTask;
                        },

                        //HK save for later
                        OnSignedOutCallbackRedirect = context =>
                        {
                            context.Response.Redirect("~/");
                            context.HandleResponse();

                            return Task.CompletedTask;
                        },
                        OnUserInformationReceived = context =>
                        {
                            //IHttpContextAccessor httpContextAccessor;
                            RegisterUser(context);

                            return Task.CompletedTask;
                        },
                    };

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM