I am starting to implement federated authentication with AWS Cognito using AWS C++ SDK.
I want to authenticate a user with Cognito User Pool and Facebook, Twitter, Google.
I understand that I can link several logins under single user identifier (Cognito identityId), but it is possible only when such logins are added manually after first login.
In example, I see scenario:
A user is registered using Cognito UserPool.
Then, staying authenticated, the user authenticate itself using Facebook. And Facebook tokens can are added to logins.
When further retrieving AWSCredentials call processes - the Facebook login will be added to the user identity at Cognito Identity Pool.
After, the user can login using UserPool credentials and through Facebook authentication under the same user identityId.
Firstly, I am not sure that my scenario is correct, but it is what I realized after reading many posts here and AWS docs.
And if the scenario is correct, then I am in stuck with another question: how to refresh tokens?
In AWS C++ SDK in order to refresh AWS Credential the call CognitoIdentityClient.GetCredentialsForIdentity is used, but it requires to pass user logins.
My more specific question: do I need to pass all logins? Does it require to have all access tokens in the logins no expired?
Adressing your first point, you can use federated identity without using cognito user pool. This means that you can simply autheticate a user directly with facebook, google etc and not add them to user pool. If you do want all users to be there in user pool then you will have to write the code to accept certain parameters from these authentication providers and then add them along with username and password to your user pool.
Now on to your question. To refresh token you have to use InitiateAuth. In auth flow you have to pass "REFRESH_TOKEN_AUTH" and in AuthParameters you pass the refresh token.
Related
I'm using Cognito with a user pool to provide authentication for my Ionic application application. The application use AWS Amplify to perform the Signup and Signin operation.
Now, I need to add facebook authentication so I added an external federated identity mapping also the facebook attributes to the corresponding Cognito user pool attributes.
On the application side I use the Facebook SDK to login with Facebook, receive Facebook's JWT token and call the Amplify federatedSignIn() to authenticate. The authentication works but no user is created inside the Cognito user pool (accordingly to official documentation "Whether your users sign in directly or through a third party, all users have a profile in the user pool").
Since the user is not created I cannot call the Amplify method currentSession() to get the token (to be used for lambda authentication) since there is no user.
Am I missing something?
This is the expected behaviour using federated identity. In order to use socials login through Cognito user pool its necessary to use Cognito's built-in hosted UI which is not supported by Ionic at the moment.
I don't understand auth. vs. unauth. user access within AWS Cognito. While learning about Cognito I came across several articles on the Internet and questions here within Stackoverflow concerning this and I'm just not grasping the concept.
I'm gathering that a simple use case for unauth. user access within Cognito is when we have users who need to access some AWS resource(s) who have an account but aren't "logged-in." But how is this possible? In other to get an access token, wouldn't you need a valid username and password? If by unauth. we mean a user who has a valid access token but can't access some resources [based on some user pool parameter], I suppose that makes sense, but I don't understand how Cognito works in this regard.
I've searched for hours on this w/o grasping this concept and I really just need a little help from the community if anyone would be willing to share.
UPDATE: What's confusing to me is that "unauth." is a non-logged in user already, no? Why do I have to or want to get an access-token for a non-logged in user? What is the purpose of this?
Something that is confusing when starting out with AWS Cognito, is that it is actually two services. Cognito User Pools is a user store that authenticates users and Cognito Identity Pools authorizes users.
Unauth:
When referring to a unauthenticated flow, you're skipping the authentication process and really just authorizing with an identity pool. To do this in code, you setup a credentials provider, and make a call to GetID. This generates an identityID in the identity pool and retrieves authorization tokens that give access based on the IAM role for unauthenticated users. Example here
Auth:
Now for the authenticated flow, before you authorize with the identity pool, you have to have authentication tokens. These can be retrieved by authenticating with a third party (Facebook for example), or with a Cognito User Pool. You authenticate with those services by providing a username/email and a password. The tokens delivered by those services can then be "passed" to a credentials provider. When done this way, authorizing with the identity pool will return access tokens that give access based on the IAM role for authenticated users. In addition, a user can "log out" and later "log back in" and they will be able to receive the same identity ID that was generated for them the first time they authorized with the identity pool.
I hope that all makes sense. I'll give an example of why you may combine the two
Example
Let's say we're building a web platform that lists events around our city. This platform needs to:
Store events in a database
Allow city organizers to add events to the database
Allow residents to view the events
We wouldn't want the residents to have to login to view publicly listed events, so when they visit the event's page of our website, unknown to them, they actually authorize with an identity pool. Thus they are provided unauth IAM role access to make a GET API call to our database, to retrieve the events.
Of course, we don't want just anyone adding events to the database. So for city organizers, there is a login form. This login form takes a username and password to authenticate them with a user pool. The user pool tokens are then used to authorize with the identity pool, giving them auth IAM role access to make a POST call to our API, allowing them to add events to our database.
I have an API service, which I'm going to deploy using AWS API Gateway with Cognito authorizer + Lambda as backend. This service will be used by our javascript client. Also, it should be exposed to end users as raw endpoints for programmatic access.
While it was quite easy to enable signup/login in js client using federated identities, I can't figure out the way to provide users with private access token to include directly in http headers.
Here are two authentication flows, I'd like to get in the end:
The flow for js client user:
User signs up with Facebook or Google.
User verifies his identity.
After login, user goes to the Profile/API Keys section in the interface.
User copies access token and can include it in http request header in any http client (httpie, curl, language libraries whatever)
The flow for admin created user:
Admin creates user.
Access token is generated for that user.
Admin passes generated access token the user.
User can include it in http headers to make request, as in previous flow.
An access token should be permanent, and can be regenerated by user at any time (think of Stripe API access keys).
The point here is to eliminate additional steps for the user to start using service programmatically. The closest thing in AWS docs so far is developer-authenticated-identities, but user should utilize AWS sdk anyway.
One possible way to accomplish this task is to use Custom authorizer instead of Cognito authorizer in API Gateway. Custom authorizer could implement logic based on e.g. auth header name and decide to either authorize in Cognito or to user API access token in database. I'm not sure, if it is possible, and if it is the major drawback is to reimplement Cognito authentication flow in lambda function.
The question is how can I accomplish such API access token (re)generation using Cognito or API Gateway?
The first flow should be possible with User Pools. Cognito User Pools now has a federation feature where you can federate using Facebook/Google and receive access token/refresh token depending on the flow used.
For admin created user, the user would need to authenticate before tokens are issued but this can be achieved by creating the user with a temporary password and signing the user in with that password, after which it can be changed and logged in again to receive access/refresh token.
The refresh token use case is that it can be used against the Cognito APIs to receive a new access token. When the refresh token expires (default is 30 days but it is configurable), the user would have to authenticate again.
I want to integrate a pretty standard functionality: give option to user (mobile and web) to either login with email/password or with facebook (google) account with RBAC (different users may have different roles, like users, moderators, admins, creators, etc). Here is basically what I want from sign in:
I went through a number of AWS tutorials and other materials. I got some grasp on how to implement it, but I still don't have a full picture. Hope someone can help me here.
Here is my current understanding (please correct me where I'm wrong).
1) For the email/password signup/signin I use a User Pool. When user signs-in I call authenticateUser (I'm using JS SDK):
cognitoUser.authenticateUser(authenticationDetails, {
..
})
where onSuccess
I store identity, access and refresh tokens, so, user
doesn't have to enter his credentials every time
Because users will be accessing AWS servicess (e.g. S3) I exchange idToken to AWS credentials
Store AWS creds in LocalStore for further use, when access resources
2) For the facebook sign-in I use Federated Identity
get a facebook access token
with fb token get a cognito identity
exchange a cognito identity to AWS creds and store those in LocalStore
Questions:
Q1. Is it valid and fairly complete logic for sign-up/sign-in? Did I miss anything?
Q2. How should I store facebook users? Can I do it in User Pools? I have impression that it's not possible, but that means I have 2 different user directories: one in UserPool and another one in another place (lets say in DynamoDB)
Q3. If I have to store users in different places (UserPool and DynamoDB) that means I have 2 users for essentially one user, who first registered with email/password and then decided to use facebook - this is inconvenience for both me as app admin and user. How to deal with this situation?
Q4. How to manage groups for users, who signed-in with facebook token (like users, moderators, admins, creators, etc)?
Q5. How should I restrict access to resources other than AWS for facebook signed-in users?
Q6. Any working example for this?
Thanks!
We added support for Federation through Facebook, Google and LoginWithAmazon for User Pools. This will create a user in user pool when a user logs in with federation. You can also capture the attributes from the identity provider using the attribute mapping feature.
Also if you use the app integration feature, Amazon Cognito User Pools wil generate a sign-in page like this for you.
Steps to SignIn/SignUp with a social provider through Amazon Cognito Console:
Configure a domain for your user pool like .auth..amazoncognito.com
Add any social provider and configure attribute mapping.
Enable the provider on the App Client.
Configure the callback URI, OAuth response type and allowed scopes.
Access your hosted UI at https://.auth..amazoncognito.com/login?client_id=&response_type=&redirect_uri=
Click on the button to SignUp/SignIn with Facebook (or your provider).
Authenticate with the provider, you will be redirected to the callback URI with tokens/code.
Check the newly created user in Amazon Cognito console.
I'm human and may have missed something, but that sounds pretty good to me.
You can't store a federated identities login in user pools. Thing of user pools as another identity provider, just like Facebook is. Dynamo (or something else) would be the way to go.
If a user logged in with both, linking those logins, you might want to consider avoiding user pools attributes entirely and only using dynamo. With two logins linked, Cognito federated identities only requires one login token to proceed, but user pools requires it's login token to see/update attributes. The user would have to login with the user pool to touch those attributes, it'd get messy.
I don't know that this is supported out of the box, like it is with user pools. You might have to do this using your hypothetical user database described above.
You can also link your user pool to Cognito as a provider, much like you do for Facebook. That's how you exchange an id token for credentials.
No official example from the service, though I can't speak for others.
i'd like to explain an auth flow and hope you can answer if amazon cognito the correct solution for this.
Requirements:
For every Login (Username/Password, Facebook, Google etcpp), there should be a valid User Pool account.
Flow Facebook (no identity or user pool account exists).
Customer clicks "Login with Facebook":
1) calling GetOpenIdToken -> with the FB AccessToken
1a) at the same time, use the FB AccessToken to fetch the email address from Facebook
2) calling AdminCreateUser with a generated password and facebook email
3) calling AdminInitiateAuth and fetch the idToken
4) calling GetOpenIdToken and add the idToken for cognito user pool and the facebookAccessToken
Result: a user in the Cognito User Pool and a linked federated account
Important is for me: the token from 4) is a user pool token and contains "sub" (UUID wich one is important for our internal database)
Ok, thats is ok and works good BUT:
Flow Facebook user comes back (identity and linked user pool account is available)
Customer clicks "Login with Facebook":
1) calling GetOpenIdToken -> with the FB AccessToken
2) calling DescribeIdentity and get the Login List
2a) we can see that there is a linked user pool id and don't need to create a new user
exact at this point comes the question:
how can i get a user pool token if i just have the facebookAccessToken, but a linked user pool login?
and is it possible to get the user pool data for that linked user just with the facebook accessToken ?
If this the correct flow or is this auth flow not supported by Cognito?
Thanks
Marcel
No this is not supported currently. You have created an identity in Cognito Federated Identities which has linked logins (FB and Cognito User Pools), but to authenticate with Cognito User Pools you currently cannot use Facebook access token. The only way to get the user pool token is by using the username/password for that account.
We have heard this request from multiple customers and would consider adding it in future releases.
Those Flows are not currently supported by AWS Cognito. You can build the customize flow on your identity api and just use cognito with Developer Credentials. But not recomended