Sign In With Apple refresh token validation only access token returned

1.2k views Asked by At

I'm using the AppleAuth npm package in my server to submit token requests to Apple's servers during the sign in with Apple process. (This is based off the sample server code provided with the sign_in_with_apple package in pub.dev) I have no issues submitting the authorization code to get my first access and refresh tokens.

However, when trying to test how my app would get a new refresh token, when I submit a POST request to https://appleid.apple.com/auth/token with the grant_type set to refresh_token the response I get is different than from having the grant_type set to authorization_code.

I looked at the source code of the package, and for its AppleAuth(myConfig).refreshToken(myRefreshToken) (<- pseudo code lol) the only difference in the POST payload is:

{
 grant_type: 'refresh_token', // instead of grant_type: 'authorization_code'
 refresh_token: refreshToken, // instead of code: authorizationCode
 ... // other params
}

While the initial request with authorization code returns both an access token and a refresh token, for some reason the refresh token request is only returning the access token. I really don't think it's the package causing the error, nor can I see how my code would be the source either, since the above code is the only difference.

I tried passing the access token that it returns in a new refresh token request in order to test that I can get new refresh tokens whenever necessary in the future, but it returns a 400 status error.

Am I missing something here? Is there a reason the refresh token request returns no new refresh token? Or am I missing something entirely about how the process/flow is supposed to work? I am trying to do this for the "check the refresh token once daily to confirm the user is still in good standing with Apple's servers" part of the process.

I've really been stuck on what to do at this point. I can save the identity_token.sub field in my database to check whether my user is signed in, but of course I want to make sure my user's apple ID is still valid with apple, and that they haven't revoked access. Could it be that because I tried to get a new refresh_token too soon Apple only returned the access_token?

Oh also, the app itself is a Flutter app and I am testing all of this on my iPhone 11 so it's not an Android/Web flow.

1

There are 1 answers

2
Gary Archer On

Whether you get a new 'rolling / rotating' refresh token in a refresh token grant response is generally vendor specific:

  • You may get a new refresh token occasionally but not always
  • The primary purpose of this message is to get a new access token, not a new refresh token

In terms of token handling, the client should update its tokens similarly to the saveTokens method in this sample of mine.

I've not used Sign In with Apple but I suspect proceeding as follows would be the simplest solution:

  • Keep access tokens short lived: no more than 60 minutes
  • This forces a frequent token refresh, which by default is very quick
  • If the user's Apple Id is revoked I would expect this to return an invalid_grant response