amplify-android icon indicating copy to clipboard operation
amplify-android copied to clipboard

Way to login with google directly in the app instead of throwing to sign in with web UI

Open SomnathS09 opened this issue 2 years ago • 21 comments

Before opening, please confirm:

Language and Async Model

Kotlin, Kotlin - Coroutines

Amplify Categories

Authentication

Gradle script dependencies

// Put output below this line
// Not applicable because new feature request

Environment information

# Put output below this line


Please include any relevant guides or documentation you're referencing

https://adrianhall.github.io/android/2018/09/18/auth-with-aws-amplify-1/

Describe the feature request

There is no direct way to do federated login in Android, there is only 1 API i.e signInWithWebUi which throws user to a web page or custom web view. As mentioned here : https://developers.google.com/identity/sign-in/android/backend-auth We need a way to directly login in user with "sign-in with google" button, which talks to google OAuth server and login directly with Cognito. Please provide a direct API like Amplify.fedratedSignIn{provider : google} which handles all of those backend redirects and give the result as user.

Initialization steps (if applicable)

No response

Code Snippet

// Put your code below this line.

amplifyconfiguration.json

No response

GraphQL Schema

// Put your schema below this line


Additional information and screenshots

No response

SomnathS09 avatar May 22 '23 07:05 SomnathS09

Hi @SomnathS09,

Please see our federateToIdentityPool method: https://docs.amplify.aws/lib/auth/advanced/q/platform/android/#identity-pool-federation.

Please note, there are some limitations with this approach. You will not have access to Cognito User Pool's and refreshing tokens is a manual process.

I hope this helps!

tylerjroach avatar May 22 '23 14:05 tylerjroach

@tylerjroach Thanks for answering and mentioning the limitations. And Yes, Actually I am looking for solution that will embed the user credentials into Amplify as simple as available with Amplify.Auth.SignIn(username, password) method; So that later I can access all id, access, refresh token and user details like Amplify.currentUser() as well.

What is needed for this, please guide with your experience.

SomnathS09 avatar May 22 '23 14:05 SomnathS09

@SomnathS09 In your initial comment, you mentioned only having signInWithWebUI. I want to make sure that you are aware that we do have a signInWIthSocialWebUI that allows passing AuthProvider.google(). While this will still launch in the hosted ui flow, it will handle Google Authentication for you.

At this time, for social providers, we provide the hosted ui experience or the federateToIdentityPool experience. The Amplify.signIn API does not currently support native social sdk's.

tylerjroach avatar May 22 '23 14:05 tylerjroach

@tylerjroach Yes, I am aware of signInWIthSocialWebUI, but it takes user out of the app to web browser. If user is not signed into google account in web browser, it asks for passwords. Many of our users face this problem. With signInWithGoogle directly on native, the experience would be better as they won't have to type password, just select account and Android's Google One Tap sign-in will log them in.

You must have also used Android apps that provide direct native google sign-in, why don't Amplify focuses on it?

SomnathS09 avatar May 22 '23 17:05 SomnathS09

@SomnathS09 thank you for clarifying -- we do not support this auth flow at this time. I'll mark this issue as a feature request.

tjleing avatar May 23 '23 22:05 tjleing

@tylerjroach @tjleing I'm thinking of the following approach :

  1. Get the google account by logging in user via mGoogleSignInClient (Google SDK)
  2. Pass in this account info to HostedUIRedirectActivity.kt (Amplify Android SDK) somehow and login to Amplify Auth

can you please guide the step 2? it has become high priority for us to integrate direct google account sign-in feature.

SomnathS09 avatar May 31 '23 06:05 SomnathS09

@SomnathS09 This approach would not work. The redirect code that goes into HostedUIRedirectActivity comes from Cognito, it does not come from Google.

We do not yet support Google Native SDK Auth outside of federateToIdentityPool.

tylerjroach avatar May 31 '23 14:05 tylerjroach

Can you throw some light on:

How does cognito generate this token? can I make some middleware server that calls to cognito endpoint for generating this token (maybe with some Google credentials) and receive the token? What's going on behind this Google-Cognito OAuth flow?

And about limited to identityPool : if I get you correctly I cannot identify the user in User pool, because getting .currentUser will throw error right? It will be just temporary credentials?

SomnathS09 avatar May 31 '23 14:05 SomnathS09

Following this as well.

ZiggyMo avatar Jul 21 '23 06:07 ZiggyMo

Funny, I tried to figure out how this works without amplify already. I thought, well let's debug through amplify, they do this somehow... Well, no(t yet?)!

andretietz avatar Dec 04 '23 14:12 andretietz

@tylerjroach Do you have any news about this ? It's been 11 months now. Do you have any github repo example at least with an android app (so Kotlin frontend) and a signup/signin process with google as a social provider ? Have the Amplify team given up Kotlin ? From the documentation that's how I interpret it.

emmanuelha avatar Apr 19 '24 08:04 emmanuelha

@emmanuelHa Sign in with Google still requires signInWithSocialWebUI or using federateToIdentityPool.

Have the Amplify team given up Kotlin ? From the documentation that's how I interpret it.

The Amplify Android team is still actively focused on the Kotlin Android developer experience. Please let us know what concerns you have from documentation.

tylerjroach avatar Apr 19 '24 13:04 tylerjroach

Hello @tylerjroach thank you for your answer. From a global point of view the Amplify documentation about Sign up / Sign in scenario is far from easy to use.

  • Let me start with an obvious remark. When you write documentation users want simple code to copy paste, test it and boom, it works. Common use case so easy coding. You don't run into tunnel effect, you move forward and work on your business use case because that's why we are paid ;=). An example:

setContent { Authenticator { state -> SignedInContent(state) } }

Looks very simple right, but it would have been even better with a simple implementation of SignedInContent. What does it takes for people developing all the day on those topics ? Nothing

  • Another remark: The difference between those two pages should be more explicite: https://docs.amplify.aws/android/build-a-backend/auth/sign-in-with-web-ui/ https://docs.amplify.aws/android/build-a-backend/auth/add-social-provider/ In the first page it is mentioned social providers When configuring social sign-in through the Amplify CLI. We are in a page which is not about social provider, so why making this remark ? By the way in the second page when we configure the auth provider part and its credential we set up the type of application: Choose Web application as Application type and name your OAuth Client. => Android context and we pick up web application => it is very confusing and a simple remark in the documentation would be beneficial imho.

  • Third remark: when I tried the second page https://docs.amplify.aws/android/build-a-backend/auth/add-social-provider/ Once signed up throught google provider and the user identity stored into cognito I get in my Kotlin app the following error: links are blocked ://callback/?code=xxx&state=yyy where my-theme comes from AndroidManifest.xml:

    <activity
        android:name=".AuthActivity"
        android:exported="true"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <action android:name="android.intent.action.RUN"/>
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <data android:scheme="my-scheme" />
        </intent-filter>
    </activity>

Would you have any idea what could be the missed configuration ?

Now in the new version Gen 2: Can you tell me where is in the documentation https://docs.amplify.aws/gen2/ the use of Amplify.Auth.signInWithSocialWebUI ? This function can be used from Kotlin and there is no mention of it in the new documentation. By the way if I look at this documentation https://docs.amplify.aws/gen2/build-a-backend/auth/add-social-provider/ we realize that the function signInWithSocialWebUI was replaced by export const auth = defineAuth in amplify/auth/resource.ts. So authentication was made from kotlin and moved to ... typescript :=/ How the kotlin frontend is supposed to call the const auth = defineAuth defined in resource.ts ?

My last question is for the usage of a non Web page in the context of an android app. I saw that you suggested to use federateToIdentityPool ( https://docs.amplify.aws/android/build-a-backend/auth/advanced-workflows/#pageMain) What would be the need to acces to Cognito User Pool's as long as the user is saved into cognito ? May be to get the currentUser ? Can't we use Amplify.Auth.getCurrentUser() for that ? And we would need to code the UI "from scratch" right ? For the usage of federateToIdentityPool How can we get the token ? Using credentialManager.getCredential ?

Sorry for all those questions, but if amplify teams want an adoption from kotlin developers, this subject has to be a non subject.

emmanuelha avatar Apr 19 '24 14:04 emmanuelha

Hi @emmanuelHa Let me try to address a few of these things that I can immediately answer, and then I'll forward concerns along to our product team.

  • For your "Third Remark", I'm not sure what you are trying to do with your own AuthActivity. com.amplifyframework.auth.cognito.activities.HostedUIRedirectActivity should be used as specified in the documentation. It is our internal headless Activity to handle the intent and proceed with the rest of the authentication flow.
  • As for Gen 2. The Gen2 experience (and docs) are still in developer preview. The link you have provided is referencing how to create your Auth backend. Gen2 offers a typesafe, code-first experience when defining your backend. https://docs.amplify.aws/gen2/how-amplify-works/concepts/ This is a new experience over creating your backend via the CLI. Android is one of the front-end experiences once the backend is created. While the initial preview documentation focuses on front-end js, Gen2 Android documentation will be present when the Gen2 experience goes GA.
  • For the last question, no you can't use getCurrentUser when using federateToIdentityPool. You can use fetchAuthSession to retrieve session/credential information (https://docs.amplify.aws/android/build-a-backend/auth/advanced-workflows/#retrieve-session)

    Note that when federated, APIs such as Auth.getCurrentUser will throw an error as the user is not authenticated with User Pools.

tylerjroach avatar Apr 19 '24 17:04 tylerjroach

@tylerjroach Thanks for your responses. If I use this activity:

    <activity
        android:name="com.amplifyframework.auth.cognito.activities.HostedUIRedirectActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="my-scheme" />
        </intent-filter>
    </activity>

I get "Default Activity not found" error

For Gen 2:

Gen2 Android documentation will be present when the Gen2 experience goes GA

When do you think it could be GA ?

emmanuelha avatar Apr 19 '24 20:04 emmanuelha

@emmanuelHa You still need a main activity for your app that containing these intent filters:

<intent-filter>
  <action android:name="android.intent.action.MAIN" />
  <action android:name="android.intent.action.RUN"/>
  <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

The activity with these intent filters is the activity that is used to launch the app.

That is the reason for your error. HostedUIRedirectActivity is an additional activity that needs to go in your manifest.

tylerjroach avatar Apr 19 '24 20:04 tylerjroach

Ok. When I add the HostedUIRedirectActivity i get:

Unable to start activity ComponentInfo{fr.ehtech.my-scheme/fr.ehtech.my-scheme.MainActivity}: android.view.InflateException.

By the way when mainActivity calls signInWithSocialWebUI how is HostedUIRedirectActivity called ? Under the hood ?

emmanuelha avatar Apr 19 '24 20:04 emmanuelha

In AndroidManifest I had to remove the package to make the app launched. But @tylerjroach could you explain how Amplify.Auth.signInWithSocialWebUI works ? Because I signed in once and then I have to code an explicite call to Amplify.Auth.signOut in my app to be disconnected. Then once disconnected how can I login again ? Do I have to create a button to execute Amplify.Auth.signInWithSocialWebUI ? I thought the HostedUIRedirectActivity would display a screen with the traditional form to signup/signin/logout ? Another question is: is it possible to login with social provider and deal with two google emails for example ? Or mix a google provider with a traditional user/password signup/signin with Authenticator component ?

emmanuelha avatar Apr 21 '24 17:04 emmanuelha

The Authenticator component does not need to take up the full screen. You can additionally add a button on the screen to sign in with Google (onClick to call signInWithSocialWebUI.

HostedUIRedirectActivity is headless. It does not have a view. It is simply used to handle redirects that come from the browser.

As for how hosted ui works:

  1. Customer calls signInWithSocialWebUI. This launches a CustomTab to the social provider (ie: Google).
  2. End User signs in with social provider. The CustomTab redirects back into the application and Amplify exchanges the code provided from Google into Cognito credentials.
  3. Sign in is completed.

If customer wants to sign out, a button needs to be provided to them where you call Amplify.Auth.signOut.

Q: "it possible to login with social provider and deal with two google emails" A: Yes. If you; use Google as a sign in provider, the CustomTab will direct the customer to Google, where they can provide credentials for whichever account they choose.

tylerjroach avatar Apr 22 '24 13:04 tylerjroach

Thank you @tylerjroach I progress. What I have done:

  • Customization of Authenticator: https://ui.docs.amplify.aws/android/connected-components/authenticator/customization adding a footer with a Button which launches:
  • Amplify.Auth.signInWithSocialWebUI (https://docs.amplify.aws/android/build-a-backend/auth/add-social-provider) This way I can signup with both a user/password AND with a social provider. Great! In cognito I have two users, one signed up from Authenticator, one from google signInWithSocialWebUI.
  • from Authenticator in Cognito I see Email verified true
  • from signInWithSocialWebUI in Cognito I see Email verified false Do you think that could be the reason ?

emmanuelha avatar Apr 22 '24 15:04 emmanuelha

federateToIdentityPool has limitations. for example, app is not able to access S3 after calling federatedToIdentityPool().

XingZhaoDev avatar Jun 21 '24 23:06 XingZhaoDev