Way to login with google directly in the app instead of throwing to sign in with web UI
Before opening, please confirm:
- [X] I have searched for duplicate or closed issues and discussions.
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
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 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 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 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 thank you for clarifying -- we do not support this auth flow at this time. I'll mark this issue as a feature request.
@tylerjroach @tjleing I'm thinking of the following approach :
- Get the google account by logging in user via mGoogleSignInClient (Google SDK)
- 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 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.
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?
Following this as well.
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?)!
@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 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.
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.
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.HostedUIRedirectActivityshould 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 usefetchAuthSessionto 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 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 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.
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 ?
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 ?
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:
- Customer calls
signInWithSocialWebUI. This launches a CustomTab to the social provider (ie: Google). - 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.
- 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.
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 ?
federateToIdentityPool has limitations. for example, app is not able to access S3 after calling federatedToIdentityPool().