Refresh access token with a refresh token acquired through PKCE flow


it is mentioned as the last post of

Per gpadma’s post,
"An example /token request to get new access token using refresh token would be:

curl --location --request POST ‘’ \

–header ‘Accept: application/json’ \

–header ‘Content-Type: application/x-www-form-urlencoded’ \

–data-urlencode 'grant_type=refresh_token’ \

–data-urlencode ‘redirect_uri=http://localhost:8080’ \

–data-urlencode ‘client_id=0oaqfdvdr9Dvz5pUC0h7’ \

–data-urlencode 'code=xxx’ \

–data-urlencode 'code_verifier=xxx’ \

–data-urlencode ‘refresh_token=xxx’

P.S: Today, Okta does not return refresh tokens for SPA apps."

but code can only be obtained through authorization request and it expires in 300 seconds. Does it mean 3rd party apps using PKCE flow need to rerun authorization request to get another code to refresh access token?

In order to get a refresh token, you must first request the “offline_access” scope in your authorize request. Then, when you make the token request, with the authorization code returned back from that request, you will receive an ID Token, Access Token, AND Refresh Token. Only the Authorization Code is short lived at 300 seconds and it is NOT used to refresh tokens.

If you want to get a Refresh token for a SPA, you will need to enable the “Refresh token rotation” feature in your Org (found under Settings → Features if you have high enough admin permissions in your org) and enable “Refresh token” as an allowed grant for your specific application. More details here: Refresh token rotation | Okta Developer

Hi, Andrea,

Thank you for the reply. My question is NOT about how to get refresh token in PKCE flow.
I want to know how to refresh access tokens using the refresh token acquired with a PKCE client/api key, as it does NOT have a client secret or api key secret.

if I just remove code_verifier field from that token request mentioned above, you can see it still has the code field. That is what my question is, do we need the authorization code in refreshing access token requests

With a refresh token, you can get new tokens for a public app (PKCE auth, without a client secret) by just supplying the client_id in the request body. Ex:

curl --location --request POST '' \
--header 'Accept: application/json' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'scope=offline_access openid' \
--data-urlencode 'refresh_token=REFRESHTOKEN' \
--data-urlencode 'client_id=CLIENTID'

Thank you Andrea. This is helpful,

Do you know when dynamic refresh tokens will be rolled out? I was told it is only available in preview tenants now. They would be great for public apps

If you go to Settings- > Features, do you see the option to enable “Refresh token rotation?”

ah, I saw it and it seems I can enable it. if the Okta tenant does not have preview as part of its domain, that means it is a production tenant, right?

Yup, that’s correct.

Many thanks Andrea for all the kind replies. Very helpful!