Cognito AmazonWebService authentication issue - javascript

I'm doing an user management with the AmazonWebService cognito and I having some difficulties to authenticate me to my user pool.
Do am I logged in if I just do:
login: function(username, password, _poolData) {
var deferred = $q.defer();
var authenticationData = {
Username : username,
Password : password,
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(_poolData);
var userData = {
Username : username,
Pool : userPool
};
cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
console.log('idToken + ' + result.idToken.jwtToken)
deferred.resolve('successfully logged in.');
},
onFailure: function(err) {
console.log(error);
alert(err);
deferred.reject('login failled.');
},
});
return deferred.promise;
},
Because I can not get my user attributes after using this login method.
Like this:
getCognitoUserAttr: function(username, _poolData) {
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(_poolData);
var userData = {
Username : username,
Pool : userPool
};
cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.getUserAttributes(function(err, result) {
if (err) {
alert(err);
return;
}
for (var i = 0; i < result.length; i++) {
console.log('attribute ' + result[i].getName() + ' has value ' + result[i].getValue());
}
});
}
I always have the error message:
Error: User is not authenticated
Note that the login method is from :https://docs.aws.amazon.com/fr_fr/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-javascript-examples.html
What I have to do?

Here you go. I made a function called getUserAttributes() then used the same code as seen in isAuthenticated.
getUserAttributes(){
let cognitoUser = this.getCurrentUser();
if (cognitoUser != null) {
cognitoUser.getSession(function (err, session) {
cognitoUser.getUserAttributes(function(err, result) {
if (err) {
console.log(err);
return;
}
for (let i = 0; i < result.length; i++) {
console.log('attribute ' + result[i].getName() + ' has value ' + result[i].getValue());
}
});
});
}
}
this is the login function i use
authenticate(username: string, password: string, callback: CognitoCallback) {
let authenticationData = {
Username : username,
Password : password,
};
let authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
let poolData = {
UserPoolId : CognitoUtil._USER_POOL_ID,
ClientId : CognitoUtil._CLIENT_ID
};
let userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
let userData = {
Username : username,
Pool : userPool
};
let cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId : CognitoUtil._IDENTITY_POOL_ID,
Logins : {
'cognito-idp.REGION.amazonaws.com/POOLID':result.getIdToken().getJwtToken()
}
});
callback.cognitoCallback('loginSuccess', null);
},
onFailure: function (err) {
callback.cognitoCallback(err.message, null);
}
});
}

Related

AWS Cognito: Generate token and after refresh it with amazon-cognito-identity-js SDK

i'm implementing a node.js backend using the amazon-cognito-identity-js.
I want to create a login(username, password) and refreshToken(token) APIs.
This is my code:
import { AuthenticationDetails, CognitoUser, CognitoUserPool, CognitoRefreshToken } from "amazon-cognito-identity-js"
public loginWithAmazonCognitoIdentity (username: string, password: string){
var authenticationData = {
Username : username,
Password : password,
};
var authenticationDetails = new AuthenticationDetails(authenticationData);
var poolData = { UserPoolId : 'eu-north-1_xxxxxx',
ClientId : '3al0l3mhcxxxxxqgnp789987'
};
var userPool = new CognitoUserPool(poolData);
var userData = {
Username : username,
Pool : userPool
};
var cognitoUser = new CognitoUser(userData);
const user = cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
var accessToken = result.getAccessToken().getJwtToken();
console.log("token: " + accessToken);
var refresh = result.getRefreshToken().getToken();
console.log("RefreshToken: " + refresh);
},
onFailure: function(err) {
console.error(err);
},
});
}
This function returns an accessToken and a refreshToken without errors.
After this, i have implemented this function:
public refreshToken(refreshToken)
var poolData = { UserPoolId : 'eu-north-1_xxxxxx',
ClientId : '3al0l3mhcxxxxxqgnp789987'
};
var userPool = new CognitoUserPool(poolData);
var userData = {
Username : 'lacucudi',
Pool : userPool
};
var cognitoUser = new CognitoUser(userData);
var token = new CognitoRefreshToken({ RefreshToken: refreshToken })
cognitoUser.refreshSession(token, (err, session) => { if (err) {console.log(err)} else console.log('session: ' + JSON.stringify(session)) });
}
but passing the refreshToken previously retrieved it returns an:
NotAuthorizedException: Invalid Refresh Token.
Can anyone tell me what is the correct backend implementation of these 2 apis ?
I solved in this way:
import Amplify, { Auth } from "aws-amplify";
import {
AdminCreateUserCommand,
AdminSetUserPasswordCommand,
AuthFlowType,
CognitoIdentityProviderClient,
CognitoIdentityProviderClientConfig,
GetUserCommand,
InitiateAuthCommand,
MessageActionType,
RevokeTokenCommand,
} from "#aws-sdk/client-cognito-identity-provider";
public async login(username: string, password: string): Promise<AuthTokens> {
if (!username || !password) {
throw new HttpException(400, "Please provide both username and password");
}
Amplify.configure({ Auth: config.auth });
const user = await Auth.signIn(username, password);
if (!user.signInUserSession) {
throw new HttpException(500, `Could not authenticate user ${username}`);
}
const {
signInUserSession: {
accessToken: { jwtToken: access_token },
idToken: { jwtToken: id_token },
refreshToken: { token: refresh_token },
},
} = user;
return {
id_token,
access_token,
refresh_token,
};
}
public async refresh(refresh_token: string): Promise<AuthTokens> {
if (!refresh_token) {
throw new HttpException(400, "Please provide a refresh token");
}
const refreshTokenAuth = new InitiateAuthCommand({
ClientId: config.auth.userPoolWebClientId,
AuthFlow: AuthFlowType.REFRESH_TOKEN_AUTH,
AuthParameters: {
REFRESH_TOKEN: refresh_token,
},
});
const response = await this.client.send(refreshTokenAuth);
const {
AuthenticationResult: { AccessToken, IdToken },
} = response;
return {
refresh_token,
access_token: AccessToken,
id_token: IdToken,
};
}
public async logout(refreshToken: string): Promise<boolean> {
if (!refreshToken) {
throw new HttpException(400, "Please provide a refresh token");
}
try {
const command = new RevokeTokenCommand({
ClientId: config.auth.userPoolWebClientId,
Token: refreshToken,
});
const response = await this.client.send(command);
const { httpStatusCode } = response.$metadata;
return httpStatusCode == 200 ?? true;
} catch (e) {
logger.error(e);
throw new HttpException(500, e);
}
}
I used aws-amplify for login and aws-sdk/client-cognito-identity-provider for other operations.
NotAuthorizedException: Invalid Refresh Token
error message was returned because the device tracking option was enabled in Cognito settings.
It' s incredible for a service provided by AWS to give wrong error messages and very little documentation about it

AXIOS POST return result

I have created a non-JWT api call and it works. The moment I added JWT verifyToken it works but I cannot seems to get the return result set from AXIOS POST.
Function 2 --> /userget ----is working I can display result on HTML
Function 7 ---> /api/userget ---It can get data and token but I cannot display on HTML, it goes to "Bad response"
++++++++++++++++++++++++++++++++
function myFunction2() {
console.log("Going2");
var userid = document.getElementById("userid").value;
console.log(userid);
axios( {
method: 'post',
url:'http://localhost:8081/userget',
data : {
userid : userid
}
})
.then(function (response) {
console.log(response.data.result[0].username );
var userid = JSON.stringify(response.data.result[0].userid);
var username = JSON.stringify(response.data.result[0].username);
var email = JSON.stringify(response.data.result[0].email);
var userid = JSON.parse(userid);
var username = JSON.parse(username);
var email = JSON.parse(email);
var displaydata = ("User ID : " + userid + "<br><br>Name : " + username + "<br><br>Email :" + email);
document.getElementById("demo").innerHTML = displaydata;
})
.catch(function (error) {
document.getElementById("demo").innerHTML = "Bad response";
});
}
+++++++++++++++++++++++++++++++++
function myFunction7() {
console.log("Going7");
var userid = document.getElementById("userid").value;
console.log(userid);
console.log("Print local token == " + localStorage.getItem("token"));
var msgtxt = localStorage.getItem("token");
axios( {
method: 'post',
url:'http://localhost:8081/api/userget',
headers: {
'Authorization': `Bearer ${msgtxt}`
},
data : {
userid : userid
}
})
.then(function (response) {
console.log(response.data.result[0].username );
var userid = JSON.stringify(response.data.result[0].userid);
var username = JSON.stringify(response.data.result[0].username);
var email = JSON.stringify(response.data.result[0].email);
var userid = JSON.parse(userid);
var username = JSON.parse(username);
var email = JSON.parse(email);
var displaydata = ("User ID : " + userid + "<br><br>Name : " + username + "<br><br>Email :" + email);
document.getElementById("demo").innerHTML = displaydata;
})
.catch(function (error) {
document.getElementById("demo").innerHTML = "Bad response";
});
}
+++++++++++++++++++++++++++++
app.post('/userget', function (req, res) {
const userid = req.body.userid;
console.log ("User id == " + userid)
user.getUser(userid, function (err, result) {
if (!err) {
console.log(result)
res.send({result})
} else{
res.send(err.errno + " No record");
}
res.end()
});
});
+++++++++++++++++++++
app.post('/api/userget', verifyToken, (req, res) => {
const userid = req.body.userid;
console.log ("User id == " + userid)
jwt.verify(req.token, secretKey, (err, authData) => {
if(err) {
res.sendStatus(403);
} else {
user.getUser(userid, function (err, result) {
if (!err) {
console.log(result)
res.send({result})
} else{
res.send(err.errno + " No record");
}
res.end()
});
res.json({
message: 'Post created...',
authData : authData
});
}
});
});
Error in terminal
/home/ronaldtan/Programming/webservices/node_modules/mysql/lib/protocol/Parser.js:437
throw err; // Rethrow non-MySQL errors
^
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at ServerResponse.header (/home/ronaldtan/Programming/webservices/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/home/ronaldtan/Programming/webservices/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/home/ronaldtan/Programming/webservices/node_modules/express/lib/response.js:267:15)
at ServerResponse.send (/home/ronaldtan/Programming/webservices/node_modules/express/lib/response.js:158:21)
at /home/ronaldtan/Programming/webservices/controller/app.js:170:17
at Query. (/home/ronaldtan/Programming/webservices/model/user.js:44:32)
at Query. (/home/ronaldtan/Programming/webservices/node_modules/mysql/lib/Connection.js:526:10)
at Query._callback (/home/ronaldtan/Programming/webservices/node_modules/mysql/lib/Connection.js:488:16)
The problem is the following:
user.getUser(userid, function (err, result) {
if (!err) {
console.log(result)
res.send({
result
})
} else {
res.send(err.errno + " No record");
}
res.end()
});
res.json({
message: 'Post created...',
authData: authData
});
The second statement (res.json(...)) is executed before the async-operation user.getUser(..) has finished. So once its callback is executed, res.json will already have finished and since you are trying to res.send again (res.json does the same operation under the hood) you get the error.
It seems like you can just remove the res.json(...) statement as you want to return the found user, not some info about creating a post.

How can i send server to client '''user''' in this code?

I am using this code for get Facebook user profile but i cant send client this user variable. How can i do it ?
Daha neler yazayım derdim bu kadar işte. Facebook kullanıcı bilgilerini client tarafına dönemedim. Ne yapmalıyım ?
Here is my code :
router.post('/fbLogin', async function (ctx, next) {
var user;
console.log(ctx.request.body.token);
var options = {
host: 'graph.facebook.com',
port: 443,
path: '/v2.11/me?fields=id,first_name,last_name,email',
method: 'GET',
headers: { 'Authorization': 'Bearer ' + ctx.request.body.token }
};
const req = https.request(options, async function (res) {
res.setEncoding('utf8');
res.on('data', async function (d) {
var fbJsonObject = JSON.parse(d);
user = await db.collection('users').findOne({ facebookId: fbJsonObject.id });
if (!user) {
var uname = fbJsonObject.first_name.toString() + '_' + fbJsonObject.last_name.toString().substring(0, 1);
console.log(uname);
var count = await db.collection('users').find({ username: /uname/ }).count();
if (count != 0) {
uname = uname + count.toString();
}
var pass = customPassword();
await db.collection('users').insertOne({
method: 'facebook',
email: fbJsonObject.email,
username: uname,
password: phash.generate(pass),
friends: [],
facebookId: fbJsonObject.id
});
user = await db.collection('users').findOne({ facebookId: fbJsonObject.id });
console.log("Kayıt başarılı");
console.log(user);
}
})
});
req.end();
});
and client side code :
async loginWithFB() {
await this.facebook.login(['email', 'public_profile']).then((response: FacebookLoginResponse) => {
this.facebook.api('me?fields=id,name,email,first_name,last_name,picture.width(720).height(720).as(picture_large)', []).then(profile => {
//this.userData = { id: profile['id'] }
this.fb(response.authResponse.accessToken);
})
})
}
async fb(token2) {
var resp = await this.http.post('http://api.suma.nopsmart.com:3000/fbLogin', {
token: token2
}).toPromise();
var x = resp.json();
console.log(x);
}

AWS Cognito: Missing credentials in config

If a user logs in, I'm checking if the user has the required policies for IoT, if not, i'm attaching it.
This works fine, if i'm logging in for the first time.
Now when I'm logging out, and try to login with a different user, for some reason the credentials are missing, and when i'm refreshing the page, its working again....
window.login = function() {
var shadowsRegistered = false;
AWSCognito.config.region = AWSConfiguration.region;
AWSCognito.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: AWSConfiguration.IdPoolId
});
var authenticationData = {
Username : document.getElementById("benutzername").value,
Password : document.getElementById("passwort").value
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
var poolData = {
UserPoolId : AWSConfiguration.UserPoolId,
ClientId : AWSConfiguration.ClientAppId
};
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData = {
Username : document.getElementById("benutzername").value,
Pool : userPool
};
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
AWS.config.region = AWSConfiguration.region;
var auth_params = {
IdentityPoolId: AWSConfiguration.IdPoolId,
Logins : {
'cognito-idp.eu-central-1.amazonaws.com/eu-central-XXXX' : result.getIdToken().getJwtToken()
}
};
AWS.config.credentials = new AWS.CognitoIdentityCredentials(auth_params);
var cognitoIdentity = new AWS.CognitoIdentity();
cognitoIdentity.getId(auth_params, function(err, data) {
if (err) {
cognitoId = AWS.config.credentials.identityId;
}
else{
cognitoId = data.IdentityId;
}
var iot = new AWS.Iot();
iot.listPrincipalPolicies({principal: cognitoId}, function(err, data) {
if (err) {
console.log(err, err.stack); //ERROR on 2nd login
}
else{
// not related, works on the first login..
The Error I'm receiving:
CredentialsError: Missing credentials in config
I fixed it by myself. You need to clear the cached credentials.
$('#logout').click(function() {
currentUser = userPool.getCurrentUser();
currentUser.signOut();
AWS.config.credentials.clearCachedId();
AWS.config.credentials = new AWS.CognitoIdentityCredentials({});
location.reload();
});

javasctipt - asynchronous issue for return value

I am working in MEAN STACK application and i want to set mail's parameters dynamic.
route.js
var Helper = require("../helper.js");
router
.route("/api/user/registration")
.POST(function (req, res) {
//after user insert send mail
Helper.sendCustomEmail(params, function (error, response) {
if (error) {
console.log("Mail : " + error);
res.json({"status": 0, "error": {"other": "Oops! something went wrong, please try again later"}});
} else {
console.log("Message sent");
res.json({status: 1, message: 'Thank you for registration. You will get verification email soon', token: res.locals.user.jwttoken});
}
});
});
Helper.js
exports.sendCustomEmail = function(params, callback) {
//Include nodejs mailer and smtp module
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
//read header email template
var headerHtml = params.fs.readFileSync(basePath + "emailHeader.html").toString();
//read footer email template
var footerHtml = params.fs.readFileSync(basePath + "emailFooter.html").toString();
//Your dynamic template html only
var dynamicMessage = params.message;
var message = headerHtml + dynamicMessage + footerHtml;
message = message.replace(/##DOMAIN_URL##/g, "http://" + params.domainUrl);
// create reusable transporter object using the default SMTP transport
var transporter = nodemailer.createTransport(smtpTransport({
host: this.getSiteSetting("SMTP_HOST"),
secure: true,
auth: {
user: this.getSiteSetting("SMTP_USER"),
pass: this.getSiteSetting("SMTP_PSSSWORD")
},
tls: {
rejectUnauthorized: false
}
}));
transporter.sendMail({
from: this.getSiteSetting("SMTP_FROM"),
to: params.to, // receiver
subject: params.subject,
html: message // body
}, function(error, response) { //callback
callback(error, response);
});
};
var SiteSetting = require('../models/siteSetting');
exports.getSiteSetting = function($keyword) {
if ($keyword !== undefined && $keyword !== null && $keyword !== "") {
SiteSetting.findOne({setting_key : $keyword},function(err,siteSetting){
if(err){
return null;
}else{
if(siteSetting !== null){
console.log(siteSetting.setting_value);
return siteSetting.setting_value;
}
}
});
}else{
return null;
}
};
dependencies
"express" => "version": "4.13.4",
"mongoose" => "version": "4.4.4",
"mongodb" => "version": "2.4.9",
"OS" => "ubuntu 14.04 lts 32bit",
from the following code SiteSetting function console.log print properly but before return mail send error occur.
Please give me a proper guideline for this code.
This can be solved as bellow.
exports.sendCustomEmail = function(params, callback) {
//Include nodejs mailer and smtp module
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
//read header email template
var headerHtml = fs.readFileSync(basePath + "app/client/views/layout/emailTemplates/emailHeader.html").toString();
//read footer email template
var footerHtml = fs.readFileSync(basePath + "app/client/views/layout/emailTemplates/emailFooter.html").toString();
//Your dynamic template html only
var dynamicMessage = params.message;
var message = headerHtml + dynamicMessage + footerHtml;
message = message.replace(/##DOMAIN_URL##/g, "http://" + params.domainUrl);
var host = null;
var user = null;
var pass = null;
var from = null;
this.getSiteSetting("SMTP_HOST", function(res) {
host = res;
setParams();
});
this.getSiteSetting("SMTP_USER", function(res) {
user = res;
setParams();
});
this.getSiteSetting("SMTP_PASS", function(res) {
pass = res;
setParams();
});
this.getSiteSetting("MAIL_FROM", function(res) {
from = res;
setParams();
});
var setParams = function() {
if (host !== null && user !== null && pass !== null && from !== null) {
// create reusable transporter object using the default SMTP transport
var transporter = nodemailer.createTransport(smtpTransport({
host: host,
//port: 25,
//port: 465,
secure: true,
auth: {
user: user,
pass: pass
},
tls: {
rejectUnauthorized: false
}
}));
transporter.sendMail({
from: from,
to: params.to, // receiver
subject: params.subject,
html: message // body
}, function(error, response) { //callback
callback(error, response);
});
}
};
}
var SiteSetting = require('../models/siteSetting');
exports.getSiteSetting = function(keyword, callback) {
if (keyword !== undefined && keyword !== null && keyword !== "") {
SiteSetting.findOne({ setting_key: keyword }, function(err, siteSetting) {
if (err) {
callback(null);
} else {
if (siteSetting !== null) {
//console.log(siteSetting.setting_value);
callback(siteSetting.setting_value);
}else{
callback(null);
}
}
});
} else {
callback(null);
}
};

Categories