AWS Cognito Facebook and Phone number login - ios

We are building an app that requires social logins (Apple, Facebook, Instagram, Google, etc) and also phone number login (where the user receives a code via SMS to login)
This is a similar sign-in model to Tinder/Bumble dating apps
We are using AWS for our backend and want to use AWS Cognito for our Authorization/Authentication
I am having difficulty finding out a way to get AWS Cognito working with our setup:
Currently, AWS Cognito provides 2 ways of authorization.
Cognito User Pools
Cognito Identity Pool
We have developed the Phone number login method with User Pool and the social login methods i.e. Google and Facebook are Federated via. Identity Pool.
The issue with the Federated Signing-in method is that the JWT tokens are not returned by Cognito, instead, temporary AWS credentials are returned (which for now works efficiently with the system).
But since AWS does not allow us to use two authorizers at a time, we then needed to use the temporary credentials instead of JWT tokens provided by the user pool. The issue here is that the temporary credentials get expired in a maximum time of 12 hours from the time they have been issued and in case of phone number login, the user needs to then login back to generate the credentials again which degrades the User Experience.
Though Google and Facebook log in can also be integrated via User Pool and retrieve JWT Token in return, the issue is that a UI hosted by Cognito appears which again prompts the user with several login methods used in the app, which again is a bad UX as user needs to tap on Sign-in in with Facebook twice to sign-in.
Is there a way to have Phone number login/social login without:
Using Hosted UI (My understanding is that the Hosted UI cannot be changed to appear how we want, ie: like our original sign-in page designs)
Forcing the user to log in again ever 12 hours
Forcing the user to log in twice (once in our app and once in the Cognito provided UI)
Thank you for your time

Related

How to randomly generate user ID without login AWS

Users can use my app without a login. But they get more features if they create an account, like saving a product.
I'm working through this AWS doc: Integrate Your Existing NoSQL Table - AWS Mobile Hub Developer Guide
But it doesn't appear to have any details about allowing permission for users that don't have a login. I would need to randomly generate an ID when a user first opens the app and still create a user with it.
I've setup a database that has a list of products. That I plan to use the ObjectMapper API to query the database.
AWS has a service called Amazon Cognito.
Amazon Cognito has two parts, Cognito user pools and Cognito Federated Identity.
Cognito User Pools manages user creation, the storage of credentials, the allocation of groups etc.
Cognito Federated Identity, converts an authenticated user into AWS IAM credentials.
Cognito Federated Identity can use Cognito User Pools to authenticate, or Facebook, Amazon, Google, Apple, SAML or OpenID.
Cognito Federated Identity allows both Authenticate and Unauthenticated users.
You can switch from Unauthenticated users to Authenticated users.
You can use Cognito Federated Indentity to get a user ID by calling GetId.
The Logins parameter is optional. GetId will return a unique user Guid each time. You can then store that Guid Locally to track your user, and later if the User decides to signup, you can link that guid to an authenticated user. The link has iOS code examples.
AWS Mobile Hub (now Amplify) uses Cognito in the background, you can see the process flow here.

How do I secure an account that is created via OAuth Spotify

I would like users to register an account on my site via OAuth Spotify. I have the following scheme:
User authenticates via Spotify
Spotify ID and Mail are returned
An account will be created on the website (saved to the database)
The user can log in with his Spotify to access that account
The problem I foresee here is that someone can spoof the authentication by copying the ID of another user and it's mail, am I right? If so, what would be a better way to let an user create an account using Spotify Authentication? Let the user set a password? That seems user unfriendly to me.
So, how can I achieve this?
You can use the access token acquired through OAuth to find the associated username. You can use this as the basis for your accounts instead of a username or password on your own site. The process would be something like:
The User authenticates via Spotify
The Spotify OAuth callback returns a authorization code
You use the authorization code to get an access and refresh token for the user
You use the access token to access the associated User ID and use this as the unique ID for the accounts on your site.
Save an account with the Spotify user ID to your site's database
The user can log in again with Spotify to access their account (it will streamline the process by skipping the Spotify OAuth view, if they have previously approved your site, and are logged into Spotify in their browser)
Since your application will only retrieve the User ID from someone's valid access token, and the only way your application will receive that is if they log in through the Spotify OAuth flow, each account on your site will be linked to a valid, unique, Spotify user.
While looking into this, there are security considerations about using OAuth alone to authenticate users. I would look at this post on Security Stack Exchange and decide based on what level of security is needed for your site.

How do you give users in AWS user-pools access to other aws services

I have my user pool and federated pools linked.
I am able to sign up and verify a user however it does not register on the console in the user federated identity pool. It only comes up as unauthenticated.
What do I need to do in order to have my users stop showing up as unauthorized users and have them show up as users in my userpool?
It sounds like you both have unauthenticated identities enabled and are not correctly setting the User Pools token before communicating with Cognito after authenticating. Cognito Federated Identities thinks you haven't given a token, which is why you're seeing only unauthenticated ids. Give this docs page a read, the short version is the logins need to be set like this:
logins.put("cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>", session.getIdToken().getJWTToken());

Performing Google Federated Login/oAuth2 after initial Authentication

I am trying to support "Hybrid" Federated Login and oAuth2 (using logic from this document) for a webservice which will:
support Sign in using your Google account on my site. That is, from the documentation: You can also choose to use Google's authentication system as a way to outsource user authentication for your application. This can remove the need to create, maintain, and secure a username and password store.
Access the user's Google Analytics.
Here are the steps I have done.
I form my request to https://accounts.google.com/o/oauth2/auth with the scopes (Google Analytics) I want access to.
I Get redirected to google where it has my icon and which scopes I am requesting access to. I grant access.
I get redirected back to the callback page.
I get the tokens (access and refresh), as well as a huge id_token string (which I don't know) and store all of this information in my database.
I then make a call to https://www.googleapis.com/oauth2/v1/userinfo?access_token=xxxyyyzzz to get the user's email and name and store this information in my database too. I also notice it returns a id field which to my knowledge never changes and I presume is some sort of unique identifier. I store this too.
Question: If I go to Authorized Access to your Google Account section in my Google account, it shows that my site has access to "Google Analytics. BUT, it does not say Sign in using your Google account. This is what I am trying to accomplish. I would have thought using the logic would enable Sign in using your Google account. What am I doing wrong? And what would be the applicable call to google so that users can sign in to my site?
If your site has access to something like your Contacts or Analytics using OAuth, you'll never see "Sign in using your Google account". I'm pretty sure that's only if you use OpenID (not OAuth) only for sign-in.
Specifically, OAuth is used for giving you access to APIs to create/update/delete data, while OpenID is for signing in.
If you are asking how to identify user for future logins, you have two options:
Mix OAuth with OpenID, that is called Hybrid. I have described it on this answer.
Use userinfo scope and request userinfo (email, etc.) after successful OAuth authorization. It is described on Google OAuth 2 documentation.
If you mean automatically login to your web site in future visits you can use OpenID "immediate mode" (openid.mode parameter).
When the user is redirected back, you call the second request from your own (server-side?) code, and get their email address. When you successfully get it, that means that the user is logged on. You can add it to the session (e.g. as cookie), and as long as you have it, the user is logged on. You make the user log out by forgetting the email address, so by clearing the session/cookies.
Add this paramter to the https://accounts.google.com/o/oauth2/auth URL call: approval_prompt=force and then the Sign in using your Google account will always show regardless of whether the user was already signed into that or any other account.
So the call would be like this https://accounts.google.com/o/oauth2/auth?client_id=<client id>&redirect_uri=<uri>&scope=<scope>&access_type=<online or offline>&response_type=code&approval_prompt=force

For a hybrid SSO scenario using the Facebook iOS SDK, what's the best way generating a password/key for our own custom user records?

So my intention is to have a login in my iOS app that allows for either our standard email/pwd registration, or login with Facebook. We are also creating rest services to get application info for a given user, e.g. https://url/getPosts/[userId]?userPwd=foo
I've implemented SSO with fb in a web application before but I have some concerns about the security of authentication in a iOS client scenario. The key difference from what I've done before is that in a web app, I was making a server to server call to Facebook to get the access token so I was reasonably assured that the user was authenticated and the web server made privileged calls to the database. In the iOS case, I have the mobile client app making the Facebook iOS authentication request itself and the server has to somehow trust that this user from the client app is indeed authenticated against the matching user record in our database.
My question is how do I generate a durable and secret unique key from the iOS SDK so that I can create and associate a matching user record in our database for users that authenticate only with Facebook. I want this to be seamless so the user would not have to manually fill out another form, and we would just automatically create this matching user record in our db.
I could insert a record into my own users table when they fbDidLogin with Facebook, using the Facebook Id as the unique identifier, and the fb access token as the pseudo password/key for my own user record. I would have to validate the access token with Facebook to make sure it's valid before saving it as a password for the user (the user would never see this password, it would just be passed by the client app during api calls). That way when the user makes a call to our own rest api via the iPhone app we can authenticate and authorize using this secret/pwd/key.
An alternative that would make this whole question moot is to just handle the authorization logic on the client app, and check that there is a valid fb session before making calls to our own apis which I secure with just a single application-wide secret, but that doesn't seem as secure since getting that one secret gives authorization to data on all users. I'd rather authorize at an individual user level. Is that the right choice? Am I being paranoid about iOS security?
The fb access token expires so that might not seem durable, however if I enable offline access that token won't expire but creates a scarier looking oauth dialog window. An alternative to the access token is to hash the fb Id with an application secret key on the iOS client, and use that as the Facebook user's password in our db. However, that again is a single secret key that could perhaps be reverse compiled from the iOS client app?
Design for Facebook authentication in an iOS app that also accesses a secured web service
This post helped me undesrtand it more. If I am not mistaken, the flow goes like this:
User authenticates in iOS app
iOS app takes auth token, sends it to the rails app
Rails app takes auth token and sends it to graph.facebook.com/?auth_token=XXX to get back the user if authentication was successful.
Rails app takes the user info and matches/creates user in own database table. Sends some kind of authentication key back to iOS app.
iOS app saves the authentication key so it can use it to communicate with the rails app.
Let me know if I am missing anything.
Have you looked at the iOS docs for Single Sign On (SSO)? https://developers.facebook.com/docs/guides/mobile/#ios
You can share an app ID across mobile, canvas and web site and the same user auth works for each environment.
Check out: https://developers.facebook.com/docs/authentication/
Facebook Platform provides a number of ways to use the above OAuth flows in different app types, including Websites, Apps on Facebook.com, Mobile and Desktop Apps.
You just need to insert users Facebook key to your database to know if its authenticated with Facebook. Use OAuth at ios side authenticate user take users secret key send it to your rest web-service and save it with users other info.

Resources