Question

ErrTokenInvalid during access token exchange request

  • 15 November 2021
  • 15 replies
  • 392 views

I am sadly struggling to get past the initial steps of Oauth2 and cannot find any documentation about this error.

  1. Authenticating using my personal token works like a charm
  2. Getting an application’s temporary token works fine 
  3. Getting an application’s refresh token fails

     

Here are the steps followed:

  1. call https://api.typeform.com/oauth/authorize?state=xyz789&client_id=********&redirect_uri=********&scope=offline+forms:read manually in a browser
  2. grant access by clicking “Accept”, 

     

  3. Copy the code from the URL following the redirection

  4. Request a token using the code from step 3 but fails:

 

If I repeat the same steps above and remove the offline scope it works fine.

What am I doing wrong … ?


15 replies

Userlevel 7
Badge +5

Hi @davidb huh, that’s interesting. Just to make sure I’m reading this right, if you remove the offline scope, you are able to receive a refresh token?

@mathio do you happen to know anything about this? 

Userlevel 7
Badge +5

Sorry I dont have much experience with OAuth, but maybe @picsoung might.

Hi @davidb huh, that’s interesting. Just to make sure I’m reading this right, if you remove the offline scope, you are able to receive a refresh token?

@mathio do you happen to know anything about this? 

Hi @Liz thank you for your reply.

Removing the offline scope works absolutely fine in giving me a temporary code (as expected), but I am trying to automate my connection to the API and therefore need a refresh token approach.

My understanding from the documentation is that you have to:

  1. initially grant the application access manually through the browser using the offline scope
  2. hit https://api.typeform.com/oauth/token (grant_type=authorization_code) to get a refresh_token once
  3. subsequently hit https://api.typeform.com/oauth/token again (grant_type=refresh_token) from my scripts every time I need a new token (and therefore remove the manual operations)

If my understanding is correct, then only step 1 is working, step 2 fails with error code ErrTokenInvalid  which is not documented.

Thanks for your help

David

Userlevel 7
Badge +5

Hi @davidb I asked our tech support team about this, and they mentioned that you shouldn’t need to use the offline scope to get this to work. Is there any particular reason you’re hoping to use this scope? 

@Liz Hi there, I’m struggling with the same issue, I can’t get a Refresh token when I add the ‘Offline’ scope. Getting the following “Forbidden: this kind of access tokens cannot have refresh tokens”.

Userlevel 7
Badge +5

Hi @Guyf Thanks for stopping by! Could you share the call you’re making? 

Userlevel 7
Badge +5

@Guyf If you want to refresh a token, you first need to have the offline scope enabled on the initial oauth flow.

@Liz @picsoung I’m calling the oauth call first:

 https://api.typeform.com/oauth/authorize?client_id=D8EeDEffCKB4KmSyD3FZdZrsTd1MFQUtmmexUUK5Uxid&redirect_uri=http%3A%2F%2Flocalhost:4200%2Fintegrations%2FoauthCallback&scope=offline+forms:write+forms:write
Then I get the code back and pass it to the token endpoint:
https://api.typeform.com/oauth/token with the client_id, client_secret, grant_type = authorization_code, redirect_uri same as the request, and code I got from the response.

The response I get :

{

"code": "bad_request",

"description": "Bad Request: bad request: {\"code\":\"FORBIDDEN\",\"description\":\"Forbidden: this kind of access tokens cannot have refresh tokens\"}\n",

"help": "https://developers.typeform.com/get-started/authentication/"

}

 

Did anyone figure this out? I’m having the exact same issue, and can’t find any documentation to help me.

Userlevel 7
Badge +5

Hi @JHicks Do you have the offline scope enabled? 

I do, my code looks like:

const SCOPE = ["offline", "responses:read", "workspaces:read", "forms:read"];

export const Typeform = OAuthWeb(
"typeform",
{
getAuthUrl: async () => {
return (
`https://api.typeform.com/oauth/authorize?client_id=${encodeURIComponent(CLIENT_ID)}` +
`&redirect_uri=${REDIRECT_URI}` +
`&scope=${SCOPE.join("+")}`
);
},

getAccessToken: async (authCode: string) => {
const urlencoded = new URLSearchParams();
urlencoded.append("grant_type", "authorization_code");
urlencoded.append("code", authCode);
urlencoded.append("client_id", CLIENT_ID);
urlencoded.append("client_secret", CLIENT_SECRET);
urlencoded.append("redirect_uri", REDIRECT_URI);

// I get the error here
const req = await fetch("https://api.typeform.com/oauth/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: urlencoded.toString(),
});

...

const { access_token, refresh_token } = await req.json();

return { accessToken: access_token, refreshToken: refresh_token };
},
}
)

When I remove “offline”, it works (But i don’t get a refresh token). Same as the OP. The typeform oauth dev app I created has the 7 day expiry rule, so thats not the issue.

Weirdly enough, if I create a new oauth dev app with the exact same settings and use that app for the `client_id` and `client_secret` everything also works perfectly. Switching to the new app isn’t ideal, but I figure it could be an acceptable solution for other devs

Hello everyone!

I’m a Typeform engineer, and first sorry for the confusions in the docs, and second, let me try to bring you some clarity here.

@davidb I’m not exactly sure what could be the problem in your case, but assuming that the values that you provide to the endpoints are correct, I suspect that the problem in your case might be that the Authorization Code just expires. It is very short-living, and if the time between steps 2 and 4 is long enough, it’s already not there, and hence you get an error. I’d suggest to try to reduce that delay, and if you still have problems, please reach our to our Support Team so we can look into your case more specifically.

@JHicks for you, I think, the problem is different. In your case you’re trying to get a refresh token, but you have your app configured for the usage of “unlimited” tokens. That is a legacy and not recommended feature, and it conflicts with the refresh mechanism. This is why you’re getting the Forbidden: this kind of access tokens cannot have refresh tokens error. A solution for this case would be to go to your app settings and configure it to use one-week expiration for tokens (see screenshot). Afterwards, you should be able to get the refresh tokens using the offline scope.

Hope this helps!

Also, thank you for your feedback, we’ll try to improve our error messages and documentation about them!

 

 

@denys-tf I appreciate your response.


I don’t believe this is the issue, as the breaking oauth app is set for 1 week expiration. The second oauth app I created to test with the exact same settings did work however.

That’s a strange case @JHicks!
We only have that error message for such cases.
Could you please either contact our Customer Support or send me the client ID of your application in a direct message, so I could check if everything is okay with the app.

Userlevel 7
Badge +5

@JHicks were you able to contact our support team? Let us know if you still need help!

Reply