aws-amplify / aws-sdk-ios

AWS SDK for iOS. For more information, see our web site:
https://aws-amplify.github.io/docs
Other
1.68k stars 877 forks source link

NotAuthorizedException Sign in with Apple + Cognito #2788

Closed eanntuan closed 3 years ago

eanntuan commented 4 years ago

I'm trying to integrate SIWA with AWS Cognito, but am running into issues on the native iOS app. I'm able to successfully sign in on the AWS hosted UI after configuring with SIWA.

However, on the native iOS app, I'm able to get the auth token and decode the JWT token. However, once I send that token to AWS using func finishedWithAuth this is when it fails to send to AWS and authenticate with my identity pool there. Here's code I have so far following the documentation from SIWA with AWS Cognito (I can't link it here).

I've looked into this issue but I'm not using AWSMobileClient. I'm using AWSCognitoIdentity

Here's the error I get from line 28:

{"type":"NotAuthorizedException","message":"Token is not from a supported provider of this identity pool."} 2020-06-23 10:48:29:047 wolf-ios[1879:1393080] GetId failed. Error is [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=8 "(null)" UserInfo={type=NotAuthorizedException, message=Token is not from a supported provider of this identity pool.}] Error: The operation couldn’t be completed. (com.amazonaws.AWSCognitoIdentityErrorDomain error 8.)

Note: I've followed these instructions for setting SIWA on the hosted UI, and I'm able to successfully sign in with Apple via the web page, but not on the native iOS app


@available(iOS 13.0, *)   
    func finishedWithAuth(auth: ASAuthorizationAppleIDCredential!, error: NSError!) {
        if error != nil {
            print(error.localizedDescription)
        } else if let idToken = auth.identityToken {
            // Force the SDK to obtain new credentials
            clearCredentials()
            updateCredentialsProvider()
            let idTokenString = String(data: idToken, encoding: .utf8) ?? ""
            let logins = ["appleid.apple.com": idTokenString]
            let customIdentityProvider = CustomIdentityProvider(tokens: logins)
            let identityPoolId = Configuration.cognitoIdentityPoolId.value
            let region: AWSRegionType = .USWest2
            let credentialsProvider = AWSCognitoCredentialsProvider(regionType: region,
                                                                    identityPoolId: identityPoolId,
                                                                    identityProviderManager: customIdentityProvider)
            let configuration = AWSServiceConfiguration(region: region, credentialsProvider: credentialsProvider)
            AWSServiceManager.default().defaultServiceConfiguration = configuration
            credentialsProvider.getIdentityId().continueWith { (task: AWSTask!) -> AnyObject? in
                if task.error != nil {
                    print("Error: " + (task.error?.localizedDescription)!)
                } else {
                    // the task result will contain the identity id
                    let cognitoId = task.result
                    logit("Cognito ID : \(cognitoId ?? "")")
                }
                return nil
            }
        }
    }`
palpatim commented 4 years ago

@eanntuan Please also review the SDK docs for additional context. That example is for AWSMobileClient, but AWSMobileClient delegates down to CognitoIdentity under the hood, so the concepts are the same.

Your code looks right based on my quick scan, so this may be an issue in your IdentityPool configuration or the CustomIdentityProvider. Do note that federating into Identity Pool requires you to configure SIWA in your Identity Pool with the Bundle Identifier, not the Apple Services ID. Also note the known issue described in #2513.

eanntuan commented 4 years ago

Hello - thank you for your response. Are you referring to the Cognito --> Identity Pool --> Edit Identity Pool --> Authentication Providers --> Apple should be the app's Bundle Identifier, even though it says Apple Services ID? I ended up changing this value to my app's Bundle Identifier, and now I'm able to authenticate without an error.

Screen Shot 2020-06-30 at 12 29 00 PM

Once I changed the Apple Authentication Provider Apple Services ID to the app's Bundle ID, I was able to successfully get the identity id with `credentialsProvider.getIdentityId().continueWith (see the screenshot of attached code).

However, now, I'm having issues connecting the current user, which should now be the SIWA user id and email to the AWS Cognito.

I'm using the currentuser.isSignedIn, and it's returning false after successfully getting the identity id... Am I missing additional steps to sign the user in from Apple's auth apple Id credential to AWS Cognito?

royjit commented 4 years ago

Hi @eanntuan

If you are using Cognito Identity Pool, you will not get a valid user when you invoke currentUser. If you would like to have user management along with Apple Sign In, I recommend you use HostedUI with Apple as one of the signIn provider.

You can try the latest Amplify library for the same - https://docs.amplify.aws/lib/auth/social_signin_web_ui/q/platform/ios

eanntuan commented 4 years ago

Does this mean it's not possible to SIWA on a native iOS application that uses the AWSCognito framework?

I'll still need properties of the current user, even if I use the HostedUI - such as isSignedIn and their username. For the HostedUI, when I authenticate successfully and redirect to the redirectUrl, I'm still confused how to grab the user's information via Cognito. Or is this not supported?

royjit commented 4 years ago

SIWA will still work when you use HostedUI, the only difference is that you do not need to worry about adding the Apple Sign In button and the callbacks. You just need to call something like this:

_ = Amplify.Auth.signInWithWebUI(for: .apple, presentationAnchor: self.view.window!) { result in
            switch result {
            case .success(_):
                print("Sign in succeeded")
            case .failure(let error):
                print("Sign in failed \(error)")
            }
        }

Details are given here - https://docs.amplify.aws/lib/auth/social_signin_web_ui/q/platform/ios

After this you can get user attributes using these apis - https://docs.amplify.aws/lib/auth/user-attributes/q/platform/ios

eanntuan commented 4 years ago

Thank you @royjit for the info - I want to use our own native login UI, not the hosted UI. Is this still possible to incorporate SIWA on a native login screen, connect the user to our user pool, and have them proceed as normal within the app? (where their info is accessible via the special SIWA user pool, and we can get their user id to cross-reference in dynamo)

royjit commented 4 years ago

SignIn using the native UI for social provider and then connecting to Cognito User Pool is not currently supported. Similar ticket - https://github.com/aws-amplify/aws-sdk-ios/issues/1937

bumbleparrot commented 4 years ago

SignIn using the native UI for social provider and then connecting to Cognito User Pool is not currently supported. Similar ticket - #1937

I want to use the native sign in UIs from each provider: Apple, Google, Facebook but also want the benefit of a User Pools to store user attributes. It sounds like this can’t be done!

After a week of tinkering and searching, this is the answer I’ve been looking for!

@Royjit, is my understanding correct?

royjit commented 3 years ago

@bumbleparrot Yes, you are correct, signIn to social providers and then store the user details in Cognito User Pool is currently supported only through the hosted UI option by Amazon Cognito User Pools.

I am closing this issue as a dup for #1937

angelusualle commented 1 year ago

@royjit crap experience