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.
Related
How can I pass the Cognito user's idToken to Amplify.configure() , cause the users have to be authenticated, not as a guest user. So Instead of getting an unauthenticated identityId, How do I get an authenticated Id by setting in the aws amplify configure.
For sign-in and sign-up we are not using Amplify instead we are using Rest API
Currently I'm sending Object to configure as follows,
{
Auth: {
identityPoolId: const.identityPoolId,
IdentityId: 'us-east-1:xxxxxxxxxxxxxxxxxxxyyyyyyzzzzzz',
region: 'us-east-1'
},
Analytics: {
disabled: false,
autoSessionRecord: true,
AWSPinpoint: {
appId: PinpointId,
region: 'us-east-1',
bufferSize: 1000,
flushInterval: 5000,
flushSize: 100,
resendLimit: 3
}
}
}
};
Any help is highly appreciated. Thanks
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!
I've been pulling out my hair trying to set Appsync and Cognito in my React Native app.
I've tried the two following ways:
Amplify.configure(config);
OR
Amplify.configure({
Auth: {
region: config.aws_cognito_region, // REQUIRED - Amazon Cognito Region
userPoolId: config.aws_user_pools_id, // OPTIONAL - Amazon Cognito User Pool ID
userPoolWebClientId: config.aws_user_pools_web_client_id, // User Pool App Client ID
},
});
AND
const client = new AWSAppSyncClient({
url: appSyncConfig.graphqlEndpoint,
region: appSyncConfig.region,
auth: {
type: appSyncConfig.authType,
jwtToken: async () => (await Auth.currentSession()).getIdToken().getJwtToken(),
},
});
OR
const client = new AWSAppSyncClient({
url: appSyncConfig.graphqlEndpoint,
region: appSyncConfig.region,
auth: {
type: appSyncConfig.authType,
apiKey: appSyncConfig.apiKey,
},
});
I've also followed these two tutorials Tackling user auth, Building a notes app.
In both cases, I get the following error in GraphQL with no description:
Error: Network error: Response not successful: Received status code
This is while in Authorization Type is Amazon Cognito User Pool. I've also tried AWS Identity and Access Management (IAM), but that gives me a 403 error. Can someone point me in a direction where I can debug this further?
It might be caused a typo in the docs / article you've read. Trying replacing :
auth: {
type: appSyncConfig.authType,
apiKey: appSyncConfig.apiKey
}
with :
auth: {
type: appSyncConfig.authenticationType,
apiKey: appSyncConfig.apiKey
}
I have the following code and its working for me:
import Amplify, { Auth } from 'aws-amplify';
import API, { graphqlOperation } from '#aws-amplify/api'
window.LOG_LEVEL = 'DEBUG';
Amplify.configure({
Auth: {
"identityPoolId":'ap-southeast-1:xxxxxx',
"mandatorySignIn": false,
"region": "ap-southeast-1",
"userPoolId": "ap-southeast-1_xxxx",
"userPoolWebClientId": "xxxxxxx"
},
API:{
"aws_appsync_graphqlEndpoint": 'https://xxxx.ap-southeast-1.amazonaws.com/graphql',
"aws_appsync_region": 'ap-southwest-1',
"aws_appsync_authenticationType": 'AMAZON_COGNITO_USER_POOLS',
"aws_appsync_apiKey": 'null',
}
});
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)
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