So I used this chunk of code found on the official repo of AWS JS SDK.
It is used to authenticate a user.
It is returning a blank response.
AWSCognito.config.region = 'us-east-1';
var authenticationData = {
Username : '+1112223333', //some phone number used as an Alias
Password : 'password123456',
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var poolData = {
UserPoolId : 'us-east-1_P00l1d', // Your user pool id here
ClientId : 'xxx' // Your client id here
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : 'myusername',
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 : 'xxx', // your identity pool id here
Logins : {
// Change the key below according to the specific region your user pool is in.
'cognito-idp.pool_id_number_here_xxx' : result.getIdToken().getJwtToken()
}
});
},
onFailure: function(err) {
alert(err)
console.log("Error " + err);
},
});
So, for the authenticationData, I used the phone number as username (phone number is set as an alias) and the password. I tried with the username directly as well.
The UserPoolId and ClientId are correct as I used the same value for registering and confirming the phone number.
In the userData, I set the Username with the proper myusername.
About the Identity Pool, I created an Identity Pool on AWS Console linked to my App and my UserPool and I replaced the values IdentityPoolId and Logins in authenticateUser.
I am not completely sure about the value in Logins though. I used cognito-idp.POOLIDNUMBER.
The output from AWS is blank.
I am thinking that I can not even reach the server and I suspect an issue with the roles or the Identity Pool (the userPool is fine I suppose).
My identity pool is only using AWS Cognito users, not Facebook or other Identity Providers.
Recompiling SJCL with --with-all solved the issue.
Please make sure you have all the necessary libraries for 'Amazon Cognito Identity SDK for JavaScript'. Following is the list and links to these libraries.
1.The Amazon Cognito AWS SDK for JavaScript -
https://raw.githubusercontent.com/aws/amazon-cognito-identity-js/master/dist/aws-cognito-sdk.min.js
2.The Amazon Cognito Identity SDK for JavaScript -
https://raw.githubusercontent.com/aws/amazon-cognito-identity-js/master/dist/amazon-cognito-identity.min.js
3.JavaScript BN library (jsbn.js,jsbn2.js) -
http://www-cs-students.stanford.edu/~tjw/jsbn/
4.Stanford JavaScript Crypto Library -
https://github.com/bitwiseshiftleft/sjcl
5.AWS SDK for JavaScript (optional, to use other aws services) -
http://aws.amazon.com/sdk-for-browser/
Include all these libraries and then use the code snippet below.
AWSCognito.config.region = 'YOUR_REGION';
var poolData = {
UserPoolId : 'YOUR_USER_POOL_ID', // Your user pool id here
ClientId : 'YOUR_CLIENT_ID' // Your client id here
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : "userName", // your username here
Pool : userPool
};
//Signing Users in the App
var authenticationData = {
Username : "userName", // your username here
Password : "password" // your password here
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
},
onFailure: function(err) {
console.log(err);
}
});
Related
I am having an issue with my google APi using a JWT token, I have been having trouble impersonating users for checking calendar avaliability, and I started back tracing and found when I output the JWT token after an authorize, I get the following:
{ access_token: '****',
token_type: 'Bearer',
expiry_date: 1589294984000,
id_token: undefined,
refresh_token: 'jwt-placeholder' }
the id_token comes back undefined. I have set up everything in my cloud services and I call the authorization with a config file
var googleAuthorization = require('../config/calendarConfig.js').jwtClient;
const {google} = require('googleapis');
const calendar = google.calendar('v3');
googleAuthorization.authorize(function(err, token) {
if(err) {
reject(console.log({status: 1, message: 'Google Authorization Failed: ' + err}));
} else {
console.log(token);
}
});
and the config file:
var google = require('googleapis');
var googleAauth = require('google-auth-library');
var scopes = ['https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/admin.directory.user'];
var key = require('./intranet-google-service-account.json');
var jwtClient = new google.google.auth.JWT(key.client_email, null, key.private_key, scopes,
"service#accountemail.com");
exports.jwtClient = jwtClient;
Can anyone see what I might be doing wrong to not get an ID token back?
I'm trying to understand Cognito authentication using their JavaScript SDK. I have the following code (which is triggered by a form in a React application):
import {
CognitoUserPool,
AuthenticationDetails,
CognitoUser
} from "amazon-cognito-identity-js";
const poolData = {
UserPoolId: MY_POOL_ID,
ClientId: APP_CLIENT_ID
};
export function cognitoLogin(credentials, callback) {
const authenticationDetails = new AuthenticationDetails(credentials);
const userPool = new CognitoUserPool(poolData);
const cognitoUser = new CognitoUser({
Username: credentials.username,
Pool: userPool
});
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function(response) {
console.log("SUCCESS!");
console.log(response);
},
onFailure: function(error) {
console.log("FAILURE!");
console.log(error);
}
});
}
I generated a Client App without a secret. I generated a User and used the custom domain UI to login with that user and confirm it. However, when I try to login through the SDK I get a
{
code: "NotAuthorizedException",
message: "Incorrect username or password.",
name: "NotAuthorizedException"
}
error. What could I be missing?
The credentials object must contain the keys Username and Password - notice they have first letter capitalized but yours seem to be all lowercase.
I use Amazon Cognito Identity SDK for JavaScript to log in my users at www.mydomain.com.
I was wondering if it was possible to have my users automatically logged in on store.mydomain.com
For what i know Cognito stores the logintoken and other things in localstorage and that can't be reached from subdomains?
AWS Cognito JS SDK uses LocalStorage to store the authentication tokens by default. You can change this behavior and use cookies to store the tokens. Then you can use your parent domain name while setting the cookies and all your sub-domains can access this cookie.
To achieve this, you can use the CookieStorage class from the JS SDK while creating the CognitoUserPool objects.
TypeScript Code snippets below
Full implementation can be found here. A running application can be viewed here.
To authenticate the User (on the main domain, say, example.com) -
signIn(email: string, password: string): Observable<any> {
let userPool = new CognitoUserPool({
UserPoolId: environment._USER_POOL_ID,
ClientId: environment._CLIENT_ID,
Storage: new CookieStorage({secure: false, domain: "example.com"}),
});
let authenticationDetails = new AuthenticationDetails({
Username: email,
Password: password,
});
let userData = {
Username: email,
Pool: userPool,
Storage: new CookieStorage({secure: false, domain: "example.com"}),
};
let cognitoUser = new CognitoUser(userData);
return Observable.create((observer: Observer<any>) => {
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: result => {
observer.next(result);
observer.complete();
},
onFailure: error => observer.error(error),
});
});
}
To check if user is authenticated (on a subdomain, say, sub.example.com)
isAuthenticated(): Observable<boolean> {
let userPool = new CognitoUserPool({
UserPoolId: environment._USER_POOL_ID,
ClientId: environment._CLIENT_ID,
Storage: new CookieStorage({secure: false, domain: "example.com"}),
});
let cognitoUser = userPool.getCurrentUser();
if (cognitoUser != null) {
return Observable.create((observer: Observer<boolean>) => {
cognitoUser.getSession((error, session) => {
if (error) {
console.error(error);
observer.next(false);
observer.complete();
}
console.log(session, session.isValid(), session.isAuthenticated);
observer.next(session.isValid());
observer.complete();
});
})
}
The tokens for the Amazon Cognito Identity SDK for JavaScript are stored in local storage indeed. However, if you use the Cognito Hosted UI and the Cognito Auth SDK linked below, you can manage SSO.
The way that works, if you have tokens stored against the local storage of your domain, you can login. Otherwise, you hit our login endpoint and if there is a cookie stored against it, you get tokens in the response that will be stored in local storage and can be accessed with the Amazon Cognito Identity SDK (cause they are stored in the same location).
https://github.com/aws/amazon-cognito-auth-js
My setup consists of an AWS API Gateway with IAM access control and AWS cognito for log in.
I access the API already from an Android app and would now like to build a web app (angular2) to do the same.
On Android, I'm using the AWSCognitoCredentialsProvider to supply the API SDK with the required credential. (http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-generate-sdk.html)
Unfortunately I cannot figure how / if I can do that with the javascript SDK?
I have no trouble using cognito to log in and get the session ID, access token etc. However, the API SDK requires me to provide accessKey and secretKey.
Here's the relevant code snippet from the generated API SDK:
var authType = 'NONE';
if (sigV4ClientConfig.accessKey !== undefined && sigV4ClientConfig.accessKey !== '' && sigV4ClientConfig.secretKey !== undefined && sigV4ClientConfig.secretKey !== '') {
authType = 'AWS_IAM';
}
In other words, I have this part working (from some example code):
static authenticate(username:string, password:string, callback:CognitoCallback) {
AWSCognito.config.update({accessKeyId: 'anything', secretAccessKey: 'anything'})
let authenticationData = {
Username: username,
Password: password,
};
let authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
let userData = {
Username: username,
Pool: CognitoUtil.getUserPool()
};
console.log("Authenticating the user");
let cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
console.log(AWS.config);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
callback.cognitoCallback(null, result);
},
onFailure: function (err) {
callback.cognitoCallback(err.message, null);
},
});
}
and now I'd like to use this:
this.apigClient = apigClientFactory.newClient({
accessKey: "anything",
secretAccessKey: "anything",
sessionToken: "nothing",
region: 'eu-central-1'
How do I get accessKey, secretAccessKey and sessionToken out of my AWSCognito? I was unable to find any API for that so far...
Thank you Bob, for pointing me in the right direction! I've now figured it out and thus for completeness sake, here's the full solution to my problem:
From the service that creates the apigClient:
return CognitoUtil.getCredentials()
.then(() =>
this.apigClient = apigClientFactory.newClient({
accessKey: AWS.config.credentials.accessKeyId,
secretKey: AWS.config.credentials.secretAccessKey,
sessionToken: AWS.config.credentials.sessionToken,
region: 'eu-central-1'}));
The getCredentials() method, which is key to get the required temporary credentials:
public static getCredentials():Promise{
return new Promise((resolve, reject) => {
CognitoUtil.getIdToken({
callback() {
},
callbackWithParam(idTokenJwt:any) {
let url = 'cognito-idp.' + CognitoUtil._REGION.toLowerCase() + '.amazonaws.com/' + CognitoUtil._USER_POOL_ID;
let logins = {};
logins[url] = idTokenJwt;
let params = {
IdentityPoolId: CognitoUtil._IDENTITY_POOL_ID, /* required */
Logins: logins
};
AWS.config.region = CognitoUtil._REGION;
AWS.config.credentials = new AWS.CognitoIdentityCredentials(params);
AWS.config.credentials.refresh(result => {
console.log(AWS.config.credentials);
resolve();
});
}
});
});
}
So the key insight here was, that
I authenticate to the user pool (shown in my question)
I use that with an identity provider to retrieve temporary credentials (getCredentials)
I use the temporary credentials out of AWS.config.credentials to setup the apigClient
I hope this is helpful to someone else as well. Certainly the code that I just posted probably could use some refactoring, so any comments on that are very welcome!
Cognito is actually made of 3 different services:
Cognito Your User Pools - What you've integrated here
Cognito Sync - For syncing user preference data for users
Cognito Federated Identity - For federating identities (FB, Google or User Pools) into your account and generating credentials.
What the API Gateway client is expecting is credentials that come from Cognito Federated Identity.
See the Cognito documentation for integrating your user pool with Cognito Federated Identity.
I've created a Cognito User Pool. I can list the users and add the users using the AWSCognitoIdentityProviderClient from the Java AWS SDK.
However, I have a custom login page and I wish to take the entered username and password and authenticate against my User Pool. I don't see anywhere in the Java AWS SDK where I can pass credentials and get an authentication result from.
Edit: I can't get past this error:
NotAuthorizedException: Missing credentials in config
Relevant code:
AWS.config.region = 'us-east-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:087a3210-64f8-4dae-9e3c...' // your identity pool id here
});
AWSCognito.config.region = 'us-east-1';
AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: 'us-east-1:087a3210-64f8-4dae-9e3c...' // your identity pool id here
});
var poolData = {
UserPoolId: 'us-east-1_39RP...',
ClientId: 'ttsj9j5...',
ClientSecret: 'bkvkj9r8kl2ujrlu41c7krsb6r7nub2kb260gj3mgi...'
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var authenticationData = {
Username: 'test#foo.com',
Password: 'foobarfoo',
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var userData = {
Username: 'test#foo.com',
Pool: userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
},
onFailure: function (err) {
alert(err);
},
});
The AWS Java SDK includes APIs to authenticate users in a User Pool. You can authenticate a user using either the InitiateAuth api or AdminInitiateAuth api of the AWSCognitoIdentityProviderClient class. The difference between these two API is explained in the documentation. In short, for InitiateAuth, you need to perform SRP calculations and then pass it to the API, while in AdminInitiateAuth you can directly pass the username and password. You can read about the security implications in both cases and decide which one to use.
Documentation :
https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow.html
API reference:
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html
My working sample(Groovy):
def login() {
AWSCognitoIdentityProviderClient client = new AWSCognitoIdentityProviderClient()
println("Provider client: " + client)
client.setRegion(Region.getRegion(Regions.AP_NORTHEAST_1))
HashMap authParams = new HashMap<>()
authParams.put("USERNAME", "User1")
authParams.put("PASSWORD", "a*123")
AdminInitiateAuthRequest adminInitiateAuthRequest = new AdminInitiateAuthRequest()
.withClientId(<YOUR_CLIENT_ID>)
.withUserPoolId(<YOUR_USER_POOL_ID>)
.withAuthFlow(AuthFlowType.ADMIN_NO_SRP_AUTH )
.withAuthParameters(authParams)
AdminInitiateAuthResult result = client.adminInitiateAuth(adminInitiateAuthRequest);
if (result != null) {
System.out.println("AdminInitiateAuthResult:");
System.out.println(result.toString());
} else {
System.out.println("No result available");
return;
}
}
Authentication is only supported via JavaScript, iOS and Android at this time. The necessary apis to authenticate are not part of the server SDKs (java, python et. all) during the beta. Using the JavaScript SDK is the recommended way of authenticating from your login page.
check here https://github.com/aws/amazon-cognito-identity-js
there is a missing line of code
This page http://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-javascript-examples.html is not updated
// Need to provide placeholder keys unless unauthorised user access is enabled for user pool
AWSCognito.config.update({accessKeyId: 'anything', secretAccessKey: 'anything'})
After including this I stopped having this error.