I am using Java to upload images to Amazon S3
AwsSessionCredentials awsCreds = AwsSessionCredentials.create(ACCESS_KEY, SECRET_KEY, SESSION_TOKEN);
S3Client s3main = S3Client.builder()
.credentialsProvider(StaticCredentialsProvider.create(awsCreds))
.endpointOverride(URI.create(MAIN_END_POINT)).region(main_region).build();
s3main.putObject(PutObjectRequest.builder().bucket(bucketName).key(img1Name).build(), RequestBody.fromBytes(bytesMain));
Above code works. I am passing blank string "" as SESSION_TOKEN. Just wondering what is the use of Session Token here? What value should I pass here?
You are using IAM user credentials and so you do not have a session token and your code should use AwsBasicCredentials. Session tokens are associated with short-term credentials from an assumed IAM role, in which case your code would use AwsSessionCredentials.
Background
To quote the AWS documentation:
You must provide your AWS access keys to make programmatic calls to AWS. When you create your access keys, you create the access key ID (for example, AKIAIOSFODNN7EXAMPLE) and secret access key (for example, wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY) as a set.
IAM users, for example, authenticate using an access key ID and a secret access key. These are long-lived credentials.
However, it is also possible to use short-term credentials:
You can also create and use temporary access keys, known as temporary security credentials. In addition to the access key ID and secret access key, temporary security credentials include a security token that you must send to AWS when you use temporary security credentials. The advantage of temporary security credentials is that they are short term. After they expire, they're no longer valid.
When IAM users or federated users assumes an IAM role, they are given a set of credentials that comprise an access key ID, a secret access key, and a security token. These are short-lived credentials.
Related
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.
I'm quite new to AWS Cognito and about token security. I decided to use AWS Cognito for may application. I followed the guide here for my web app and my web api.
https://dzone.com/articles/identity-as-a-service-idaas-aws-cognito-and-aspnet
https://dzone.com/articles/identity-as-a-service-idaas-asp-net-core-api-and-a
Everything works fine. But when I try to create a new User pool in AWS Cognito and then change the appsetting for both web app and web api to use the new user pool, I found something quite weird.
(For the web app). User still can access controller action by the old token that belong to the old User pool that used before even the action is marked as [Authorize]. I don't know why user still can access with the old token even appsetting is set to the new User pool. (But User cannot access to the web api,that use new User pool, with the old token)
(For both web app and web api). Then I deleted that User from the old User pool and set web app and web api to use the old user pool. I found that User still can access both action in web app and web api even that User was deleted.
I think that it might be something that I missing about validation token or setting. Can anyone suggest about a solution to fix that?
The ID Token issued by AWS Cognito User Pool is a JWT token, which is Signed By AWS. Once issued the token is valid for 1 hour. Within this 1 hour, there is no way of revoking the token since its stateless.
Amazon Cognito generates two RSA key pairs for each user pool. The
private key of each pair is used to sign the respective ID token or
access token. The public keys are made available at an address in this
format:
https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
Since the public key is publically available, anyone can verify whether the JWT token is authentic and issued by AWS Cognito.
However, this involved multiple things to verify.
Validate the JWT Token Encoding whether its compliant with JWT standard.
Validate JWT Issuer, whether its the particular User Pool (Verify its ID).
Validate whether the token is an ID Token (Optional).
Validate the Audience of the Token (Whether it is issued for the particular App).
Validate Token Signature (This is where the public key is needed).
Validate whether the token is expired or not.
This information is already self-contained within the JWT token string properly encoded according to the JWT standard.
Therefore, even the Cognito User Pool is deleted, if there is a valid token (< 1 hour after issued), it should be valid, if the verification process uses a stored Public key to verify it.
I am using JWT token for rest api's security.
When user is logged in check user's credentials with DB.
If it matched we are encrypting it for further security and then passing it to jwt to create a token
Now in order to match user's token we need to keep password somewhere so that we can match them when user sends any request after logged in
we can do it 2 ways
1. Keep detail in Database and each time rest call is fired check token with token in Database which is too costly for each rest call
2. Preserve secret somewhere in JVM and use it. Here I have tried HttpSession from package
javax.servlet.http.HttpServletRequest
// My key issue code
// Encrypt it
Key key = keyGenerator.generateKey(password);
jwtToken = Jwts.builder()
.setSubject(username)
.setIssuer(uriInfo.getAbsolutePath().toString())
.setIssuedAt(new Date())
.setExpiration(toDate(LocalDateTime.now().plusMinutes(1)))
.signWith(SignatureAlgorithm.HS512, key)
.compact();
// Adding details to session
HttpSession httpSession = currentRequest.getSession();
httpSession.setAttribute("userSecret", password)
This works fine for single Server instance.
But at some point we need to scale up and run multiple instance of server.
How do we handle this case where user may logged in using 1 instance and may serving rest call using another instance using load balancing.
As users secret is available only in first Server's JVM.
You can share the private key, which was used for encrypting the JWT, among the servers. When a servers gets an API call, you can try to decrypt the JWT with the private key. If the decryption is successful, you have a valid a JWT and you can process the request. If the decryption fails, that means it's an invalid JWT. Once a JWT has been created, you don't need to hit the database. That's the primary usage of JWT in my opinion.
I am not sure what you mean by userSecret.
In development, we have successfully written an image to S3 bucket and then get the url back so we can store the url.
Now that we're moving into production, we need to not include the access and secret keys.
Everything is saying to use Cognito, but we don't want to authenticate users. We just want images that are stored in the app to be backed up online and store the url. Every user can dump images in the same bucket because they will never access the images, just download via url.
Does anyone know, is there an invisible way to establish this connection securely to only read and write from the app without forcing users to login?
You may want to checkout CognitoIdentityService. CognitoIdentity allows developers to get temporary credentials to call other AWS service. So, developers need not put access and secret keys within the application. They can simply use the credentials provided by Cognito.
With Cognito, developers can configure if they wish the users to be authenticated or not. With CognitoIdentity authentication is optional. If user not authenticated, user will be given a new identityId every time. For authenticated users, identityId remains same. But it can easily be used for either case to get temporary credentials.
I know there is a similar ques at
http://stackoverflow.com/questions/12296017/how-to-validate-an-oauth-2-0-access-token-for-a-resource-server
But it didn't answer my question.
What I want to ask is after an authentication server grants the access token, how it is validated by the resource server? By validation I mean which parameters of token helps the resource server to validate the origin and authenticity of the token.
As far i can imagine, any hacker can generate a psuedo token by analyzing a past token.
The Secret key That Is generated that is used to validate It matches the signature . You Can use
https://jwt.io
to check the signature of jwt token by providing secret key it will verify it and secret key is generated in oauth when guid(Client Id ) is generated.
I think you are confusing Access Token with Authorization Grant.
When a user authenticates against the Authorization Server (AS), the server will generate what's called an Authorization Grant that contains all the relevant information such as the scope, issuer, expiry, etc...In most implementations thess grants will be persisted to a database or similar persistent storage. The Access Token that the client receives and then sends to the Resource Server (RS) will be just some kind of opaque string that uniquely identifies a valid authorization grant generated by the AS. So the access token alone does not have any meaning per se.
This means that the RS has no way of validating access tokens by itself, only the AS does. The RS can validate the syntax but it will need to send the Access Token to the AS for validation. This interaction between the RS and the AS is not part of the OAuth 2.0 standard, as mentioned in the answer that you posted, and it's up to the AS implementation to decide how to accomplish this task.
Even though you're right when you say that any hacker can generate random access tokens only the AS can generate and persist authorization grants. That's the main reason why your RS should always contact the AS to verify the validity of the authorization grant linked to the access token before granting access to any resource.
I hope this clarifies your question.