Base solution for your next web application
Open Closed

Handling refreshing token in client #12240


User avatar
0
hongbing.wang created

Hi,

ASP.NET Zero API: v13.3.0 | Angular client: v13.3.0

We want to shorten AccessTokenExipration to 15 minutes and RefreshTokenExpiration to 7 days.

The API Task<RefreshTokenResult> RefreshToken(string refreshToken) works fine in Swagger UI. However, there are following issues with the Angular client.

When the access token expires, if customer tries to open any page that is not on the main tree, it gives an internal error, instead of re-routing to the login page.

For example:

Go to Departments page and wait 15 minutes

Go to Custom fields page and get Internal error

Go to Controllers page and get Internal error

Go to Alarms page and now it redirects you to the login page

More importantly, RefreshToken is not called or not working in the client.

Has the RefreshToken() been fully implemented in the client? If not, please advise the method for the implementation.

We are aware that there is "this._tokenAuthService.refreshToken(token)" in tryAuthWithRefreshToken() in "src\account\auth\zero-refresh-token.service.ts". this._refreshTokenService.tryAuthWithRefreshToken() is called by canActivateInternal in "src\app\shared\common\auth\auth-route-guard.ts". But we need further assistance.


7 Answer(s)
  • User Avatar
    0
    m.aliozkaya created
    Support Team

    Hi @hongbing.wang,

    We will check refresh token on Angular soon as possible.

  • User Avatar
    0
    hongbing.wang created

    Hi m.aliozkaya,

    Client uses _tokenService to getRefreshToken(). In src\assets\abp-web-resources\abp.js, abp.auth.getRefreshToken = function () { return abp.utils.getCookieValue(abp.auth.refreshTokenCookieName); } Please note that our app has http-only cookies enforced. This means the following methods in src\account\auth\zero-refresh-token.service.ts will fail. this._tokenService.getRefreshToken() this._tokenService.setToken(tokenResult.accessToken, tokenExpireDate); this._tokenService.setRefreshToken(tokenResult.refreshToken);

    We tried adding a periodic checkAndRefreshToken() in zero-refresh-token.service.ts without success due to the http-only cookies enforcement.

    We also tried to set the new tokens on server side when client calls the API RefreshToken(string refreshToken) in TokenAuthController.

                var cookieOptions = new CookieOptions
                {
                    Secure = true,
                    HttpOnly = true,
                    SameSite = SameSiteMode.None,
                };
    
                Response.Cookies.Append("Abp.AuthToken", accessToken, cookieOptions);
                Response.Cookies.Append("Abp.AuthRefreshToken", newRrefreshToken.token, cookieOptions);
    

    In theory, server can get the existing refresh token by using Request.Cookies["Abp.AuthRefreshToken'] if the client and server on the same domain with the same CookieOptions. However, we didn't get the refresh token in this way. It's always been null. What's the correct way to do this on server?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @hongbing.wang

    Are you able to see the request and response for retrieving the access token using refresh token ? If so, could you share them with us ?

  • User Avatar
    0
    hongbing.wang created

    Hi ismcagdas,

    refreshToken: { "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "2", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "[email protected]", "AspNet.Identity.SecurityStamp": "7HNZKYBQ65VMM5PMYEH3XS2P6754ZH5H", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Admin", "http://www.aspnetboilerplate.com/identity/claims/tenantId": "1", "WMSProUId": "2", "_g1362": "259fc6c0-d904-4c1d-9b9e-6de3bd439d89", "sub": "2", "jti": "d87e21c9-9dd4-4b00-be77-fde6da1df4df", "iat": 1732748386, "token_validity_key": "4c760f75-f2b5-44dd-9da5-8cdc7ea91cc2", "user_identifier": "2@1", "token_type": "1", "nbf": 1732748386, "exp": 1764284386, "iss": "umsplus", "aud": "umsplus" }

    After RefreshToken, new accessToken: { "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "2", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "[email protected]", "AspNet.Identity.SecurityStamp": "LFBR6FGRUIQKJUYYGP6EBXZQPCYWK4ZP", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Admin", "http://www.aspnetboilerplate.com/identity/claims/tenantId": "1", "WMSProUId": "2", "_g1362": "4c6d908b-fc68-43fe-bf73-7bb72a2c7dcd", "sub": "2", "jti": "f4949ced-8889-4cb2-8bb0-fc012a4cec3c", "iat": 1732749456, "token_validity_key": "c234f015-766c-4d8c-b8e1-961d2f2837ad", "user_identifier": "2@1", "token_type": "0", "refresh_token_validity_key": "dadcf875-58fd-4ffe-ad97-52b55b3f787e", "nbf": 1732749456, "exp": 1732749576, "iss": "umsplus", "aud": "umsplus" }

    newRefreshToken: { "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "2", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "[email protected]", "AspNet.Identity.SecurityStamp": "LFBR6FGRUIQKJUYYGP6EBXZQPCYWK4ZP", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "Admin", "http://www.aspnetboilerplate.com/identity/claims/tenantId": "1", "WMSProUId": "2", "_g1362": "4c6d908b-fc68-43fe-bf73-7bb72a2c7dcd", "sub": "2", "jti": "13c1a619-5187-4f73-970a-a4ce46d91251", "iat": 1732749456, "token_validity_key": "dadcf875-58fd-4ffe-ad97-52b55b3f787e", "user_identifier": "2@1", "token_type": "1", "nbf": 1732749456, "exp": 1732749696, "iss": "umsplus", "aud": "umsplus" }

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @hongbing.wang

    Thanks. Is it possible for us to access your project and test this case using your latest source code ?

  • User Avatar
    0
    hongbing.wang created

    Hi ismcagdas,

    This issue is only related to three files. I have shared the files with you at https://drive.google.com/file/d/1vwPQA0HiYl-zEP5o94HlRorx36AjkbJQ/view?usp=sharing

    \webapi\src\umsplus.Application.Shared\AppConsts.cs: public static TimeSpan AccessTokenExpiration = TimeSpan.FromMinutes(15); public static TimeSpan RefreshTokenExpiration = TimeSpan.FromDays(7);

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    I think you are missing AddRefreshTokenCookie method explained here https://aspnetzero.com/blog/http-only-cookies-in-asp.net-zero-angular-ui. Since you are using HTTP-Only in your app, server must write the RefreshToken to cookies. This cookie will be sent to server in every request automatically.

    You can follow the blog post I shared above, make necessary changes and see if it works.