Select to view content in your preferred language

OAuth2 authorization code flow not returning refresh_token — mobile users re-prompted for credentials every 30 minutes

280
1
Jump to solution
2 weeks ago
NigelCharman
Occasional Contributor

We have a server-side web application that authenticates users via ArcGIS Online using the OAuth 2.0 authorization code flow. Our backend exchanges the authorization code for an access token, caches it server-side (Azure Functions + Azure Table Storage), and uses it to make feature service calls on behalf of the user. On initial login the flow works correctly.

The problem: Users on mobile browsers (e.g. Chrome on Android) are prompted to re-enter their ArcGIS username and password every ~30 minutes when the access token expires. Desktop browser users do not experience this — when the token expires on desktop, ArcGIS silently re-authenticates via the existing browser session and a new token is issued without the user being prompted.

We believe the difference is that desktop users maintain an active ArcGIS Online browser session (cookie) which allows silent re-authentication, whereas mobile users do not have this persistent session. The correct solution for mobile is therefore refresh tokens, which would allow our backend to silently renew the access token without any browser interaction at all.

What we have implemented: Our backend includes silent token refresh logic using grant_type=refresh_token. We also send expiration=20160 in the authorize URL per the /authorize documentation, which should set a 2-week refresh token lifetime.

The issue: The token exchange response for grant_type=authorization_code does not include a refresh_token field at all. Without it our silent refresh cannot work and mobile users are forced through the full login flow every 30 minutes.

The /token documentation explicitly states:

refresh_token — ONLY returned when grant_type=authorization_code or grant_type=exchange_refresh_token

Our token exchange request:

client_id=...
client_secret=...
grant_type=authorization_code
code=...
redirect_uri=...

The response contains access_token and expires_in (1800 seconds) but no refresh_token.

Our question: Is there an ArcGIS Online organisation-level setting or OAuth application registration setting that controls whether refresh tokens are issued? Our app is registered as "OAuth 2.0 Credentials" (not "Impersonates item owner"). We have not been able to find any setting in the app registration UI that enables refresh tokens.

Any guidance appreciated.

0 Kudos
1 Solution

Accepted Solutions
NigelCharman
Occasional Contributor

SOLVED! We initially thought we weren't receiving a refresh_token at all, but this turned out to be a bug in our own diagnostic tooling. The actual fix was adding expiration=20160 to the /oauth2/authorize URL:

?client_id=...
&response_type=code
&redirect_uri=...
&state=...
&expiration=20160

Per the /authorize documentation, for authorization code grants expiration controls the refresh token lifetime, not the access token (which is always capped at ~30 minutes). Without it, ArcGIS was not issuing a refresh token.

With a refresh token in hand, our backend silently renews the access token on expiry using grant_type=refresh_token, so mobile users are no longer prompted for credentials every 30 minutes.

View solution in original post

0 Kudos
1 Reply
NigelCharman
Occasional Contributor

SOLVED! We initially thought we weren't receiving a refresh_token at all, but this turned out to be a bug in our own diagnostic tooling. The actual fix was adding expiration=20160 to the /oauth2/authorize URL:

?client_id=...
&response_type=code
&redirect_uri=...
&state=...
&expiration=20160

Per the /authorize documentation, for authorization code grants expiration controls the refresh token lifetime, not the access token (which is always capped at ~30 minutes). Without it, ArcGIS was not issuing a refresh token.

With a refresh token in hand, our backend silently renews the access token on expiry using grant_type=refresh_token, so mobile users are no longer prompted for credentials every 30 minutes.

0 Kudos