IdentityServer4 refresh token invalid grant
Asked Answered
S

4

7

I'm having some issues on requesting new refresh tokens in IdentityServer4. Sometime after authentication, I get an Unauthorized response from my API, ok, but when I try to request a new refresh token, I get an invalid_grant from the server. I made sure that I set offline_access, but am still encountering the problem. Here is my code:

My Client in Server Config.cs

new Client
            {
                ClientId = "myclientId",
                ClientName = "MyClient",
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,

                RequireConsent = false,

                ClientSecrets =
                {
                    new Secret("mySecret".Sha256())
                },

                RedirectUris = { "http://localhost:5002/signin-oidc" },
                PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

                AllowOfflineAccess = true,

                UpdateAccessTokenClaimsOnRefresh = true,

                AllowedScopes =
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    IdentityServerConstants.StandardScopes.OfflineAccess,
                    ...
                }
            }

My Startup.cs from MVCclient

app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationScheme = "Cookies",
            AccessDeniedPath = "/Home/Error403"
        });

        app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
        {
            AuthenticationScheme = "oidc",
            SignInScheme = "Cookies",

            Authority = Configuration["Identity.Url"],
            RequireHttpsMetadata = false,

            ClientId = Configuration["ClientId"],
            ClientSecret = Configuration["ClientSecret"],

            ResponseType = "code id_token",

            Scope = { "openid profile offline_access" },

            GetClaimsFromUserInfoEndpoint = true,
            SaveTokens = true,

        });

Here I'm getting invalid_grant

var disco = await DiscoveryClient.GetAsync(Configuration["Identity.Url"]);
        if (disco.IsError) throw new Exception(disco.Error);

        var tokenClient = new TokenClient(disco.TokenEndpoint, Configuration["ClientId"],
            Configuration["ClientSecret"]);
        var rt = await HttpContext.Authentication.GetTokenAsync("refresh_token");
        var tokenResult = await tokenClient.RequestRefreshTokenAsync(rt);

tokenResult is assigned invalid_grant. Am I missing something?

Starvation answered 19/7, 2017 at 18:2 Comment(0)
C
3

I found that this happens when IdentityServer is put to sleep by IIS. We had a dev server which did not have a "Keep alive / awake" policy, so if left for some time (20 minutes I think) the site is put to sleep... When used again, this screwed up any attempt at using refresh tokens, but strangely instead of claiming I had an invalid refresh token, got an error of "Invalid Grand Type" in the response.

Caltanissetta answered 2/7, 2020 at 22:32 Comment(0)
C
2

try changing this line in mvc client config

Scope = { "openid", "profile", "offline_access" }

note quotes around each scope

Collimate answered 19/7, 2017 at 18:11 Comment(6)
everything else looks ok to me... check logs on the auth server. this has solved number of issues for me. Try to run your auth server as a console app not IIS Express if you are using visual studio...hope it helps!Collimate
When my access/refresh tokens are valid yet, RequestRefreshTokenAsync() works fine. But when it's expired, i get invalid_grant. Is that so? If so, then I have to renew before expiration, right?Starvation
well you can request for RequestRefreshTokenAsync() if your access token has been expired or before it expires, but to get new access token your refresh token should be valid (not expired). But if your refresh token is expired as well then you will get the error -- You can check on the auth server, it will log the fail as well that it could not validate the refresh token. So its the refresh token expiry that is giving you error. Make sure you renew your tokens before refresh token expires ( you can have sliding refresh tokens)Collimate
I still having the same problem. After sometime, all my access tokens requesteds that are valid or expired turns in "The signature key was not found." and my request get invalid_grant. In localhost this never happens. Can be something in my host server? Can be something with SecurityTokenSignatureKey? Can be something with SSL?Starvation
Man, I found the problem!! It's the AddTemporarySigningCredential() in my identity server. After my pool recycle, all my tokens get invalid. Thanks!Starvation
@RafaelTrojack add a new answer pointing that out, this way you can help out other users facing the same problem with an easier solution.Lagomorph
E
1

I fixed this issue by editing these lines

 AllowedGrantTypes = { "authorization_code", "refresh_token" },
 RefreshTokenUsage = TokenUsage.OneTimeOnly,
 RefreshTokenExpiration = TokenExpiration.Sliding,
 SlidingRefreshTokenLifetime = 2592000 * 2

Your identity server also allows the client to refresh the token. Refresh token will expire after 60 days. Every time refreshing the access token also updates the refresh token to a new value.

You must log out and log in to get the new refresh token, then you can use your new refresh token to refresh the access token later.

Reference: https://identityserver4.readthedocs.io/en/latest/topics/refresh_tokens.html#additional-client-settings

Equinox answered 16/9, 2022 at 3:20 Comment(0)
T
0

I've just faced with the same error. I noticed that the error occured when I try to refrsh access token within short period of time, ex. twice per second. Solution was to increase RefreshTokenUssage parameter in database (table dbo.Clients) for client up to 10 (original value is 1).

Trigraph answered 24/12, 2020 at 19:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.