Okta SAML attributes, Cognito and acces tokens - amazon-cognito

We are using OKTA SAML as an iDP along with Cognito as a SP.
We have groups that are assigned to the users, and these attributes are mapped are part of the Okta SAML config.
The issue is the following - on the Cognito side, we get 2 tokens - id_token and access_token.
These groups appear as part of the decoded id_token as "custom:groups": "[Group1, Group2, Everyone, Group3]", - which is what we want.
Is it possible instead of these groups to appear on the id_token side, to be on the access_token?
If that is not possible is there a workaround with some other kind of attributes to appear as part of the claims in access_token?
Best Regards

Related

Can I federate Cognito with "client credentials" flow (or other way to trust a server-side application authenticated elsewhere?)

I have an AWS REST API Gateway with Cognito authentication using the client credentials grant.
We have been creating new clients by hand and sharing the ID/secret with people who need to use our API. They send the ID/secret and "grant_type=client_credentials" to Cognito, it gives them a bearer token and they use the API with the token. All fine so far. (It is a CLI tool running on a schedule, not accessed by a browser. I specifically need to avoid any sort of "go to the browser to login".)
Now, we have a new "island" of users who have a local OIDC (Azure AD) provider that can issue them a bearer token from a curl to an endpoint.
Is there a way to make Cognito accept those tokens??
I have tried federating Cognito with a different oidc provider (I don't have AD, but a different provider), getting myself a bearer token from it and sending it to the API GW, and I just get 401'ed. I don't know if there is something I'm doing wrong or if it's not possible.
(Things I might be doing wrong seems to be a long list! I need to create a client in the other provider and add it's ID/secret/URL to Cognito, that works. I used the same client ID/secret to generate my bearer token. But when I'm in client creds flow in Cognito, I need to set a custom scope. Do I need to add that scope to my initial request to the other provider (The API GW doesn't require a scope, it is just a mock endpoint at the moment in testing). The client_id= in the request is for the client in the other provider, not the Cognito client ID. Should I set it to the Cognito client ID?)
OR do I need to write a custom authenticator for the API GW to validate the token? (Decode JWT, Check : issuer is allowed and signature is valid.)
And not use Cognito at all for these other users.
(If it was an HTTP API, I think I can create a JWT authoriser and it does it all for me, but it isn't and there are some features on REST APIs not available on HTTP (like WAF))
Sorry it's a bit short on details. I could spend days copy/pasting all the configs from ID provider/Cognito but if it fundamentally won't work I wasted my time!
(After trying it, I think maybe federation only works for actual users with a browser based login flow, not clients with a CLI flow. I can't find anyone saying client credentials flow does work anyway!)
Cognito is using the authorization server role. So in all cases, the tokens returned to client applications will be issued by Cognito. These apps will never deal with Azure AD tokens. Multiple types of client can coexist together:
CLIENT CREDENTIALS GRANT
Clients who use this flow might represent B2B connections. The business partner must always get Cognito tokens directly, and no federation is used here.
AUTHORIZATION CODE GRANT
Browser clients will use this flow, and you can configure Cognito to implement authentication by making a second OIDC Connect redirect to Azure AD.
My blog post provides a walkthrough on how settings are configured. Cognito will act as a client of Azure AD and use a scope such as openid profile email.
After a user login, Cognito will receive Azure AD tokens, validate them, then issue its own tokens. Nothing will change in the API gateway, which will continue to verify Cognito tokens.

Is it a good practice not having OAuth in multi tenant applications in AWS Cognito?

We have a multi tenant application with supporting role based access by getting users' attributes like tenantId, role etc. from a datastore in AWS Custom Authorizer Lambda and injecting tenant and user specific information into request context. However, we are not using OAuth 2.0 flows for users authentication and authorization. It is a classic username/password registration in AWS Cognito to get a valid JWT access token which is validated again in our Custom Authorizer. I was wondering if this is a good practice or should we introduce an OAuth 2.0 flow like Authorization Code Grant? AWS Cognito doesn't have the same capabilities as AuthO has which means we can't figured out a way to limit user's accesses to specific APIs which are protected with specific scopes. For example; userA has weather-api:write and userB has weather-api:write and weather-api:read scopes who are from the same tenant. There is no way configuring this approach with one Cognito AppClient.
I appreciate for any comments. Thanks!

Why shouldn't I use IdToken as bearer token in an IDP context?

I am using an IDP platform (here AWS Cognito but that could be Auth0, OKTA or Keycloak) and I was wondering why I was discouraged to use the ID Token as an authorization token.
To be more specific, I will not make use of a resource server with authorization delegation from a user to a third-party app. My IDP will just let me SSO all my users on my different applications. There is no scope to grant here, only authentication claims that each service will use to grant or refuse access to resources (like an email, user ID, or the roles).
I understand I could provide my application with the id token and then create some session for my user. By why shouldn't I use the id token itself as a stateless session token, given that its signature can be checked on each application's back-end ?
And if I should use an access token over the id token - can I replace scopes by roles ? Or how should I understand the scopes in a non-delegation context ("user is usign the app himself, not giving permission" vs "user is giving all scopes to the SPA front-end which is an application in itself")
By the way, I am recovering the tokens through code PKCE flow on the front end.
The ID token only contains details about the user and how the user authenicated. so its perfect for creating a longer lasting cookie session with the user. The default lifetime for and ID-token is very short as well, like minutes. You typically throw the id-token away after establishing the sesson. You should never ever pass the ID-token around to other services.
The access token is mean to give you access to the APIs that the token is intended for.
when the user signs in, you ask for acceess to certain scopes and the scopes selected (consented) by the user , then is included in the access token (as scopes and audience claims).
In theory you can pass the ID-token to an API, bits not how its supposed to work.
See this and this for more details:

Should I store the cognito auth token in my database?

I have a mobile application which needs to be GDPR compliant. We're using AWS amplify and appsync, but we're unclear on how the Cognito auth token is used. Do we need to store the token in our database to associate it with users?
Our concern is that once a user is authenticated, the client will not know which userdata is associated with that identity unless we store the auth token.
You don't need to store tokens. Cognito Auth token are JWT tokens. JWT tokens can have custom payload within them. Everything you need is already included in it. You can pass literally anything like userId, phoneNumber etc... any custom data when you are issuing the tokens.
For example, if you trigger lambda with apigateway and use cognito pools for authorization you will automatically get sub etc in the claims field which you will identify user in the client (in this case client is lambda)
If you are using custom lambda authorizers you can still use cognito user pools but this time you are absolutely free to embed any custom data into token to use it later.
Play in jwt.io with your tokens and you will see whats in it already.

OAuth 2 access_token vs OpenId Connect id_token

Although I have worked with OAuth 2 before, I am a newbie to Open ID Connect.
Reading the tutorials and documentations I have come across both access_token and id_token where access_token is the random unique string generated according to OAuth 2 and id_token is JSON Web Token which contains information like the id of the user, algorithm, issuer and various other info which can be used to validate it. I have also seen API providers who provide both the access_token and id_token and as far as I know it is for backward compatibility.
My question is that is it possible to use both the access_token and the id_token for accessing the protected resources ? Or is the id_token just for verification purposes and access_token is used for getting access to protected resources ?
Originally, OAuth and OpenId are designed for different purpose: OpenId for authentication and OAuth for authorization. OpenId Connect is a unification of the two and serves for both, but does not change their original functionalities. Keeping that in mind, you should be able to find out yourself. ;-)
The id_token is used to identify the authenticated user, e.g. for SSO. The access_token must be used to prove access rights to protected resources, e.g. for the userinfo endpoint in OpenId Connect.
Another angle to provide an answer:
id_token
An id_token is a JWT - make note of that!
It contains claims about the identity of the user/resource owner
Having a valid id_token means that the user is authenticated
access_token
An access_token is a bearer token
A bearer token means that the bearer can access the resource without further identification
An access_token can be a JWT (see Appendix point 1.) or opaque
If you want to read more: Types of tokens in oidc and oauth
access_token is useful to call certain APIs in Auth0 (e.g. /userinfo) or an API you define in Auth0.
id_token is a JWT and represents the logged in user. It is often used by your app.
is it possible to use both the access_token and the id_token for
accessing the protected resources ?
Not completely, first, you need to use id_token to log in,
second, you will get a accessToken,
last, use accessToken to access data.
Here is an article that describes why the id_token was introduced and what was it's initial purpose: Why we need a id_token in OpenID Connect & Facebook Connect. In short they tried to standardize the Hybrid Flow that was used by the Facebook.
We considered was using the id_token as the access_token.
We rejected that option because:
Many providers have existing OAuth token formats for there endpoints that wo uld be difficult to change.
We don't want long term access tokens being stored in the browser as cookies.
There are clearly separate recipients of the two tokens overloading the semantics of the two tokens would reduce flexibility and increase complexity in the long term.