I followed the tutorial https://github.com/jcbsmpsn/gke-rbac-walkthrough to grant a service account access to GKE and it worked but later the service account token expired and I had to renew it. Is there a way to make the token non expiry?
When access token expires, refresh tokens can be used to obtain new access tokens. It is the Authorization Server that will issue a refresh token to the client which is then used to obtain a new access token. This is done at (d) as per this Protocol Flow, basically the refresh token is included with the access token when it is being issued.
This documentation provides more details regarding the process of refreshing an access token.
Related
I'm using AWS Cognito for authentication and authorisation in backend API's. If user sign in using Cognito, I get access token,id token and refresh token.
In this scenario i will use id token for authentication and authorisation purpose. If the id token expires I will use refresh token to generate new tokens.
But, if I use Google as Identity Provider. After successful user creation, I'm getting only the access token and the id token. Its expiry is 1 hour also. After 1 hour how can i maintain user authentication in this scenario ?
Is it possible to generate refresh token after Google authentication from Cognito ?
This is the url I'm using for Google signup/signin :
https://{DOMAIN_NAME}.auth.{REGION}.amazoncognito.com/login?response_type=token&client_id={CLIENT_ID}&redirect_uri=http://localhost:5000/
According to your sign in URL, you are trying to use Implicit grant flow here (because response_type=token).
Cognito should not return a refresh token for Implicit grant flow. That is the intended behaviour according to the specification:
The authorization server MUST NOT issue a refresh token.
Also using the implicit flow is highly discouraged due to vulnerabilities.
Please consider using Authorization code grant flow along with PKCE. With that you can get the refresh token.
The reason you get the refresh token along with Cognito, UserName/Password is because it should be using a different Auth flow (example: USER_PASSWORD_AUTH).
We are working on switching to Cognito as the 3rd party OAuth 2.0 provider for our backend services.
Our legacy system had its own Spring Authorization Server (deprecated) for generating and verifying access tokens which enabled us to add custom claims to Access Token itself, there was no need to carry around Id Token to extract information about the authorised user.
But Cognito pushes us to use OAuth 2.0 standards naturally, and there is no possibility to add custom claims to Access Tokens. Id Tokens are used for extracting custom claims and user information throughout an authorised session.
This brings us to a situation where we need to have Id tokens in the backend service sessions for the endpoints that needs some user info in order to process requests. But to fetch the Id token from the Cognito provided /userInfo endpoint, Access Tokens need to have openid scope, but to have the openid scope in the Access token, we need to use Cognito Hosted UI which is not applicable for the mobile app and our legacy Web app.
So either we need to use Identity Token as the Bearer token(not advised by standards), or we need to expect ID token with a custom HTTP header along with the Access token. Is there a huge security risk if ID tokens are used also for enabling access to REST API's ?
I am building a Smart Home skill for Alexa, and as part of the skill, I need to use the Login with Amazon OAuth server. I have managed to get to the point of handling the initial authentication of the user by handling the AcceptGrant directive and requesting access tokens from LWA. The problem that I am having is how to uniquely identify the user after the authentication is complete.
Amazon's documentation states the following about uniquely identifying customers:
Store the access and refresh tokens with the grantee access token so that you can always associate the tokens with the customer. Store the tokens in a secured location, such as Amazon Web Services (AWS) DynamoDB or a secure token store in your device cloud.
Source
I have followed this advice and, as part of the authentication process, I use a simple DynamoDB table to store the grantee token as the primary key and the access and refresh tokens as associated with it. Then, when a future request comes in, I use the access token from the directive to look up the user in the table. This works fine until the token expires, at which point, I am no longer able to identify the user, as I cannot find an entry in the database. I understand that I am supposed to renew the token, but how can I do that if I can't find the user for whom I am supposed to perform the renewal in the first place?
I have tried finding a solution in the Amazon developer documentation, but all I have come across is the following, and it is too vague to be helpful:
Once you have the token, verify that it identifies a user in your resource server. The token could become invalid for multiple reasons, for example:
The user deleted or canceled their account with your service. For example, an Alexa user might have set up account linking with My Lights, then later canceled their My Lights account. At this point, the token stored by the Alexa service would identify a non-existent user.
The token has expired, and the Alexa service was unable to obtain a new token. This can occur with an authorization code grant if your authorization server does not provide refresh tokens.
Source
I am using an AWS Lambda function (Node.js 14.x) to call Cognito revokeToken function to revoke a refresh token.
According to the official document, "revokeToken" will:
Revokes all of the access tokens generated by the specified refresh token. After the token is revoked, you can not use the revoked token to access Cognito authenticated APIs.
While I can successfully revoke the refresh token & associated access tokens, previously created access tokens can still be used to access API Gateway resources (with Cognito User Pool authentication enabled).
Why can I still authorise requests to API Gateway after using Cognito's RevokeToken method to revoke access tokens?
Your refresh token & access tokens created using that refresh token are being revoked however, API Gateway will not pick up on this & still allow access.
The reason for this is that API Gateway uses the identity token to authorize API calls, not the access token.
The documentation (very unclearly I must admit) mentions:
After the token is revoked, you can not use the revoked token to access Cognito authenticated APIs.
In this case, what is meant by the above is that the token is revoked for API actions that actually belong to Cognito, not services which use Cognito for authentication.
This is why you can still authenticate with API Gateway as it will internally use the not-revoked ID token.
To demonstrate this, the typical Cognito authentication result will look like this:
{
"AuthenticationResult":{
"AccessToken":"eyJraWQiOiJvZ2JFM2xXN0FWeEpPZjJWRU50MW9RNnRrY3ZOdVRJUUNTZkJpczlBWDFBPSIsImFsZyI6IlJTMjU2In0.eyJvcmlnaW5fanRpIjoiOThjM2QyNTgtYWU1NC00MzBiLWEwNjktYjg4OGZhNWQ5YzkwIiwic3ViIjoiZWE5MGQ2MjktMWI3NS00Y2ZiLThkOWQtZGRmZWJhZGZlZGYzIiwiZXZlbnRfaWQiOiJlODMxZWI1MS1mMjM3LTRhNDctYTM3YS1jNTk5MzBkNzFkZDgiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6ImF3cy5jb2duaXRvLnNpZ25pbi51c2VyLmFkbWluIiwiYXV0aF90aW1lIjoxNjM0NDcxOTA1jsda56dsf8sd7f7sdf9sdf6hdf8gfdf8dg89dfg8dfgIiwiZXhwIjoxNjM0NTU4MzA1LCJpYXQiOjE2MzQ0NzE5MDUsImp0aSI6IjNlMWQ1ZmJjLTUwNjMtNGZmNS1iZDIxLWFlZTk1ZjAyZTVjZCIsImNsaWVudF9pZCI6IjNiZHBsZzNxYmwyNWJhczM1aWRuOWU4YWdqIiwidXNlcm5hbWUiOiJxbDAzIn0.FU8fv7bXDFLhUku_A11bLiw2kCdLCIepZ0l4E5t8okC_KgABGE4G_VFZ5E34VYAokuy-npWQaP84PKksnPR-S17phEQ-CWyoL5OM7t5sqkJseikqrgxzMoAgnSn34RUY4FJDhmuM9F5ejNhaKp-uDhDnvYaWe8Qcuz1TfBlgLUwARE1eBMaxqusmPOyJpZOvKcaeiOfqduv_rnN36UjIRaOeeDkht54n0066H9vBYnE1kwkVLlLagCI7kF2agHV6Kkl-cTVZTZjqCYzhOuAba_ZhdedsLn9xrQcY14-qgxfYiBxc-m1CVSZ-ZUTlmRShFrG6aHZDYSlWP38bRgQD8g",
"ExpiresIn":86400,
"TokenType":"Bearer",
"RefreshToken":"eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.ODcmlgBQ4TWaUudE5edD5Y0Fx4LQQ6LnmNjfBBcfS14s4Q9MmiD9YQZZSyKTu9UoeR3SpQkGEVvkI6t7rhtyheMqwtJiCxmitCcKVm8RhLrjgEIq2wbBTegINEOKFQKpf3IHsolssm2UuebYpaXxxB68swMwDdBC-By51aTdAaZpJWGiviqZiCNnuzvuKNfhnrZVk482ctrBdu0AgGj-YxKsnVEQozXvCHiojnQE7YfJW048ctYUBgti0wpKvNI2_PbavT11W8cD0x093uQhARZtSBazv4mkqtbPpdv6GSzIE6PHETfKIxJIMaDzLJKAnbOHCEquHfYD1KouZO93Cw.IopkTsaLXan0zWOW.jWxoHQPORSNVHQKfypBQ23BWtq3hzwkDDasd65asd7a8sfg8sd8gsd78gs9gdf8asdc9asdfdsfFXw-hfLA1uhCIeZebRNcTzmVcR_Kd0g75tCzH8FJw4TXMPvQ9Qg9NcJI1JsA_DLC1B9m0hwPXtUib0Pz7k5Z2l7fwCUUfFfT4VNiPrhsuz35XlbNJc1fq1kfN88f5sGZ0UocYwl_CtPf-0FwMeGJkhyyKIWAguV0z5FsfaVWojDPcGkw5JqILUwYxKZUW3mSORI5tXrgVloLoF48xaFoXpK5T2xPHfSaUZMJBsFMK24MdDRgLIfy6XS-21upJsi30O6yyc96A1vYYpk-eD871WC9156AlB3BskCsmgPKRSjPaDQ6Dfuc_xDR4ZLYb5XSaFtEC8q5eGeq-N2DjS0eDQbsUyMFY8ddY7BVNWIv0X1_HRKz6Nilrveimmc4OfaQ3aTHj32VDkxJb5BZgylEgLtaO_HRnqjnPD1Ic-XlxH0oXLgVm2aN3SSdXuEr3BdtCoRtnGfAkLAlK686L-3Ryo2Xg1oR61gNJXBljeFQVeTeUSNuYBKyc_swv4pwBUW_Ff_iOiR_ddhMuzqattTEtGxyXDKIVls3tDoyerJsD5e-_igpKkw5cks9Il6XI1I0Mq2jnso7xFeZEBztt3qcXJ5w8OdV1Qsc79SnAIA8yF9K_8zwZvMfFU5ODJSkvY56lReBiHDImQfDiImkgShDSKu-4y8IP10Ba3jr55b7rebgk3fO9yV9JcZOx9C2JtAHKFaTVCYz2YRA3fChUXlRHcqJfc2cYYAx5wD9fJLR4FiVkgkapaNadYT0pc4LPnylyijtUXgxL7tpDG4i9yJiQ1hT3kHV4o9NZeXyPV-VDN2XWeCOEYhpXASnj7nyRpzH4wPmD9xa6N-4mDzqDVXel7c527eecN7ZfU3MPXJ2fHnTGTzDjPCCPG1Ur0LE-9CJMWMMxbFDV9RR6paKMU8fno-cgczR-HZsWIgGzXudYEyb03OVDmRgdKxW_oWL8yWx0KEMtibHH.5jIZnrXB7RFLn3LS1bJqGA",
"IdToken":"eyJraWQiOiJlZFRQVFU0cXNOdFQyOEd2TWlXakg1aUExZjZFOVwvekw3OEZLYzdWU1VoWT0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJlYTkwZDYyOS0xYjc1LTRjZmItOGQ5ZC1kZGZlYmFkZmVkZjMiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImlzcyI6Imh0dHBzOlwvXC9jb2dadfgsdf6asdf87sd6fsd8f89fjpITrZUOH58mhfm-ToGQznHcWxd5I48W-uHckz1F9dLP9YLZpI0e3BGPPPeEOf2lAIa0dSfzKhl-SZgSLRBd5qX066jx1_6SvnTMpDgRE9JZmFM_n3cI2_jGoShxUwr7NpGaUCo2r2LPXx9Rs-KqmU33mqTFD8F-CezracE9xuAuDiTNCwlBA9_LB1FPQhvzkkgSR5vouIyUYzg"
},
"..."
}
This contains 3 parts:
AccessToken - used for checking access to Cognito authenticated APIs
RefreshToken - used for refreshing the access token
IdToken - a bearer JWT token generally used by services outside of CUP (Congito User Pools)
AccessToken & RefreshToken are being revoked but the JWT ID token (that API GW uses) is not being revoked.
This is confirmed by an AWS employee in this GitHub issue:
Because IdToken is represented as a JSON Web Key Token, it's signed with a secret or private/public key pairs, which means even if you revoke the IdToken, there is no way to revoke the distributed public key.
Others also have indicated this problem, here, here & here for example.
This is not really Amazon's fault as the nature of JWT tokens means that they are stateless. The authorizing server doesn't need any state stored to be able to validate the JWT token - the token itself is all that is needed to verify a token bearer's authorization.
This is perhaps highlighted a bit clearer in another section of the docs:
Revoked tokens will still be valid if they are verified using any JWT library that verifies the signature and expiration of the token.
Essentially, the bad news is that you've hit an Amazon Cognito limitation.
The slightly good news is that if your solutions permits, you can set the expiry of the ID token to a minimum of 1 hour for Cognito ID tokens. While the Cognito Quotas page mentions a minimum of 5 minutes for ID tokens, the console will actually throw a Cannot be greater than refresh token expiration. error for 5 minutes. You will have to set it to the minimum refresh token expiration duration which currently sits at 60 minutes.
A better way to say this is how the documentation for [AdminUserGlobalSignOut][9] has worded it:
Signs out users from all devices, as an administrator. It also invalidates all refresh tokens issued to a user. The user's current access and Id tokens remain valid until their expiry. Access and Id tokens expire one hour after they are issued.
The good news is that an update was given by an AWS Amplify contributor in February that they were working on it (the same "fix" would apply to API Gateway hopefully as a service external to Congito).
The "best" news is that it is possible to implement "real" token revocation yourself to prevent the ID tokens from still being used. You will need to have a custom API Gateway Lambda authoriser (also this guide may be useful) to validate the token with Cognito but then to also check the token to see if it's been revoked by e.g. checking a blocklist DynamoDB table. Read more about the methodology in my answer here.
Until Amazon allows you to "revoke" the ID token too i.e. manages adding of ID tokens associated with the revoked refresh token to a block list on their side which other services can use for verification, you will have to implement this yourself.
I'm looking at my options for a managed sign-on service and AWS Cognito looks promising.
I notice that it's user pools etc do not currently replicate across regions. I wanted to confirm that 1 region is sufficient us-west-# for example (or us-east-#) would be sufficient for an application that has users spread across Canada, the US and Puerto Rico.
In general, not only in the case of Cognito, the closer your users are in the data center that hosts your services the better. And this is only so you can minimize the propagation delays between your clients and the data center hosting your service.
Therefore, if you have to choose one region, choose the one that the majority of your clients are closer to.
AWS Cognito, does not replicate userPools across regions at the moment. Therefore, if you want to use the AccessToken against that userPool you need to go to the region that the userPool resides.
Now, every other service that accepts accessTokens, will accept your token inside AWS, outside AWS in any region.
I'm adding this supplementary detail to the question as a reference for the token types that Cognito returns. As I just found it by googling some of the info in the answer above.
Using the AccessToken against the userPool would be done for things like updating the user's account information. Which would be required to use the region the pool resides in since pools are not replicated.
http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html
ID Token
The ID token is represented as a JSON Web Key Token (JWT). The token contains claims about the identity of the authenticated user. For example, it includes claims such as name, family_name, phone_number, etc. For more information about standard claims, see the OpenID Connect specification. A client app can use this identity information inside the application. The ID token can also be used to authenticate users against your resource servers or server applications. When an ID token is used outside of the application against your web APIs, you must verify the signature of the ID token before you can trust any claims inside the ID token.
The ID token expires one hour after the user authenticates. You should not process the ID token in your client or web API after it has expired.
Access Token
The access token is also represented as a JSON Web Key Token (JWT). It contains claims about the authenticated user, but unlike the ID token, it does not include all of the user's identity information. The primary purpose of the access token is to authorize operations in the context of the user in the user pool. For example, you can use the access token against Amazon Cognito Identity to update or delete user attributes. The access token can also be used with any of your web APIs to make access control decisions and authorize operations in the context of the user. As with the ID token, you must first verify the signature of the access token in your web APIs before you can trust any claims inside the access token.
The access token expires one hour after the user authenticates. It should not be processed after it has expired.
Refresh Token
The refresh token can only be used against Amazon Cognito to retrieve a new access or ID token.
By default, the refresh token expires 30 days after the user authenticates. When you create an app for your user pool, you can set the app's Refresh token expiration (days) to any value between 1 and 3650.