Context
I'm trying to extend tools like ICARUS Terminal and Ardent for CMDRs but I'm running into unexpected and undocumented behavior with Refresh Tokens issues from the Frontier Oauth service. I would love some insight from someone at Frontier, or first experiences from other developers who have used this API and either experienced this same issue, or not experienced it. I've also tried reaching out on the EDCD Discord about this issue.
What is working
Getting Oauth authentication working was straight forward and getting an updated Access Token (which also returns an updated Refresh Token) is simple, the code looks like this:
JavaScript:
const response = await fetch('https://auth.frontierstore.net/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: formData({ /* This function converts the object into form data */
'client_id': AUTH_CLIENT_ID,
'grant_type': 'refresh_token',
'refresh_token': refreshToken
})
})
const responsePayload = await response.json()
The Access Tokens have an expiry time of 4 hours after being issued and the pattern is to use a single use Refresh Token to get a new one after that time (and to persist the new single use Refresh Token for the next time you need to do this). I can repeatedly refresh an Access Token and Refresh Token pair, as long as the Access Token itself has not expired; that works great.
What isn't working
I cannot use the Refresh Token after Access Token itself expires.
The Refresh Token acts as a simple session token (i.e. it's just a string and must be persisted in a datastore server side by Frontier, it is not itself a JWT) and it appears that Frontier's Oauth implementation is not persisting the Refresh Tokens at their end, after ~4 hours the endpoint then returns:
JavaScript:
{
error: 'invalid_token',
error_description: 'The access token expired or is not found'
}
The Access Token is not part of the request to refresh to the token, which makes this a slightly odd error. I suspect either by design or by mistake the Frontier Oauth flow just doesn't let you use Refresh Tokens to persist a session if the Access Token isn't actively being used.
Workarounds
I would rather not work around this by persisting Access Tokens server side and doing a keep alive on them every few hours to work around this (currently they are stored securely in an JWT on the client) but presently that is the only way I have to allow users to stay signed in for more than 4 hours - I am issuing my own JWT's with their own expiry time so I can persist a session longer.
The reputed 25 day max length for a session seems very reasonable but 4 hours is a very short expiry time and would require someone to sign in again every day, which is a bit much as user experience goes. One thing that might be contributing factor is that I'm using the PKCE only flow and not providing a secret, because there doesn't appear to be a way to request a secret via the developer portal (and they are not issued automatically); it occurs to me this could be intentional behavior to mitigate inappropriate usage of the APIs, to avoid the overhead of having to police usage - or it could be unintended behavior.
I'm unclear if Frontier's implementation behaves differently if using a PKCE only flow versus being used with a shared secret - I would be interested to learn about direct experiences with others using the API to know if they had similar or divergent experiences.
The implementation I've written is open source, and all the other open source implementations I could find follow the same pattern, so unless I'm missing something I assume other developers have also run into this issue.
Last edited: