aws-amplify / amplify-android

The fastest and easiest way to use AWS from your Android app.
https://docs.amplify.aws/lib/q/platform/android/
Apache License 2.0
237 stars 111 forks source link

signInWithSocialWebUI Google not working #2831

Open mbahmani90 opened 1 month ago

mbahmani90 commented 1 month ago

Before opening, please confirm:

Language and Async Model

Kotlin

Amplify Categories

Authentication

Gradle script dependencies

```groovy // Put output below this line implementation 'com.amplifyframework:core:2.16.0' implementation 'com.amplifyframework:aws-api:2.16.0' implementation 'com.amplifyframework:aws-datastore:2.16.0' implementation 'com.amplifyframework:aws-auth-cognito:2.16.0' implementation 'com.amazonaws:aws-android-sdk-auth-userpools:2.8.0' implementation("io.github.jan-tennert.supabase:postgrest-kt:0.7.6") implementation("io.ktor:ktor-client-cio:2.3.3") implementation 'com.amplifyframework:aws-storage-s3:2.16.0' implementation("aws.sdk.kotlin:dynamodb:1.0.30") implementation("aws.sdk.kotlin:secretsmanager:1.0.30") implementation("aws.smithy.kotlin:http-client-engine-okhttp:1.0.11") implementation("aws.smithy.kotlin:http-client-engine-crt:0.30.0") implementation 'aws.sdk.kotlin:aws-core:1.0.44' ```

Environment information

``` # Put output below this line ```

Please include any relevant guides or documentation you're referencing

No response

Describe the bug

Hi,

Hope you are all fine!

I want to add social provider sign-in for google accounts. I followed all of the instructions in https://docs.amplify.aws/gen1/android/build-a-backend/auth/add-social-provider/

Then I added google identity provider in user pool ->sign-in experience and enter client_id and client_secret:

image

The host UI configuration is as follows:

image

When I run the Amplify.Auth.signInWithSocialWebUI in the first time the application minimize but when I reopen the app a diolog pops up and I choose my account and in user pool my account appears:

resultLauncher.launch(googleSignInClient.signInIntent)
AmplifyRepository.signInWithGoogle(this)
Amplify.Auth.signInWithSocialWebUI(
    com.amplifyframework.auth.AuthProvider.google(),
    this,
    {
        app.l("AuthQuickstart Sign in OK: $it")
    },
    {
        app.l("AuthQuickstart Sign in failed $it")
    }
)

image

However, the email is not verified.

It is worth noting that I don't have any problem with signInWithEmailAndPassword, and it works fine.

Could you please explain if anything else is required to do?

Thanks.

Reproduction steps (if applicable)

No response

Code Snippet

// Put your code below this line.

Log output

``` // Put your logs below this line ```

amplifyconfiguration.json

No response

GraphQL Schema

```graphql // Put your schema below this line ```

Additional information and screenshots

No response

tylerjroach commented 1 month ago

Can you click on the "Google" identity provider and take a look at the attribute mapping? Did you add configure Google sign in's via the Amplify CLI or are you trying to configure this manually? I think there is a missing email attribute mapping to look into, but if the CLI was used, I would have expected this to already be configured.

mbahmani90 commented 1 month ago

Yes, I did configuration via Amplify CLI.

image

If anymore information is required please let me know.

Thanks.

tylerjroach commented 1 month ago
Screenshot 2024-05-30 at 9 41 01 AM

What about attributes to verify under the sign up tab. When authenticating with Google, did you get an email verification? If not I'll try and test this myself. I can't remember the sign up flow with Google provider and whether email confirmation is still used.

mbahmani90 commented 1 month ago

Sign up tab: image

When authenticating with Google, did you get an email verification?

No, I don't receive verification email. And I also tried to resend verification code but it didn't receive any email.

fun resendVerificationCode(displayedName: String , email: String , onComplete: () -> Unit , onError: (it: AuthException) -> Unit){
    try {
        Amplify.Auth.resendSignUpCode(email , { onComplete() } , { onError(it) })
    }catch (e : Exception){
        app.l(e.toString())
    }

}

I developed my app based on cognito, s3 and dynamodb. Everything is working well. it is really pity not to have signInwithSocialUI. I tested many ways and remove and create everything several times. However, it is not still solved.

Thank you.

tylerjroach commented 1 month ago

I'll let you know what I see on my end when I set up a test app.

mbahmani90 commented 1 month ago

Thank you.

tylerjroach commented 1 month ago

I've verified that on a new Amplify app with google hosted ui sign in, I am also not seeing the email as confirmed.

However, the user is "enabled" and the confirmation status is "external provider". The user should be able to complete user pool actions with this status.

Can you explain your use case on how email verification impacts these users? I'm still trying to verify what the expected behavior is.

mbahmani90 commented 1 month ago

Yes, in my case the user is also enable but the email is not verified. I also verified the email manual but when I log in android application side I receive the user is not verified. I will send you the log soon. Are you able to login is application successfully?

image

tylerjroach commented 1 month ago

Yes, I am able to log in successfully. I'll take a look at the logs you are seeing when they come in. Thank you.

mbahmani90 commented 1 month ago

Sorry for delay in response: when I call:

Amplify.Auth.fetchAuthSession(
    { app.l("AmplifyQuickstart Auth session = $it") },
    { error -> app.l("AmplifyQuickstart Failed to fetch auth session $error") }
)

I receive the following error:

AmplifyQuickstart Auth session = AWSCognitoAuthSession(isSignedIn=false, identityIdResult=AuthSessionResult{value=null, error=NotAuthorizedException{message=Failed since user is not authorized., cause=NotAuthorizedException(message=Unauthenticated access is not supported for this identity pool.), recoverySuggestion=Please sign in and reattempt the operation.}, type=FAILURE}, awsCredentialsResult=AuthSessionResult{value=null, error=NotAuthorizedException{message=Failed since user is not authorized., cause=NotAuthorizedException(message=Unauthenticated access is not supported for this identity pool.), recoverySuggestion=Please sign in and reattempt the operation.}, type=FAILURE}, userSubResult=AuthSessionResult{value=null, error=NotAuthorizedException{message=Failed since user is not authorized., cause=NotAuthorizedException(message=Unauthenticated access is not supported for this identity pool.), recoverySuggestion=Please sign in and reattempt the operation.}, type=FAILURE}, userPoolTokensResult=AuthSessionResult{value=null, error=NotAuthorizedException{message=Failed since user is not authorized., cause=NotAuthorizedException(message=Unauthenticated access is not supported for this identity pool.), recoverySuggestion=Please sign in and reattempt the operation.}, type=FAILURE})

Are the authorized scope correct? image

mbahmani90 commented 1 month ago

I use Amplify.Auth.getCurrentUser to check if the account is already sign in and it works fine for Amplify.Auth.signIn.

However, when I signed in with google provider by calling Amplify.Auth.signInWithSocialWebUI , I receive nothing (neither onComplete() nor onError() ) it is also the same for Amplify.Auth.getCurrentUser or Amplify.Auth.fetchAuthSession !

Amplify.Auth.getCurrentUser({
            UserAccountRepository.accountId = it.userId
            onComplete(it)
        } ,
        {
            onError(it)
        })

Do you know if it is the correct way to check isSignedIn?

mbahmani90 commented 1 month ago

The "Auth" element in backend-config.json

"auth": {
    "xxxxx": {
      "customAuth": false,
      "dependsOn": [],
      "frontendAuthConfig": {
        "mfaConfiguration": "OFF",
        "mfaTypes": [
          "SMS"
        ],
        "passwordProtectionSettings": {
          "passwordPolicyCharacters": [],
          "passwordPolicyMinLength": 8
        },
        "signupAttributes": [
          "EMAIL",
          "NAME"
        ],
        "socialProviders": [],
        "usernameAttributes": [
          "EMAIL"
        ],
        "verificationMechanisms": [
          "EMAIL"
        ]
      },
      "providerPlugin": "awscloudformation",
      "service": "Cognito"
    }
  }
tylerjroach commented 1 month ago

@mbahmani90

I missed an important detail in the original build.gradle you posted. I see this dependency implementation 'com.amazonaws:aws-android-sdk-auth-userpools:2.8.0'.

This comes from our AWS Android SDK. If this happens to be using AWSMobileCient, which is also part of the AWS Android SDK, it will wipe the credentials from Amplify v2.

You should try and remove all references to com.amazonaws:aws-android-sdk-xxx in your application. If you still rely on an AWS Android SDK library, please see the compatibility guide here: https://docs.amplify.aws/gen1/android/sdk/configuration/amplify-compatibility/


From the last fetchAuthSession logs you posted, it is clear that you have no credentials. Both userPool and identityPool information are missing from the result and isSigendIn shows false. It may be possible that the account is being created ok on the browser side, but the redirect isn't being received on the app side. However, I think the first thing you still need to look at is the usage of AWS Android SDK libs.

Another thing that can help with debugging... Add AndroidLoggingPlugin(LogLevel.VERBOSE) as the first configured Amplify plugin. This would add a large number of helpful logs for the Auth plugin to see what is happening.

mbahmani90 commented 4 weeks ago

Hi,

Sorry for delay in response.

I deleted all of com.amazonaws:aws-android-sdk-xxx dependencies and remove auth amplify remove auth. Then recreate user pool. However, nothing has been changed and the error still remains.

Then I add AmplifyCredentialsProvider class:

class AmplifyCredentialsProvider : AWSCredentialsProvider {

    override fun getCredentials(): AWSCredentials = runBlocking {
        app.l("Get Credentials")
        suspendCoroutine { continuation ->
            app.l("suspendCoroutine")
            Amplify.Auth.fetchAuthSession(
                { authSession ->
                    app.l("fetchAuthSession")
                    val awsTemporaryCredentials = (authSession as? AWSCognitoAuthSession)
                        ?.awsCredentialsResult?.value as? AWSTemporaryCredentials

                    val sdkCredentials = awsTemporaryCredentials?.let {
                        app.l("${it.accessKeyId}, ${it.secretAccessKey}, ${it.sessionToken}")
                        BasicSessionCredentials(it.accessKeyId, it.secretAccessKey, it.sessionToken)
                    }

                    if (sdkCredentials != null) {
                        app.l("Credential is not null!")
                        continuation.resume(sdkCredentials)
                    } else {
                       app.l("Credential is null!")
                        val authException = RuntimeException("Failed to get credentials")
                        continuation.resumeWithException(authException)
                    }
                },
                {
                    app.l("AuthExcepttion")
                    continuation.resumeWithException(
                        RuntimeException("Failed to get credentials. See exception.", it)
                    )
                }
            )
        }
    }

    override fun refresh() = runBlocking {
        suspendCoroutine { continuation ->
            Amplify.Auth.fetchAuthSession(
                AuthFetchSessionOptions.builder().forceRefresh(true).build(),
                // We do not need to capture value if refresh succeeds
                { continuation.resume(Unit) },
                // We do not need to throw if refresh fails
                { continuation.resume(Unit) }
            )
        }
    }
}

The dependencies:

implementation 'com.amazonaws:aws-android-sdk-ddb:2.73.0'
implementation 'com.amazonaws:aws-android-sdk-mobile-client:2.73.0'
implementation 'com.amazonaws:aws-android-sdk-auth-core:2.73.0'

before runningAmplify.Auth.signInWithSocialWebUI in amplifyCredentialsProvider.getCredentials() I receive :

app.l("Credential is null!")

When I call Amplify.Auth.signInWithSocialWebUI then in amplifyCredentialsProvider.getCredentials()gets stuck in app.l("Get Credentials")

It is worth noting I am using MIUI Global 14.0.5.0 and Android version 12 SKQ1.211019.001

I only wanted to let you know. Don't waste your time. If there is no issue on your side, it means that I am making mistake somewhere in this process.

Thanks.

mbahmani90 commented 3 weeks ago

Just one note.

image

In app integration -> appClientWeb -> Hosted UI when I click on View Hosted UI the account created but not verified. I guess that the problem is not from android side.

image

tylerjroach commented 3 weeks ago

You cannot use implementation 'com.amazonaws:aws-android-sdk-mobile-client:2.73.0' with Amplify Android. You can use the custom credentials provider you have shown above for other AWS SDK usages, but MobileClient cannot be present. It will overwrite Amplify credentials.

mbahmani90 commented 3 weeks ago

Sorry I forgot to say that. I have tested with and without implementation 'com.amazonaws:aws-android-sdk-mobile-client:2.73.0'.

tylerjroach commented 3 weeks ago

Please post the logs that are shown when calling fetchAuthSession after you have added AndroidLoggingPlugin(LogLevel.VERBOSE) as the first configured Amplify plugin in your application. This will help identity the cause.

mbahmani90 commented 3 weeks ago

Hi Tyler!

Please give me a time because I should develop other parts as soon as possible it may take several days. Then I will send you the logs.

Many Thanks for your support.