What is the difference between these two approaches of initializing a new AmazonCognitoIdentityClient?
AmazonCognitoIdentity identityClient = new AmazonCognitoIdentityClient(
new BasicAWSCredentials("access_key_id", "secret_access_key")
);
identityClient.GetOpenIdTokenForDeveloperIdentity()
-
AmazonCognitoIdentity identityClient = new AmazonCognitoIdentityClient(
new CognitoAWSCredentials ("IDENTITY_POOL_ID", "REGION_NAME");
);
identityClient.GetOpenIdTokenForDeveloperIdentity()
Although most examples on the internet show BasicAWSCredentials being used to instantiate a CognitoIdentityClient, but the method signature in the doc says it accepts AWSCredentials class - both BasicAWSCredentials as well as CognitoAWSCredentials are subclasses of the AWSCredentials class. Hence, i am assuming both should be working normally i guess???
I am trying to understand how will this difference, impact the following:
privileges,
timeouts,
etc?
API reference for cognitoIdentityClient constructors is here: http://docs.aws.amazon.com/sdkfornet/v3/apidocs/index.html?page=CognitoIdentity/TCognitoIdentityCognitoIdentityClient.html&tocid=Amazon_CognitoIdentity_AmazonCognitoIdentityClient
In client device you should instantiate AmazonCognitoIdentityClient client using CognitoAWSCredentials. Using STS service, AWS client will obtain temporary credentials that will let the client assume the role you previously defined in your identity pool. Typically this role would have very limited access to your AWS resources. (S3 upload to a specific bucket etc.) This is like giving out to people a special type of your car key which can only turn on the music system, not the engine.
On the other hand GetOpenIdTokenForDeveloperIdentity is a special API call that needs developer credentials. You should never deploy developer credentials to any client device and you should keep it only on your server. Once you instantiate a AmazonCognitoIdentityClient using developer credentials on your server, you can expose a REST endpoint for clients to obtain OpenId token (for a given identity id or creating a new one). Let's assume that your users are logging in to your API using their username and password and you return them a custom access token which is stored in your database. After that your endpoint may implement this logic:
Fetch unique identifier for your user using custom token (user id, username, e-mail etc.)
Use LookupDeveloperIdentity and find out the identityId for the given username.
Use GetOpenIdTokenForDeveloperIdentity with found identityId and send back to the client. So they can "login" to that identityId.
If this user has not any identityId assigned to its username, create a new one and send back.
As you see developer AWS tokens are enabling a couple of sensitive API calls. Now let us assume that client had developer access token and thus has access to GetOpenIdTokenForDeveloperIdentity call. Then they would be able to generate OpenId tokens, switch to other people's identities easily and access their private data.
If you don't use developer authenticated identities (https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html) you do not need GetOpenIdTokenForDeveloperIdentity mechanism though. If you are using only public authentication methods (Twitter, Facebook etc.) you should ignore the second paragraph and use CognitoAWSCredentials.
As described in Çağatay's answer, the BasicAwsCredentials are instantiated with your developer credentials. What he described about when to use each constructor is absolutely correct in every case other than developer authenticated identities.
Since this code will be deployed on a back end service, it's exposure is less of a concern. Mobile clients will communicate with this server and get the token from it, with which they will get credentials. The credentials are never exposed to the user in this pattern.
As you can see in the Cognito documentation, the sample has BasicAwsCredentials. An end to end sample is visible in this blog post.
Related
I have a Django Rest API with JWT authentication which is the backend for a Angular frontend. There are many clients who use the service with our frontend. Now some enterprise clients wanted to integrate the APIs from their system's backend. I don't want to remove JWT from current APIs. I am planning to create new APIs in the same backend with OAuth token for those users.
I wonder what is the best way to implement OAuth for this scenario.
I am thinking Client Credentials grant type is the best way.
Question1: Am I right that client credentials is the right approach ?
For those enterprise users, it is sufficient they get just access token through the UI interface so that they can access all our APIs.
But here the problem is one additional step of getting the Client ID and Client Secret first and using that to get Access Token.
Question 2: What is the use of client ID and client secret ?
Question3: Should my backend hide the process of generating Client ID and Client secret and just give Access token (or) give them Client ID and Client Secret and ask then to generate access token ?
Question 4: If I am giving them Access Token without client id and secret, is that fine to have infinite expiry time? and
TLDR; How to implement OAuth when the resource server and auth servers are same ?
There are 4 grant types in oAuth2 which is meant for different scenarios.
client credential : the consumer (app) make calls to back-end using the bearer token created using apikey(or clientId) and secret only. Mostly used for anonymous calls where generic information is retrieved.
Resource owner password credential (ROPC) : the consumer (app) make calls using the bearer token created using apikey, secret, username and password. Mostly used when you(your authorization server) already know the users(user database is handled in your own system).
Authorization code : the consumer (app) make calls using the bearer token created using an authorization code. The authorization code is provided by a 3rd party (which actually has/manages the logged in user data) and the created authorization code linked to the logged in user. Google and Facebook log in for various sites is a typical example. Facebook/Google gives an authorization code for those websites and they exchange that code for a token.
Implicit grant : Mix of password credential and authorization code. Instead of authorization code, you get a bearer token from the 3rd party authorization server.
Question1: Am I right that client credentials is the right approach ?
I think you can use CC if there is no user level logics in your backend. If userlevel involved, may be ROPC is a better choice
Question 2: What is the use of client ID and client secret ?
Client ID and Client Secret is very similar to username and password in an application level, which is used to obtain bearer token.
Question3: Should my backend hide the process of generating Client ID and Client secret and just give Access token (or) give them Client ID and Client Secret and ask then to generate access token ?
If you are implementing oAuth2, your consumer should create the access token. But looking at your use case, may be even a simple hash of userId+timestamp is sufficient. ;)
Question1: Am I right that client credentials is the right approach ?
Yes. Providing the new APIs do not need to be called in the context of an end user.
Question 2: What is the use of client ID and client secret ?
The client ID allows the auth server to identify the application
requesting the token (it's often carried through to the access token
too, allowing the API to identify the calling application).
The client Secret means the auth server can trust that the client is
genuinely who he says he is as only he should have the private client
secret for his public client ID.
It's effectively a username and password in this scenario.
Question3: Should my backend hide the process of generating Client ID
and Client secret and just give Access token (or) give them Client ID
and Client Secret and ask then to generate access token ?
Your Auth server should issue the client credentials to the application once and the application should provide those credentials every time they wish to obtain a token via the client credentials grant type.
authorization code grant, or implicit grant might be more suitable for this scenario. The first one allows you to add an authentication step before the tokens are returned to the users (might be useful if you want to integrate your JWT authentication to this as well) and the second one is mainly used for single-page applications, and does not include an intermediate authentication step. This one would be useful if you want to improve efficiency.
client_id and client_secret are given to you when you register a client application in your identity provider(authorization server). This client application does not mean an application or an API belonging to your clients, but your own application to which you plan to incorporate OAuth(and OIDC). These two parameters are useful when making the requests to authorization in order to obtain tokens. The server uses those values to determine whether the request is made by a valid application. Only you have access to those values as you will be the one who's registering the application with the server.
I think this question is answered in the previous section.
I think it would be better if you go through this before doing any implementation. It provides most of the basic knowledge you should have before implementing an OAuth system. I hope this answer was useful to you.
I have just started with Amazon Cognito and I want to use it for my web application. I want to develop a stateless app, in which I SignUp/SignIn using Cognito and then using the JWT token in rest of the requests.
I have implemented sign-up and sign-in flow in Node.js using amazon-cognito-identity-js package and then using the JWT token to call a lambda function using aws-sdk. Things are as expected till here.
But now the issue is with different user operations like get attribute, verify attribute, update password etc. as listed #
https://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-javascript-examples.html
All of these operations require cognitoUser object and in the documentation they are using userPool.getCurrentUser(); expression.
And I have read somewhere that this method returns the last authenticated user. So I think this expression userPool.getCurrentUser(); will cause conflicts. For example if UserB logs in after UserA and UserA tries to update his password, it will not work.
Can someone suggests me what are the possible solutions?
Should I store the cognitoUser object in session at server side ?
[This solution breaks my stateless requirement and I will have to maintain session on server side.]
Is there any way to perform these operations using JWT token ?
Please suggest if you can think of any other better approach to implement Cognito in web app.
Thanks.
We have a stateless app using cognito and lambdas.
The way we have set it up is to not call lambdas directly but to use Api Gateway and lambda-proxy integration.
If you call lambdas directly from your front end code and are using the cognito tokens for authentication then you need to put a lot of logic in each lambda to validate the token, e.g. download the relevant keys, check the signature of the jwt, timestamps, issuer etc. If you use API gateway then you can just create a cognito authorizer and place it in front of your lambdas.
We pass the id_token when making api calls, then the call is validated by the authorizer and the lambda receives all the current attributes set up in the user pool. This means we don't need to make additional calls to get attributes.
For changing the user passwords this can be done from the front-end of the app by calling the cognito api with the access_token if you have allowed it in the user pool client setup.
I'm just trying to get a handle over this framework and I want to confirm that my approach is correct.
I can authenticate my own user using the method: getOpenIdTokenForDeveloperIdentity and supplying an IdentityPoolId and a Logins key-pair with my Developer provider name and a token which I provide.
Now, from what I understand, when the user logs into a second device, in order for Cognito to understand that this is the same user, I have to provide it with an IdentityId. However, I'm not sure of the best way to get the IdentityId programmatically so that it will match up with the initial login.
The only technique I can think of is to store the IdentityId in my own DB and provide my own method for retrieving it. Is this the best way? Or should I be working with this framework differently?
I'm still a beginner to AWS in general and I'm just trying to understand the best practices for this framework.
BTW, I'm implementing the Android SDK and the PHP SDK for my backend.
When you use getOpenIdTokenForDeveloperIdentity, it returns the identity id associated with the user identifier you provided. So if the user identifier you use is the users' username, when you call getOpenIdTokenForDeveloperIdentity with that same username from the second device, it will return the associated identity id. There is no need to store the identity id unless you want to, it is provided to you each time you call getOpenIdTokenForDeveloperIdentity.
This blog post may be of further help:
http://mobile.awsblog.com/post/Tx2FL1QAPDE0UAH/Understanding-Amazon-Cognito-Authentication-Part-2-Developer-Authenticated-Ident
When you use Cognito, your user first authenticates with an Identity Provider (such as facebook, google or other Oauth provider), and the token you get back from it is sent to Cognito and is the key to tying your users information together across logins on other devices.
You don't need to store this information in a database, unless you are writing you own custom identity provider and not using one of the public ones available.
There are three communicating parties in our system:
Frontend
Service A
Service B
plus we have stand-alone security token service, our identity provider.
Authenticated user interacts with Frontend, it calls Service A, which in turn calls Service B. User's access token is passed through this pipeline using "poor's man identity delegation". Service A and Service B authorize (or not authorize) user's actions based on claims in passed identity. Everybody is happy!
But now I ran into situation when Service A has no user context during operation. It happens:
during startup
when Service A processes message from message bus
when timer fires
In each cases Service A needs to call Service B to obtain some data, but it receives 401, because no access token passed to Service B.
Are there any best practices how to handle such situation? The only idea I have in my head now is to register 'System' user (possible user per Service A, Service B, Service C etc.) in our identity provider, obtain access token for this user and use it in cases described above. But I smells bad for me and I'm looking for alternative ideas.
Any suggestions would be appreciated. Thank you!
Short answer would be: If you have no one to Act As then Act as yourself.
Even when using "poor's man identity delegation" Service A authenticates at STS using some sort of mechanism. In the link you posted a certificate is being used. So implement a new way of getting token. You already have a method which gets ActAs token so now you need to implement a method that will get user token (for Service A).
Your STS should already know this "system" user because it is allowing him to request ActAs tokens. You just need to assign some claims to the system user that will define what it can do even when it is not acting on behalf of a any user.
I'm trying to implement OAuth 2.0 for my API. I'm using a third party library to act as the basic OAuth provider, django-oauth2-provider,
and Tastypie as the framework. Those details shouldn't matter too much. The OAuth 2.0 works -- when a user is created, an OAuth 2 client
that manages the user's secret_key and their id is created. A customer can then supply the user ID they get back from the user creation
endpoint along with their username and password to get an access token which allows them to use API endpoints.·
Where I run into issues is retrieving the client id (which must be passed into requests for the access token). Obviously when a user is first created
I can return the client_id with the HTTP response. After that, however, there will obviously be cases where the user doesn't have their client id·
stored locally (this is a traditional user/app setup, not something like Google APIs where your client id is always visible). I want to protect
GET requests to the customer resource with OAuth, but that means I can't query the API for a given user's client ID. And it seems like the whole point
of OAuth is defeated if I can always just pass in a username and password to retrieve my client id from some oauth endpoint. Am I thinking about this wrong?
Also, from reading the OAuth specs I'm under the impression that a client id and client secret are all that should be supplied for getting granted an access token. Yet the implementation I'm using defaults to forcing the user to supply a client id, client secret, username, and password. I've overridden the implementation to require only the client id and secret, but I want to make sure that was the right call and I'm not missing something.
Edit for flup's response:
I'm dealing with a Django API as the resource server, and a user of an iPhone app as the resource owner. The iPhone app is directly associated with the server -- in other words, there are no third parties involved here and no plans to involve them in the future; all software is ours. I would think that the password flow would be what I would need in that case. Indeed, that seems to be what django-oauth2-provider supplies by default. I'd like to stay somewhat in line with what they are doing to not have to completely reinvent the wheel.
The goal of oauth2 is to let the resource owner give a client a valet key which authorizes it to access certain resources on your server on his behalf.
If there are no third parties involved, there is no client to authorize and no need to use oauth2.
Instead, you could use the standard authentication mechanisms present in tastypie.