AWS Cognito Resource server identifier and scopes Resource server brings - oauth-2.0

I've read docs and seen this. Struggling to put Cognito + API GW + OAuth2 pieces together. My questions:
Do I correctly understand the flow and use of Resource server scopes: client app asks the Cognito user pool for a JWT token (login/authorization happens). Request for a token contains custom scope A so as the Cognito returned JWT access token. After that client app uses obtained token making a REST API call to a "resource server" (say, to our configured API GW endpoint). API GW endpoint is set to use our Cognito user pool as authorizer + scope is set to be custom scope A. Thus scope here acts like a "role" or "permission": if client has a valid JWT token + this token has a custom scope A inside + API GW endpoint is set to use that scope - then client app is authorized to call API GW endpoint. Effectively it acts like a "resource-based IAM policy" for endpoint but no IAM is involved here.
Do I correctly understand that AWS Cognito Resource server identifier is an arbitrary string? It is not the URI of a factual "resource server" (our API GW). URI format is used purely for uniqueness and there is no place in flow where Cognito Resource server identifier matters or somehow checked/validated? Also it looks like that Resource server identifier does not affect JWT token generation or token contents?
thanks for clarif.

Application scope should not be confused with user permission. Scopes define the access an application has to the user's resources. Therefore resource access is the overlap of the two:
Check that the user has access
Check that the application has scope (access to user acccess)
Example
2 Clients with scopes:
A: E-Commerce (product:create, product:remove, order:create, order:update-status, order:read-status)
B: 3rd-party Order Tracker (order:read-status)
2 Users with permissions:
Customer (order:create:owned, order:read-status:owned)
Admin (product:all, order:all)
Therefore…
Customer PUT /product with client A = DENY due to missing user permission
Admin PUT /product with client B = DENY due to missing scope
…
By requiring a URI, AWS seems to enforce collision resistant identifiers as you point out. It's not a common practice and doesn't really have any real security benefit, nor is it validated by AWS that you control the resource.

Related

Azure requires Scope in client credentials grant

I have 2 registered apps in Azure AD - one is a webapi that receives a webhook from SendGrid with an access token. The other is the registration of the SendGrid app so that it can request a token using Client Credentials grant. Admin consent has been granted for the exposed API to the SendGrid app registration.
In SendGrid's webhook configuration on their server (the service is in beta), we are asked for client_id, client_secret and token endpoint. We also configure the web api resource url that it will eventually send the token and its webhook data.
In Azure identity platform, Scope is required but in the RFC it is optional. SendGrid does not configure nor send the scope. So these implementations appear not to be able to work together.
2 questions:
If you do not send a scope to some other RFC compliant token endpoint, presume this means the requester can be authorized but the jwt has nothing for audience?
If according to the RFC scope is not required, can the resource server check "this was meant for me"?
I understand we can validate the issuer and any extra claims but it seems odd that one of the validations that is emphasized most in Azure AD, Auth0 documentation etc is "audience" yet the RFC allows the scope to be missing in the token request. One of the answers here again emphasizes this requirement.
I wondered if a scope could be configured in the client app registration manifest if it is missing in the request but could not find anything that looks like that.
Thanks in advance for insights.
I'm not sure if this will fix your issue, but have you tried on the app registration with the expose an api configured, under it there is a authorized client applications section, try adding the other app registration id in there. I have anecdotally seen that even without requesting the scope, it will return that scope in the token.

AWS Cognito - using scopes in authorizing access to api gateway

I have setup a Cognito user pool so that I can use it to authorize access the an api gateway. It uses OAUTH2 and the flow im using is : Authorization Code Grant,
Scopes : email, openid and profile,
Allowed Custom Scope : product-api/read_product, product-api/create_product, product-api/delete_product
I use boto3 admin_initiate_auth command to connect to the user pool:-
response = idpclient.admin_initiate_auth(
UserPoolId=USERPOOLID,
AuthFlow='ADMIN_NO_SRP_AUTH',
AuthParameters={
'USERNAME':USERNAME,
'PASSWORD':PASSWORD,
'SECRET_HASH':SECRET_HASH
},
ClientId=APPCLIENTID
)
and the response I receive is a json object with several fields, which include access_token, refresh_token etc...
but when I use the access_token to access the api gateway, i get a 401 error. Unauthorised. Looking into the access_token it looks like the custom scopes have not been added.
Could you advise why the custom scope has not been added to the access_token and how do i get the custom scopes added ?
the api gateway has a lambda authorizer added.
Usually you have to specify the Scopes in 2 places:
The OAuth client entry for the client application in the Cognito section of the AWS console
The code requesting a token - I have always implemented this in a standards based manner whereas you are using an AWS specific solution
Looks like what you want may not be supported via admin_initiate_oauth:
Include user details in AWS Cognito Oauth2 token
If your client application is a web UI then the standards based solution will do what you want.
I've tested my Cognito single page app sample with custom scopes - you can run it here:
https://authguidance.com/home/code-samples-quickstart
Not sure if this type of solution will work for you though ..

Oauth2, scopes and user roles

I am asking a question conceptually here as I am trying to understand the relationship between scopes and user roles in an OAuth2 based system.
As I am implementing an API, I want to restrict access to specific resources by using scopes on the resources. I understand the use of access tokens to request resources, and I believe my understanding to be correct in that you specify your scope(s) when requesting the access token.
What I am not entirely sure of is how restriction of scopes would work based on specific roles that an authenticated user is in. Let's assume Bob is an admin and Sue is a regular user. We have some resources protected by an is_admin scope. What stops Sue from requesting (and receiving) is_admin scope in her access token?
I am thinking that what should happen is the following:
Bob authenticates.
Bob's roles are looked up after his authentication is complete. His "admin" role has the "is_admin" scope attached.
Bob asks for an access token with all the scopes collected from his various roles
Bob is automatically given those scopes for his access token
Is it up to my calling app to enforce only sending asking for the scope Bobs needs? Or is there something I am missing with regards to scopes?
Can someone please enlighten me with some simple examples?
In OAuth2, there are the following roles:
Resource owner - usually some person
Auth provider - the OAuth2 server
Resource server - an API that requires an access token and validates its scopes
Client application - application requesting an access token with some scopes.
To understand OAuth2, it's necessary to think about it as a protocol for access rights delegation from a Resource owner to a Client application. So the main use case is: the Client application wants to access the Resource server. In order to do that, the Client application needs an access token issued by the Auth provider and authorized by the Resource owner (which gets authenticated by the Auth provider).
In your description, the Client application is missing. Let's assume it's a frontend application for your API. It needs an access token with scopes admin-user-scope or regular-user-scope. So it redirect a user (Resource owner) to the Auth provider, requesting both scopes.
The Auth provider authenticates the user and asks him/her for a consent on granting some of the requested scopes to the Client application. The Auth provider may remove some scopes - for example the admin-user-scope for non-admins. The Auth provider may give the user a possibility to remove some scopes too.
The Client application receives an access token (or a grant) with scopes in a redirect URI. If the granted scopes differ from the requested scopes, the Auth provider sends a list of granted scopes (the scope URL parameter) along with the access token, so the Client application knows what actions it can perform with the access token.
Then the client application may access the Resource server and the Resource server makes sure that the provided access token contains required scopes. The Resource server uses the OAuth2 introspection endpoint to validate the token and to get a list of its scopes.

How are access tokens distinguished between resource providers in OpenID Connect?

I am working on creating an OpenID Connect (OIDC) Provider based around django-oidc-provider. I have been reading up on the OpenID Connect Spec, and I cannot figure out how access tokens are unique for a certain application.
Consider the following example with a user, Bob:
Bob wants to login to application A, so he goes to its interface and is redirected to the OIDC Provider. After authentication he is redirected (implicit flow) back to Application A with an ID token and an access token. He then makes a request at "/image/1" to A's API with his access token. The API uses the access token to reach out to the OIDC Provider to assert the user's identity as Bob. The API then returns the data at "/image/1" for user Bob, assuming that info exists. Bob continues to send his access token to A's API for any subsequent requests.
Then, Bob decides he wants to access application B's API. He sends B's API the same access token that he used with A's API. B's API reaches out to the OIDC Provider with the token and asserts the user's identity as Bob. B's API then returns the requested info for Bob.
What prevents this from happening? I see at least two possible solutions to this:
When reaching out to Google's token validation endpoint the "aud" parameter is returned. Application B's API would have to check this parameter to decide that the token is not valid for it's own API?
An additional scope must be added when requesting the token that is specific to the resource provider say "app-A-api". Then when an API is validating a token, the API would ensure the token contains the needed scope.
Which of these methods, or others, are in line with the OIDC spec?
If one of the above should be used, am I correct in assuming I should add a new /tokeninfo endpoint that returns the scope or aud, rather than add that info to the info returned at the /userinfo endpoint?
Any input is appreciated. I think a lot of my confusion comes from not seeing the "scope" param being used to delegate access to a resource provider in any OIDC examples.
I think the thing you are missing is that the application A and its API are two separate applications. So the tokens are issued for the application A. If the app-A-api uses the access token just for the user authentication, it's better to use an ID token - it can be validated without accessing the OAuth2 server. In this scenario, the app-A-api manages its user permissions by itself.
If the app-A-api needs the token to get a list of scopes (permissions) of its client, then use the access token. But in this scenario, the app-A-api (and app-B-api) are just accepting the access token - they are not the target audience (aud attribute) of the token. The application A is the audience of the tokens.
The APIs just check whether the access token contains scopes relevant for them. They trust the token issuer and it's up to the users to decide whether they trust the application A to perform actions on their behalf.
As an example, if a JavaScript application C (app-C) uses just Google Drive and Google Plus for its actions, then app-C will ask its user for an access token with scopes belonging to Google Drive and Google Plus. It will be just one token and both Google APIs will accept it.
And about the tokeninfo endpoint, it has it's own RFC called OAuth 2.0 Token Introspection, so you can check it.

Get a Unique OAuth token API from the WSO2 Identity Server

Our Mobile Client App uses https://identityserver:port/oauth2/token service from Identity Server by passing the ClientID and ClientSecret with grant_type as “client_credentials” to generate the access token. The generated access token is used to invoke the API from ESB.
As per the implementation the ClientID and ClientSecret will be stored in the device.
For an example, ClientX requested for an Oauth Token which will have a certain expiry time. Can this token make as a unique for ClientX?
Currently all the upcoming client calls will get the same access token as its already generated from the request of ClientX. If a client is requesting a token very late it will get the same token with almost expiry time.
Is there a way to make this token unique for the Client?
In your case, if you use “client_credentials” as a grant type, resource owner is also the client.
Since this is a mobile application, once your mobile app gets the token it will be used until the expiry date and there will not be a necessity of changing it, because of mobile is belongs to a single user. Therefore the token would be same for same scope till it is expired.
Ex: BBC news mobile application.
If you need different access tokens, you need to use different scopes.
You will need different access token in case if different clients accessing the same API. In that case you may use “PASSWORD” grant type for a unique access token.
Ex: Purchasing a product using ebay.
So you should define your scope properly to identify the use of access token.
Find the following blog that will help you to guide to select your scope. [1]
[1] http://wso2.com/library/articles/2014/02/securing-your-web-service-with-oauth2-using-wso2-identity-server-1/
I will assume that mobile application instance is bound per user.
If you want to get different access tokens for every user bound to a session don't use client_credential grant type.
For example you have client-x and client-y both using client_credentials grant. Identity Server (Authorization Server) will give an access token for client-x and client-y since this is about authorizing client-x and client-y to access resource and not about authorizing a user. This means whatever user you have in client-x or client-y requesting access_token, they can get one (assuming they are authenticated).Vice versa, a user, even if authenticated both client and identity server cannot get an access token if the request comes from client-z (client-z is not registered in identity server)
If your Oauth 2.0 client is browser-based you can use implicit grant, if it is a server you can use either authorization grant or resource owner password credential.

Resources