Change cognito user pool user status - amazon-web-services

Is it possible to change with my android App, Cognito user pool user status from FORCE_CHANGE_PASSWORD to CONFIRMED? or from RESET_REQUIRED to CONFIRMED?
If yes which API call can I use?
In fact, I imported users to Cognito and I don't find a way or any example on how to turn them to CONFIRMED status using my App.
Thanks

To change the cognito user pool user status from FORCE_CHANGE_PASSWORD to CONFIRMED-
1.with aws-cli:
get a session token with the temporary password
aws cognito-idp admin-initiate-auth --user-pool-id us-west-2_xxxxxxx --client-id xxxxxxx --auth-flow ADMIN_NO_SRP_AUTH --auth-parameters USERNAME=xxx,PASSWORD=xxx
set new password with the session token
aws cognito-idp admin-respond-to-auth-challenge --user-pool-id xxxx --client-id xxxx --challenge-name NEW_PASSWORD_REQUIRED --challenge-responses NEW_PASSWORD=xxx,USERNAME=xxx --session session_key_from_previous_token
2.with aws-sdk:
get a session token with the temporary password
cognitoidentityserviceprovider.adminInitiateAuth(
{
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId: 'xxx',
UserPoolId: 'xxx',
AuthParameters:
{ USERNAME: 'xxx', PASSWORD: 'temporary_password' }
}, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
set new password with the session token
var params = {
ChallengeName: 'NEW_PASSWORD_REQUIRED',
ClientId: 'xxxx',
ChallengeResponses: {
USERNAME: 'xxx',
NEW_PASSWORD: 'xxx'
},
Session: 'session_key_from_previous_token'
};
cognitoidentityserviceprovider.respondToAuthChallenge(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
Note: If get an error about "Unable to verify secret hash for client", create another app client without a secret and use that.

To change the status of the user you just need to go through the respective flows. To change FORCE_CHANGE_PASSWORD to CONFIRMED, you would need to use the one time password and login and change your password. For RESET_REQUIRED, you would need to use the Forgot Password flow and that will change the status to CONFIRMED.

Related

AWS Cognito Pre authentication get user data

I can't extract the username/password pair from the request.
2022-11-30T03:11:13.958Z xxxxxxxxxxxxxxxxxxxxx INFO{
version: '1',
region: 'xxxxxxxxx',
userPoolId: 'xxxxxxxxxxxxx',
userName: 'test',
callerContext: {
awsSdkVersion: 'aws-sdk-unknown-unknown',
clientId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxx'
},
triggerSource: 'PreAuthentication_Authentication',
request: { userAttributes: {}, validationData: null, userNotFound: true },
response: {}
}
Node script:
export const handler = async(event, context, callback) => {
console.log(event);
console.log(event.request);
console.log(context);
console.log(context.body);
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
Add all rights to Identity and Access Management (IAM), but unfortunately I can't see the password either, it's possible that it can't be extracted.
You (the AWS account user / role) cannot see, view, or extract the Cognito users' passwords ever, this is the purpose of Cognito as a service.
If you really want to do this you could do the signup outside of Cognito with your own system, then set the password manually for the user in Cognito with adminSetPassword.

AWS getting credentials from Cognito Identity Pool using user pool JWT

I am trying to build a function in lambda that would get the user’s AWS credentials (in order to make an Authorization signature to request S3 resources.
event.headers.Authorization is a JWT from Cognito user pool sign in and is used in a lot of other functions and works properly.
Below in the code snippet I tried to use to get the credentials
EDIT: I can confirm that the JWT used in the Authorization header here is an ID token
console.log(event.headers.Authorization)
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'ap-northeast-2:443c5880-d302-4dcf-8cea-b1835723cdb4',
Logins: {
'cognito-idp.ap-northeast-2.amazonaws.com/ap-northeast-2_onyCNlZBF': event.headers.Authorization
}
});
console.log(AWS.config.credentials)
Below is the response , the access key and session token is missing
CognitoIdentityCredentials {
expired: true,
expireTime: null,
refreshCallbacks: [],
accessKeyId: undefined,
sessionToken: undefined,
params: {
IdentityPoolId: 'ap-northeast-2:443c5880-d302-4dcf-8cea-b1835723cdb4',
Logins: {
'cognito-idp.ap-northeast-2.amazonaws.com/ap-northeast-2_onyCNlZBF': 'eyJraWQiOiJJVlpiNkZTUUJudWlnZHRZMldrMkZuQTNXaHQ1dVNpTVhFdlVQaE0xSFdzPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI3MDdhNjQ0Ny04NzZiLTRlNDItYjc1OS0zNWIxZmI3YTQ2NzciLCJhdWQiOiIycjJjZ2V2dGkyOW9mZzg3bWJuaTZwazdwdSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJldmVudF9pZCI6ImUyNjM2ZDdkLTgzZTUtNDgwNC04ZmJjLTQwN2IyNTU3NmU3YyIsInRva2VuX3VzZSI6ImlkIiwiYXV0aF90aW1lIjoxNTkxMDY3NzI1LCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTIuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTJfb255Q05sWkJGIiwiY29nbml0bzp1c2VybmFtZSI6ImFsZXgiLCJleHAiOjE1OTEwNzEzMjYsImlhdCI6MTU5MTA2NzcyNiwiZW1haWwiOiJhbGV4Lnd0aG9AZ21haWwuY29tIn0.7fPwMZEVgOIroiO32bOxAyWxaBkFQco772j9i8m3LNpMx2NxW0UzlE-8J4bp6T0np6HK0MaPgg9BY0qfKjTFYWuMzf6mA7ah6aW30U7yosOyzsuK1CWz8Ksa_-QneLtMcbFVxyAZ8jWqK-TQXhS0IctPK4zehuugvymfjzC11GPcZ9sWoS3X-u2jSebUSta1pce_EEgL3rsL3XUZIxnZZiAqYw-vmFnz64ATqYa13ggsSoGYsATU5JTmO_tTut3xsitp_s7m5jCkqouzj11XvuBZDITXiZPN1ZY62jQ6Mhk9Kin1558DNxhgb2lJTcwUSr6577bVwWJsimp22ca0gw'
}
},
data: null,
_identityId: null,
_clientConfig: {}
}

Cannot sign out the user from AWS Cognito

I have set up an API Gateway authenticated using AWS Cognito. Once the user signs in, I use the following script to verify their credentials:
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
const params = {
AuthFlow: 'ADMIN_NO_SRP_AUTH',
ClientId: APP_CLIENT_ID,
UserPoolId: USER_POOL_ID,
AuthParameters: {
'USERNAME': username,
'PASSWORD': password,
},
};
return cognitoidentityserviceprovider.adminInitiateAuth(params)
.promise();
And this will return a JSON like so:
{
"ChallengeParameters": {},
"AuthenticationResult": {
"AccessToken": "....",
"ExpiresIn": 3600,
"TokenType": "Bearer",
"RefreshToken": "....",
"IdToken": "...."
}
}
On the client side, I will take note of the IdToken and include it as a header with a name mentioned in the API Gateway's Authorizer.
Now, I'm trying to create a lambda function to sign the user out. So far, I've got this:
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
const params = {
UserPoolId: USER_POOL_ID,
Username: username,
};
return cognitoidentityserviceprovider.adminUserGlobalSignOut(params)
.promise();
When I send a request to call this code, even though everything works just fine (no error is thrown), but the IdToken is still valid and I can still call authenticated requests with it. My question is, what is the proper way of signing out a user and why this is not working?
You are right. This is the current behavior of Amazon Cognito Tokens. If you do global signout than your accessToken and RefreshToken will be expired.
But your IdToken will be still valid till 1 hour.
If you call the Global SignOut again, Than you will see the message that access token is expired
I hope this helps!

Firebase as Identity Provider with Cognito / AWS

I am having a hard time using Firebase as an Open ID Connect provider.
Can you please further describe the steps you have been through before and after to make this work?
For information, here is what I have done so far:
In AWS Console:
1 - Create an IAM Identity Provider ( OpenID Connect ) and used securetoken.google.com/<FIREBASE_PROJECT_ID> as an URL, <FIREBASE_PROJECT_ID>for Audience
2 - Checked the Thumbprint manually (it matches the one generated by AWS)
3 - Created a role with the permissions to access the desired services
4 - Created an Identity Pool in Cognito and selected my newly created role in the 'Authenticated role' Dropdown
5 - Selected my Identity Provider under the Authentication Providers > OpenID category (format is therefore): securetoken.google.com/<FIREBASE_PROJECT_ID>
In my code (I am using Vue.js) here are the logical steps I went through:
Import / setup AWS SDK
Invoke Firebase Auth service
Create a new CognitoIdentity
Use the getOpenIdTokenForDeveloperIdentity and push the tokenID received from Firebase
The issue is that I keep getting "Missing credentials in config" errors.
The code:
import axios from 'axios';
const AWS = require('aws-sdk');
AWS.config.region = 'eu-west-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'MY_COGNITO_POOL_ID',
});
export default {
name: 'My Vue.js component name',
data() {
return {
email: '',
password: '',
msg: '',
};
},
methods: {
submit() {
axios
.post(
'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=MY_KEY',
{
email: this.email,
password: password,
returnSecureToken: true,
},
)
.then((res) => {
// stores tokens locally
localStorage.setItem('jwt', JSON.stringify(res.data));
const cognitoidentity = new AWS.CognitoIdentity();
const params = {
IdentityPoolId: 'MY_COGNITO_POOL_ID',
Logins: {
'securetoken.google.com/<PROJECT_ID>': res.data.idToken,
},
IdentityId: null,
TokenDuration: 3600,
};
cognitoidentity.getOpenIdTokenForDeveloperIdentity(params, (err, data) => {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
});
},
},
};
Here are the resources I have used so far while attempting to make this work:
http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
Using Firebase OpenID Connect provider as AWS IAM Identity Provider
https://github.com/aws/amazon-cognito-identity-js/blob/master/examples/babel-webpack/src/main.jsx
http://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html
https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication/
https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication-part-2-developer-authenticated-identities/
https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication-part-3-roles-and-policies/
https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication-part-4-enhanced-flow/
The final code if that can be any help for anyone:
import axios from 'axios';
const AWS = require('aws-sdk');
const aws4 = require('aws4');
export default {
name: 'VUE_CPNT_NAME',
data() {
return {
email: '',
password: '',
msg: '',
idToken: '',
};
},
methods: {
submit() {
// Firebase SignIn API
// Doc: https://firebase.google.com/docs/reference/rest/auth/
axios
.post(
'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=[MY_KEY]',
{
email: this.email,
password: this.password,
returnSecureToken: true,
},
)
.then((res) => {
this.idToken = res.data.idToken;
localStorage.setItem('jwt', JSON.stringify(res.data));
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'IDENTITY_POOL_ID',
Logins: {
'securetoken.google.com/<FIREBASE_PROJECT_ID>': res.data.idToken,
},
}, {
region: 'eu-west-1',
});
// AWS.config.crendentials.get() methods works as well
// or a call to cognitoidentity.getId() followed by a call to getCredentialsForIdentity()
// will achieve the same thing. Cool. But why!?
AWS.config.getCredentials((err) => {
if (err) {
console.log(err);
}
const request = {
host: 'API_GATEWAY_ENDPOINT.eu-west-1.amazonaws.com',
method: 'GET',
url: 'https://API_GATEWAY_ENDPOINT.eu-west-1.amazonaws.com/PATH',
path: '/API_ENDPOINT_PATH',
};
// Signing the requests to API Gateway when the Authorization is set AWS_IAM.
// Not required when Cognito User Pools are used
const signedRequest = aws4.sign(request,
{
secretAccessKey: AWS.config.credentials.secretAccessKey,
accessKeyId: AWS.config.credentials.accessKeyId,
sessionToken: AWS.config.credentials.sessionToken,
});
// removing the Host header to avoid errors in Chrome
delete signedRequest.headers.Host;
axios(signedRequest);
});
});
},
},
};
Try setting the login map i.e the firebase token in the CognitoIdentityCredentials object. See this doc.
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'MY_COGNITO_POOL_ID',
Logins: {
'securetoken.google.com/':
}
});
Try calling get method on the credentials object before initializing the Cognito client. You can also use getCredentials instead.
If the above steps do not work & they should, pass the credentials as an option while initializing the Cognito client. See this doc for options available while using the CognitoIdentity constructor.
const cognitoidentity = new AWS.CognitoIdentity({credentials: AWS.config.credentials});
If you still receive the error, try logging credentials object in the console after calling the get() method. Ideally, it should have temporary credentials (accessKey, secretKey & sessionToken)

How to call AWS API Gateway Endpoint with Cognito Id (+configuration)?

I want to call an AWS API Gateway Endpoint that is protected with AWS_IAM using the generated JavaScript API SDK.
I have a Cognito UserPool and a Cognito Identity Pool. Both properly synced via ClientId.
I use this code to Sign in and get the Cognito Identity
AWS.config.region = 'us-east-1'; // Region
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:XXXXXXXXXXXXXXXXXXXXXXXX' // your identity pool id here
});
AWSCognito.config.region = 'us-east-1';
AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:XXXXXXXXXXXXXXXXXXXXXXXX' // your identity pool id here
});
var poolData = {
UserPoolId: 'us-east-1_XXXXXXXX',
ClientId: 'XXXXXXXXXXXXXXXXXXXXXXXX'
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var authenticationData = {
Username: 'user',
Password: '12345678',
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var userData = {
Username: 'user',
Pool: userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:XXXXXXXXXXXXXXXXXXXX',
IdentityId: AWS.config.credentials.identityId,
Logins: {
'cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXX': result.idToken.jwtToken
}
});
AWS.config.credentials.get(function (err) {
// now I'm using authenticated credentials
if(err)
{
console.log('error in autheticatig AWS'+err);
}
else
{
console.log(AWS.config.credentials.identityId);
}
});
},
onFailure: function (err) {
alert(err);
}
});
All this succeeds and I have an authorized Cognito Identity now.
Now I try to call the API Gateway Endpoint to execute the Lambda Function it points to.
var apigClient = apigClientFactory.newClient({
accessKey: AWS.config.credentials.accessKeyId, //'ACCESS_KEY',
secretKey: AWS.config.credentials.secretAccessKey, //'SECRET_KEY',
sessionToken: AWS.config.credentials.sessionToken, // 'SESSION_TOKEN', //OPTIONAL: If you are using temporary credentials you must include the session token
region: 'us-east-1' // OPTIONAL: The region where the API is deployed, by default this parameter is set to us-east-1
});
var params = {
// This is where any modeled request parameters should be added.
// The key is the parameter name, as it is defined in the API in API Gateway.
};
var body = {
// This is where you define the body of the request,
query: '{person {firstName lastName}}'
};
var additionalParams = {
// If there are any unmodeled query parameters or headers that must be
// sent with the request, add them here.
headers: {},
queryParams: {}
};
apigClient.graphqlPost(params, body, additionalParams)
.then(function (result) {
// Add success callback code here.
console.log(result);
}).catch(function (result) {
// Add error callback code here.
console.log(result);
});
But unfortunately this fails. The OPTIONS request succeeds with 200 but the POST then fails with 403.
I am pretty sure that there is no CORS problem here.
I am pretty sure the problem has to do with IAM Roles and AWS Resource Configurations.
My question is basically, can you please provide me with all the necessary AWS Resource Configurations and IAM Roles that are necessary for this to work please?
Resources I have are
API Gateway - with deployed API Endpoints
Lambda Function - called by the Endpoint
Cognito User Pool - with App synced to the Identity Pool
Cognito Identity Pool - with Authorized and Unauthorized Role mapped to it.
IAM Roles - for the Lambda Function and the Authorized and Unauthorized Role of the Cognito Identity Pool.
But I don't know how these Resources need to be configured properly to get this to work.
Thank you
What access permissions does the role of the Cognito Identity have? Make sure it has access to perform execute-api:Invoke on your API.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": [
"arn:aws:execute-api:us-east-1:<account>:<rest-api>/*/POST/graphql"
]
}
]
}
You can get the exact resource ARN from the method settings page in the web console.
Even after following everything I was getting the same error. And the reason was I missed the "sessionToken" while initialising the apigClient.
var apigClient = apigClientFactory.newClient({
accessKey: AWS.config.credentials.accessKeyId, //'ACCESS_KEY',
secretKey: AWS.config.credentials.secretAccessKey, //'SECRET_KEY',
sessionToken: AWS.config.credentials.sessionToken, // 'SESSION_TOKEN', //OPTIONAL: If you are using temporary credentials you must include the session token
region: 'us-east-1' // OPTIONAL: The region where the API is deployed, by default this parameter is set to us-east-1 });
//OPTIONAL: If you are using temporary credentials you must include the session token -- is not really optional