AWS Cognito, Lambda, User credentials in DynamoDB - facebook

I established a authentication flow with Facebook Login and AWS Cognito on the client site. Works fine. But now I need a reference of the user with its facebook id in a dynambodb table. Of course I could just call a AWS lambda function exposed via AWS API gateway, but how can I verify that the API call actually has a valid facebook id and that this facebook id matches the AWS Cognito Id. Maybe I am missing something here, I hope you guys can point me in the right direction ;) thanks!

If you can key your ddb table by cognito id instead of facebook id, you can invoke api gateway with cognito credentials. If you use callee credentials when calling lambda you can access the cognito id via the token $context.identity.cognitoIdentityId. This ensures the call was made by the owner of this id. You can further check that $context.identity.cognitoAuthenticationProvider is graph.facebook.com to ensure they authed via Facebook. Unfortunately, the facebook id is not passed in the credentials, so if you need it you will need a lookup table mapping cognito id to facebook id. For more details on the available tokens see here.

I would suggest to do the following (I'm new to AWS as well, Let me know if you have any suggestions):
Create a API Gateway /fblogin endpoint where you will POST the Facebook Access Token (You will authenticate with Facebook on the client side to get this token). That endpoint is linked to a Lambda function say fb_login.
In fb_login function you will authenticate with Amazon Cognito to get its credentials. You should have created a Federated Identity user pool in Cognito and assign appropriate roles to assume for this user pool. This helps if you want to restrict your API only to those who are authenticated and authorized. So, the result from Cognito will have IdentityId and Credentials. You can return them as a result of your request to /fblogin.
Using the above result you can sign the requests you send to your API on API Gateway (Or you can use AWS custom generated SDK for your API to handle the signing). On the API Gateway endpoints, enable CORS and authentication as AWS_IAM. This way, API Gateway verifies the user automatically by checking the signature in the request. You can get the User Id from $context.identity.cognitoIdentityId as others suggested. This way, you can be sure that the user is authorized and authenticated.
Note: Make sure you implement /fblogin endpoint on HTTPS, then the FB Access token will be secure. If not, it will be visible as plain text over HTTP.
Also, use a Dynamo DB table as a log for CognitoID - FacebookID. You can incorporate this in the Step 2 Lambda function ifself or anything you think is appropriate.

Related

Extract roles from REST API in Keycloak

At my company, we need to extract the roles of the logged in user from the REST API that Keycloak provides. We have looked through the Keycloak documentation but can't find the answers we are looking for. Let me explain the flow we want to implement: A user logs in to a client defined in Keycloak and receives a JWT which is stored in the applications web client. The user is not an admin in Keycloak. When the web client makes a request to the backend server, the backend server queries Keycloak for the user's roles. And, this is the point where we have trouble. We can't figure out the correct URL for the REST API or which token to add to the authentication header.
To summarize: we need help with the URL which is needed to query for user roles and what token to send to authorize against the API. I'm aware that the roles can be retrieved from the JWT, but we are afraid that the payload will become to big over time. A user may have multiple roles in different departments.
The roles should be in the JWT payload, this should be configured in the keycloak service. The flow should be something like this:
User is authenticated by the front end and the JWT token returned by keycloak is stored
The front end hits the back end including the token in the request header
The back end takes the token, validates it using the public key (the public key is provided by keycloak), if the token is valid, the roles are taken from the token payload and the authorization process is executed

AWS API Gateway with cognito authorization

Currently I'm developing serverless architecture where there are set of resources and methods in AWS API gateway. I plan to add Cognito authentication(user pool) and authorization as secure layer to AWS API gateway.
There are 3 authorizer in AWS API Gateway which are IAM, Cognito User Pool and custom lambda.
For my use case, the sign-in and sign-up(authentication) are using cognito user pool via API gateway. It's perfect works. My user will given app client id and client secret to enable both processes. Once after sign-in, my intention is get user able to use the access token(returned by user pool) to access resource via api gateway.
However, my user can has different role such admin, owner or guest. User only can access the authorized api. My approach is to put user into different group in user pool, assign IAM policy to group and enable identity pool. This force me to change the authorization type in api gateway to IAM. and IAM require every request to be signed by Signature V4.
It means every requests have to sign up by session token, access key, secret (returned after exchange id token with federated pool) instead of using access token based approach. So in my use case, after my user sign-in via api gateway, my client app(web/mobile/postman tool) has to generate signature and put in Authorization header. Is there alternative ways to control authorisation in user pool group but using access token in api gateway? My understanding is access token (in Authorization header) is much easier to use than complex signed signature process.
Correct me if I'm wrong. Thanks.
Will this help instead?
Create groups in user pool and assign IAM role to the group.
And then add users to the group.
More documentation here: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-user-groups.html
You are on the right track but you have chosen one of the paths of Authorizing the user requests on AWS. You are using IAM and Identity Pool and because of that, you are forced to sign every request using Signature V4 provided by AWS.
Instead of going for I would suggest as per my experience to choose custom Lambda Authorizer over Identity Pool. In this case, your authentication will remain as it is that you have already built. But instead of applying IAM as Authorizer in API gateway, you can create a lambda function that will receive the ARN of the API gateway that the user wanted to authorize in the request and user ID_TOKEN that you received in during authentication from User Pool.
{
...
"cognito:roles": [
"arn:aws:iam::**********:role/addBookSellerRole"
],
"exp": 1565758916,
"iat": 1565755316,
...
}
You can see you will get the roles array from the ID_TOKEN in JWT received from authentication. You can use this role to fetch the attached policies to this role. Follow this document to fetch the policies from the role.
Once you get the policy JSON you can compare it with the ARN of the method received in request with the list of policies. And this way you have to generate a Policy Document that will either Allow or Deny the request.
To read more about it visit my medium blog Authorization using Cognito + API Gateway + IAM.

Azure Graph API - Query user information

I'm trying to figure out how to use the Azure Graph API to query a user's full name (first and last) from a given username. I understand I can do this with the following Graph API call...
https://graph.windows.net/myorganization/users/{user_id}?api-version
However, I am not sure how I go about getting an access token to use with this, because this process will be called without a user logging in, which is usually how we obtain an access token.
Is there anyway I can pass a username/password to a given URL using cURL or something and obtain an access token that way, so it is done behind-the-scenes?
There are two main authentication methods which are supported by OAuth 2:
Authorization Code Grant Flow
Client Credentials Grant Flow
The first flow requires a user agent to be present to sign into the client service and results in a delegated token. The second method does not require a user to sign in, as it only authenticates using the client secret; this results in an app only token.
If you want to create a background service that captures data from the AAD Graph API, you can absolutely do this using the Client Credentials Grant Flow, which does not require a user to be present at any point during the authentication flow.
You simply need to configure your application to to have app only scopes. Read here: Permission scopes | Graph API concepts. App only scopes all require tenant administrators to consent to the application in order to get access to data.
Finally, I feel I must mention that there is another less used flow specified in the OAuth 2 spec: Resource Owner Password Credentials Grant. This flow specifies how a client application who has knowledge of a user's username and password could directly pass those parameters and get an access token on behalf of the user. However using this flow is not good practice at all.
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application. The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viable.
We support this in our V1 endpoint, but not in our new V2 endpoint. You can read this blog to learn more.

API Gateway authorization for Cognito User pool+Identity pool

I am working on a web app where users can login/signup with their personal email addresses or login with federated identities like Facebook/Twitter. I have set up Cognito User pool and identity pool for the same.
After successful login , APIs hosted on API gateway would be invoked to display some data on the application. I would like to implement authorization for every API invoke call and return the response only for authorized users.
I have created User Pool Authorizer in API Gateway and I am able to authenticate users created in userpool based on the Id Token.
As per my understanding , to authenticate users from Identity pool , I can use AWS_IAM in Api Gateway. AWS_IAM may not be right solution for my application as API can be invoked by user in userpool as well as identity pool.
I am thinking of implementing authentication using Custom Authorizer using Lambda functions.
If custom Authorizer has to be implemented , should validating policy document based on the session token be sufficient to validate the users from both Userpool/Identity Pool? Kindly suggest alternatives for custom authorization,if any.
Thanks in advance
Have you seen this blog post? https://aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/
It's possible to directly integrate your Cognito user pools tokens as an authorizer for API Gateway, and it simplifies the flow you described greatly.

Separate APIs for User Login?

I need to create an API for login for my website.
There can be 3 ways for a user to login:
via Username/Password combination
via Google+ Token and EmailId
via FB Token and EMailId
Should there be a single API for this or should all the above exist as separate APIs? The output for the Login API will always be a token that will be used to make further authenticated requests.
I think it's more a matter of taste. I'd have a generic ProviderAuthentication API endpoint that receives a token id and another Authentication API endpoint that receives username & password. But you can also aim towards REST level 1 and have some generic Login resource (that contains username, password, providerToken & token properties) to work with a generic Login API endpoint.