Aws-sdk-ios: How to refresh a "Sign In with Apple" JWT Token

Created on 16 Mar 2020  路  4Comments  路  Source: aws-amplify/aws-sdk-ios

State your question
We are using "Sign In with Apple" with IAM IdentityProvider and the AWSMobileClient. After signing in with Apple we pass the token to AWSMobileClient.default.federatedSignIn(providerName: "appleid.apple.com", token: token) an the user is signed in and all our API requests work.

Now I am wondering, if I have to refresh the token, when its expired. https://jwt.io/#debugger tells me the Apple JWT is valid for 10 minutes.

I was expecting after 10 minutes to get a user state change to signedOutFederatedTokensInvalid via:

awsmobileclient.addUserStateListener(self) { (state, info) in
        switch (state) {
        case .signedOut:
            // user clicked signout button and signedout
            print("user signed out")

        case .signedOutFederatedTokensInvalid:
            print("needs new token")

        default:
            print("unsupported")
        }
}

But nothing happens. All API Requests keep working even after restarting the app. The user stays signed in. Maybe the Backend does not validate the token for expiration? Or maybe there is a delay somewhere and I have not tested long enough.
Anyway how would you refresh a "Sign In with Apple" JWT Token without showing the "Sign In with Apple"-Sheet?

Sidenote: If I disconnect my App from my Apple-ID I receive a signedOutFederatedTokensInvalid (only when I restart the app). In this case I can easily route the user to the LoginViewController.

Which AWS Services are you utilizing?
AWSMobileClient

Provide code snippets (if applicable)
see above

Environment(please complete the following information):

  • SDK Version: 2.13.0
  • Dependency Manager: Carthage
  • Swift Version : 5.1.3

Device Information (please complete the following information):

  • Device: iPhone
  • iOS Version: iOS 13+
mobile client question

Most helpful comment

hi @cornr I think it's important to understand here how Cognito federated sign in works. Once you provide your apple token to Cognito's servers, Cognito then issues an id token which then gets temporary AWS credentials that includes a refresh token. It uses its own refresh token to continuing refreshing the AWS credentials. The Cognito refresh token can be set to expire anywhere from 1 to 3650 days and it defaults to 30 days which is why you are continuing to see the app working past 10 minutes. In terms of your question regarding how to re-authenticate via apple sign in, I believe apple provides a refresh token in their jwt that you can use to refresh without displaying a sign in screen to the user. However, whether or not you show a sign in screen again when the Cognito refresh token expires depends on the security posture of your app.

Diagrams of flow linked here.

Hope this helps! Closing this issue but feel free to re-open if you have any other questions. Thanks!

All 4 comments

hi @cornr I think it's important to understand here how Cognito federated sign in works. Once you provide your apple token to Cognito's servers, Cognito then issues an id token which then gets temporary AWS credentials that includes a refresh token. It uses its own refresh token to continuing refreshing the AWS credentials. The Cognito refresh token can be set to expire anywhere from 1 to 3650 days and it defaults to 30 days which is why you are continuing to see the app working past 10 minutes. In terms of your question regarding how to re-authenticate via apple sign in, I believe apple provides a refresh token in their jwt that you can use to refresh without displaying a sign in screen to the user. However, whether or not you show a sign in screen again when the Cognito refresh token expires depends on the security posture of your app.

Diagrams of flow linked here.

Hope this helps! Closing this issue but feel free to re-open if you have any other questions. Thanks!

@kneekey23 I think I understood you wrongly. We experience a .signedOutFederatedTokensInvalid after 10 minutes. So are we responsible to refresh the token we passed over to AWSMobileClient.default.federatedSignIn?

The Diagrams you mentioned e.g. Enhanced (Simplified) Authflow don't show a token refresh at the LoginProvider layer.
Is AWSMobileClient.default.federatedSignIn actually the right way to do Apple Sign in?
https://docs.aws.amazon.com/cognito/latest/developerguide/apple.html uses a credentialsProvider

I cannot find an API in https://developer.apple.com/documentation/authenticationservices to refresh a AppleID Token. Do you have an example to refresh the token?
We are really confused now.

hi @cornr I thought you said you didn't experience that after ten minutes? What is your Cognito refresh time length set to? but yes if you set your refresh token to expire after ten minutes you are responsible for refreshing the apple jwt and doing another federated sign in.

Cognito Identity Pools (which is what AWSMobileClient.default.federatedSignIn is using) only launched support for sign in with apple as a first class citizen yesterday. You previously could have done it by using the open id connect providers tab in identity pools and manually creating it yourself. In those docs you referenced, Cognito is using the low level SDK AWSCredentialsProvider which we do not recommend. We recommend using the higher level client AWSMobileClient which uses the low level SDK's under the hood as you are doing.

Found this in my search, not sure if it helps but it mentions refreshing a token.

@kneekey23 We updated Cognito Identity to the new Apple Provider. Login works. The Cognito Refresh Time is 3650 Days.
If I keep the app open I can continue to make API Requests (probably) infinitely. But when I quit the app, wait 10 minutes and start the app again: With the first API Request, the AWSMobileClient UserStateListener jumps to signedOutFederatedTokensInvalid.
The same happens with Google and Facebook only you need to wait a bit longer.
With Google and Facebook SignIn API you can perform a silent login. Probably this gets you a new token to pass to AWSMobileClient.default.federatedSignIn. A silent login is to my knowledge not possible with Apples AuthenticationServices.

Found this in my search, not sure if it helps but it mentions refreshing a token.

This Diagram shows the refreshing and verifying of the token on the server side. That in my opinion should be done by Cognito.

What is the AWS solution to keep "Sign in with Apple"-Users signed in?
Can you test that scenario with your test environment?

Was this page helpful?
0 / 5 - 0 ratings