从后台刷新 OKTA 访问令牌

问题描述 投票:0回答:1

我有 .NET 5.0 Blazor 服务器应用程序,并且 openiD OKTA 已集成。我们的访问令牌将在 1 小时后过期,之后需要刷新。我在 UI 中使用 cookie 并在后端使用 accesstoken。我目前正在执行的访问令牌刷新操作是,1 小时后,路由到控制器操作以手动刷新令牌,如下所示。

正如我所提到的,我使用 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);
        }

这里的问题是,这种方法会刷新屏幕,并且会丢失当时添加的条目。有没有更好的方法可以在后台刷新访问令牌而不影响屏幕?身份验证后,我还获得了刷新令牌以及访问令牌,但不确定这在这里有何帮助?

asp.net-core blazor-server-side .net-5 okta refresh-token
1个回答
1
投票

我通过在启动类中注册 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;
    },
};
© www.soinside.com 2019 - 2024. All rights reserved.