Is your feature request related to a problem? Please describe.
At the moment, federated auth is only available when using the Web UI, which doesn't feel like a completely native experience.
Describe the solution you'd like
Allow federated authentication for custom auth flow similar to the currently working Web UI solution.
Describe alternatives you've considered
One workaround is listed here by a customer using the SDK
https://github.com/aws-amplify/aws-sdk-ios/issues/1177#issuecomment-472265432
Additional context
This may need to be escalated to the Cognito team as the functionality may not actually exist
Amplify.Auth.signInWithWebUI uses Cognito User Pool's HostedUI and can be configured to directly open social providers' sign in page, ie. create a Facebook button in the UI that opens Facebook login page as webview from the app. Without passing in any options will have a poor experience that shows the HostedUI. Although that is a use case for developers if they want to show the HostedUI as their main flow for authentication.
_ = Amplify.Auth.signInWithWebUI(for: .facebook, presentationAnchor: self.view.window!) { result in
(link)
After the user has signed in using HostedUI, a user is also created in the Cognito User Pool.
AWSMobileClient.federatedSignIn refers to a feature with Cognito Identity Pool. On Cognito Identity Pool, you can enable different providers such as Facebook, Google, Apple to sign in with, so developers retrieve the accessToken from that provider, and then pass it to Cognito Identity Pool to be authenticated (AWSMobileClient.federatedSignIn), and then make calls authenticated calls to AWS services. A user is not created in the user pool since there is no interaction with the user pool. Often times, i've seen confusion around this as one common use case is to be able to manage your users after they've signed in, like adding user attributes, adding them to cognito groups, etc.
This issue was created because of a comment I made on Twitter, so let me add my experience here.
Fundamentally this is an issue with Cognito, rather than the iOS SDK but a proper solution will impact both. For mobile apps the main point of social login is that it removes friction from the sign-up process. Facebook is by far the most important (at least on iOS, Google login is pretty popular and streamlined on Android) so I'll use that example.
What should happen is this:
1) There's a proper branded Facebook login button on your login page
2) You press it and if you have the Facebook app installed and signed in, you get auto-magically logged in after accepting the permission prompt in the Facebook app that opens - even if you never logged in before (you shouldn't need to sign-up with Facebook).
The best you can do using the hosted UI (assuming your user doesn't use Facebook in mobile Safari - which most don't) is this:
1) You have a proper branded Facebook login button on your login page
2) You press it and get taken to the Facebook login page in a Safari View Controller (note: if you use a WKWebView to make it less obviously jumping to the web, there's a decent chance Apple rejects your app - this has happened to me)
3) You login to Facebook on the web using your Facebook credentials (which you might not remember, because the native app always keeps you logged in!).
This somewhat defeats the object of social sign-in because you now have to enter an email and password, so you might as well have just signed in/up with email.
However, it gets worse...
If you need to use the native Facebook SDK for anything else (or maybe even if you don't - it's only happened on one of my projects with the Facebook SDK installed anyway for app install ad attribution) and Facebook reviews your app (which they seem to do somewhat randomly sometime after it has gone live) then Facebook then says you have to use native Facebook login, not a web login and threatens to remove authorisation for your app if you don't update it to fix that within a certain time limit. You are then stuck implementing native Facebook auth via Cognito custom auth yourself, and probably migrating all your live users to a new user pool because you didn't have the right settings enabled to do this and they are immutable.
You could do native Facebook login via a Cognito Identity Pool, but on all of the (~5) projects where I've used Cognito AND needed social login, this doesn't work because of the issues described:
"A user is not created in the user pool since there is no interaction with the user pool. Often times, i've seen confusion around this as one common use case is to be able to manage your users after they've signed in, like adding user attributes, adding them to cognito groups, etc.".
It's also far from ideal, because you get short-lived tokens from the Cognito Identity Pool, and no refresh token, so to keep the user logged in as is typical on mobile, you have to re-authenticate with the relevant provider and then get a new token from the identity pool.
Last but not least - this got noticeably worse after I last needed to use it, because Apple now requires you to include sign-in with Apple if you have any other third-party login options. In an iOS app, the Apple sign-in really needs to be native. I don't know if anyone got this working without the hosted UI to login to a Cognito User Pool? I only saw docs for the identity pool option.
Hi @markwilcox thanks for the insight
Good summary. Just a couple of clarifications to that list:
how do i use the FB SDK and HostedUI together?
This isn't really the right question. What should mobile federated login and Cognito User Pools look like? The ideal is no hosted UI at all, but a mobile native equivalent, using the relevant native SDKs / APIs and creating you a user in the User Pool with the data from the provider, and exchanging the relevant valid provider token for a set of Cognito tokens you can then stay logged in with. The less code developers have to write themselves to make this work the better. It applies across iOS, Android and React Native (where there's quite a bit of plumbing to do to include the native SDKs for each login).
Cognito Identity Pool federation currently has the 10min expiry where the developer needs to ensure to prompt the user to sign in again, and the user ends up needing to sign in every 10 mins to continue to have access the authenticated parts of the app
I believe it's not necessary to force the user to sign in again in this scenario, as you can get usually get a refresh token from the provider. You just have to manage the complexity of refreshing the token with the provider, then using that to sign-in to the identity pool. This usually means a few network round trips, which will have some impact on your UX.
For me at least the much bigger issue with the Identity Pool route for federation, is that you almost always have your own login, so you're using a User Pool to login to the Identity Pool too, but then there's an asymmetry were you have an account for the User Pool users, but not for the federated users. The only way around this is to keep your own separate user database for both, which kind of defeats the object of using a managed service like Cognito in the first place. Unrelated point, but not being able to index and search/filter on custom attributes in Cognito (it's fairly obviously DynamoDB under the hood) makes it very limited versus an alternative like Auth0.
This issue was created because of a comment I made on Twitter, so let me add my experience here.
Fundamentally this is an issue with Cognito, rather than the iOS SDK but a proper solution will impact both. For mobile apps the main point of social login is that it removes friction from the sign-up process. Facebook is by far the most important (at least on iOS, Google login is pretty popular and streamlined on Android) so I'll use that example.
What should happen is this:
- There's a proper branded Facebook login button on your login page
- You press it and if you have the Facebook app installed and signed in, you get auto-magically logged in after accepting the permission prompt in the Facebook app that opens - even if you never logged in before (you shouldn't need to sign-up with Facebook).
This entire comment is so spot on, but the above quote the most relevant part... The entire purpose of using federated identities is to make the end user's life as simple as possible. Talking to friends and colleagues, the large majority of them don't even remember their Facebook credentials (whether or not this is good practice on their part is irrelevant). If a user of my app clicks a properly branded "Continue with Facebook" button and is prompted with a username and password input in a web view, they're simply going to close the app and move on. Furthermore, the Amplify Auth plugin prompts the user saying it's going to open a link to AWS Cognito, not Facebook, which is potentially another non-starter for a new user.
From my experience, the Google sign-in in a web view is actually a little bit easier to get away with, and there are generally less Google users than Facebook users anyway.
If I use FBSDKLoginKit, implement the native FBLoginButton, I get the exact behavior I want, and I also receive a true Facebook access token with which I can call the FB Graph API to get the user profile. Is there really no way to manually insert myself into the Cognito chain at this point, with the Facebook access token, and have it create and/or authenticate my user with the Cognito user pool?
Has there been any progress identifying a potential solution to this issue?
If I use FBSDKLoginKit, implement the native FBLoginButton, I get the exact behavior I want, and I also receive a true Facebook access token with which I can call the FB Graph API to get the user profile. Is there really no way to manually insert myself into the Cognito chain at this point, with the Facebook access token, and have it create and/or authenticate my user with the Cognito user pool?
There has always been a way to do this manually, it's just slow and a bit painful to do. Basically you have to use the Cognito hooks for custom auth. So you write a lambda function which takes the token from Facebook login and fetches whatever details you need in Cognito from the Facebook Graph API. If the user already exists you log them into Cognito, if they don't already exist you create them and log them in.
Most helpful comment
This issue was created because of a comment I made on Twitter, so let me add my experience here.
Fundamentally this is an issue with Cognito, rather than the iOS SDK but a proper solution will impact both. For mobile apps the main point of social login is that it removes friction from the sign-up process. Facebook is by far the most important (at least on iOS, Google login is pretty popular and streamlined on Android) so I'll use that example.
What should happen is this:
1) There's a proper branded Facebook login button on your login page
2) You press it and if you have the Facebook app installed and signed in, you get auto-magically logged in after accepting the permission prompt in the Facebook app that opens - even if you never logged in before (you shouldn't need to sign-up with Facebook).
The best you can do using the hosted UI (assuming your user doesn't use Facebook in mobile Safari - which most don't) is this:
1) You have a proper branded Facebook login button on your login page
2) You press it and get taken to the Facebook login page in a Safari View Controller (note: if you use a WKWebView to make it less obviously jumping to the web, there's a decent chance Apple rejects your app - this has happened to me)
3) You login to Facebook on the web using your Facebook credentials (which you might not remember, because the native app always keeps you logged in!).
This somewhat defeats the object of social sign-in because you now have to enter an email and password, so you might as well have just signed in/up with email.
However, it gets worse...
If you need to use the native Facebook SDK for anything else (or maybe even if you don't - it's only happened on one of my projects with the Facebook SDK installed anyway for app install ad attribution) and Facebook reviews your app (which they seem to do somewhat randomly sometime after it has gone live) then Facebook then says you have to use native Facebook login, not a web login and threatens to remove authorisation for your app if you don't update it to fix that within a certain time limit. You are then stuck implementing native Facebook auth via Cognito custom auth yourself, and probably migrating all your live users to a new user pool because you didn't have the right settings enabled to do this and they are immutable.
You could do native Facebook login via a Cognito Identity Pool, but on all of the (~5) projects where I've used Cognito AND needed social login, this doesn't work because of the issues described:
"A user is not created in the user pool since there is no interaction with the user pool. Often times, i've seen confusion around this as one common use case is to be able to manage your users after they've signed in, like adding user attributes, adding them to cognito groups, etc.".
It's also far from ideal, because you get short-lived tokens from the Cognito Identity Pool, and no refresh token, so to keep the user logged in as is typical on mobile, you have to re-authenticate with the relevant provider and then get a new token from the identity pool.
Last but not least - this got noticeably worse after I last needed to use it, because Apple now requires you to include sign-in with Apple if you have any other third-party login options. In an iOS app, the Apple sign-in really needs to be native. I don't know if anyone got this working without the hosted UI to login to a Cognito User Pool? I only saw docs for the identity pool option.