Axios - How to get the Cookies from the response? - node.js

I need to get an authentication cookie from a website, while performing my request using Axios.
var axios = require('axios');
const authentication = async(login, password) => {
var data = `MYPAYLOAD${login}[...]${password}`;
var config = {
method: 'post',
url: 'https://mywebsite.com/login.aspx',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data : data,
};
try {
return await axios(config, {withCredentials: true});
} catch (error) {
console.log('Error: cannot authenticate...')
}
}
const init = async() => {
const login = 'LOGIN';
const password = 'PASSWORD';
const response = await authentication(login, password);
console.log(response);
}
init()
I'm receiving some Cookies that I need, but the one including the auth token is missing.
If I use exactly the same settings in Postman, I'm receiving the AUTH_TOKEN I'm looking for.
Where am I wrong?
Thanks

Related

I am getting weird data as a response

I am trying to get some details of mail that I have sended using google-api. I am using messageId that I have received after sending email. I am expection the data to be in json format.
Here is the Nodejs code for reading sended mail:
app.post("/readMail", async (req, res)=>{
let messageId = req.body.messageId;
try {
const oAuth2Client = new google.auth.OAuth2(
properties.GOOGLE_CLIENT_ID,
properties.GOOGLE_CLIENT_SECRET,
);
oAuth2Client.setCredentials({ refresh_token: properties.REFRESH_TOKEN });
const { token } = await oAuth2Client.getAccessToken();
const generateConfig = (url, accessToken) => {
return {
method: "get",
url: url,
headers: {
Authorization: `Bearer ${accessToken} `,
"Content-type": "application/json",
},
};
};
const url = `https://gmail.googleapis.com/gmail/v1/users/Abhisek721#gmail.com/messages/${messageId}`;
const config = generateConfig(url, token);
const response = await axios(config);
let data = await response.data;
res.json(data);
} catch (error) {
res.send(error);
}
})
And This the response:
"\u001f\ufffd\b\u0000\u0000\u0000\u0000\u0000\u0002\ufffd\ufffdUmo\ufffd:\u0014\ufffd\ufffd_a\ufffdu\ufffds\u0012^\ufffdN\ufffd\u0006\t/a\ufffd2\ufffd\ufffd\ufffdީr\u0012\ufffd\u0018\ufffd8rLB6\ufffd\ufffd_'P\ufffdݱ\ufffd^]\ufffd\ufffd\ufffd\ufffd\ufffd=\ufffd\ufffd\ufffd\u000e\ufffd\n\ufffd*\ufffd\ufffd\ufffd\ufffdu\ufffd:\\75\ufffd]C\ufffdrU\ufffdD\ufffd1\ufffdW4(r0\ufffd\ufffdDj\ufffd%\ufffd\ufffdd\ufffd\u0019\ufffd*\ufffd\ufffdR\ufffdD$\ufffd\ufffd(\u0000:!\"\u0014\ufffd8r\ufffd\ufffd\ufffd!\ufffd8\u0004$Nv!"
I was expecting to get something like json data.

Axios POST request to Twillio returns with an Authentication Error?

in Node.js, I am trying to send a POST request with Axios to Twilio and send an SMS message to my phone. But I am getting an 'error: Authentication Error - No credentials provided ? Here is the code:
const body = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Body: 'hi from vsc',
To: toNumber,
From: fromNumber,
};
const headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: `Basic ${accountSID}:${authToken}`,
};
exports.axios = () => axios.post(`https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`, body, headers).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err);
});
I also tried to use the same parameters with POSTMAN and the POST request is successful. I also tried to encode my authorization username and password to Base 64, but with no success.
I wrote to Twilio customer help but haven`t received any replies yet.
Axios makes an auth option available that takes an object with username and password options. You can use this with the username set to your account SID and password set to your auth token.
The headers object should be sent as the headers parameter of a config object in the third parameter to axios.post. Like so:
const params = new URLSearchParams();
params.append('Body','Hello from vcs');
params.append('To',toNumber);
params.append('From',fromNumber);
const headers = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
};
exports.axios = () => axios.post(
`https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`,
params,
{
headers,
auth: {
username: accountSID,
password: authToken
}
}
}).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err);
});
Headers is actually a field of config, try something like this:
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: `Basic ${accountSID}:${authToken}`,
}
}
axios.post(URL, data, config).then(...)
Or this (general example calling a Twilio endpoint)
const axios = require('axios');
const roomSID = 'RM1...';
const participantSID = 'PA8...';
const ACCOUNT_SID = process.env.ACCOUNT_SID;
const AUTH_TOKEN = process.env.AUTH_TOKEN;
const URL = "https://insights.twilio.com/v1/Video/Rooms/"+roomSID+"/Participants/"+participantSID;
axios({
method: 'get',
url: URL,
auth: {
username: ACCOUNT_SID,
password: AUTH_TOKEN
}
})
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
Working code:
const params = new URLSearchParams();
params.append('Body','Hello from vcs');
params.append('To',toNumber);
params.append('From',fromNumber);
exports.axios = () => axios.post(
`https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`,
params,
{
auth: {
username: accountSID,
password: authToken,
},
},
).then((res) => {
console.log(res, 'res');
}).catch((err) => {
console.log(err);
});
The previous solutions did not work for me. I encountered either the Can't find variable: btoa error or A 'To' phone number is required..
Using qs worked for me:
import qs from 'qs';
import axios from 'axios';
const TWILIO_ACCOUNT_SID = ""
const TWILIO_AUTH_TOKEN = ""
const FROM = ""
const TO = ""
const sendText = async (message: string) => {
try {
const result = await axios.post(
`https://api.twilio.com/2010-04-01/Accounts/${TWILIO_ACCOUNT_SID}/Messages.json`,
qs.stringify({
Body: message,
To: TO,
From: FROM,
}),
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
auth: {
username: TWILIO_ACCOUNT_SID,
password: TWILIO_AUTH_TOKEN,
},
},
);
console.log({result});
} catch (e) {
console.log({e});
console.log({e: e.response?.data});
}
};

401 Unauthorized error when making axios request

I am using axios to make different GET and POST requests to a third-party API that requires a username and password login to access the data. I have tried several approaches to make this work but I keep getting this error in the console.
data: '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">\n' +
'<html><head>\n' +
'<title>401 Unauthorized</title>\n' +
'</head><body>\n' +
'<h1>Unauthorized</h1>\n' +
'<p>This server could not verify that you\n' +
'are authorized to access the document\n' +
'requested. Either you supplied the wrong\n' +
'credentials (e.g., bad password), or your\n' +
"browser doesn't understand how to supply\n" +
'the credentials required.</p>\n' +
'</body></html>\n'
}
I have been using this approach to send the username and password with node.js
export const getCameraStream = (req, res) => {
let conn = createConnection(config);
let query = `SELECT * FROM cameras WHERE id = ${req.params.id}`
conn.connect();
conn.query(query, async (error, rows, _) => {
const camera = rows[0];
const username = camera.user;
const password = camera.pass;
if (error) {
return res.json({ "status": "failure", "error": error });
}
const result = await axios({
method: 'get',
url: <placeholder for api url>,
auth: {
username, password
}
})
console.log(result);
});
conn.end();
}
and then use this code on my React front-end
const getCameraStream = async () => {
const username = camera.user
const password = camera.pass
try {
const token = Buffer.from(`${username}:${password}`).toString('base64')
const res = await publicRequest.get(`camera/getCameraStream/${camera.id}`, {
headers: {
'content-type': 'multipart/x-mixed-replace; boundary=--myboundary',
'Authorization': `Basic ${token}`
},
auth: {
username, password
}
})
console.log(res)
} catch (error) {
console.error(error)
}
}
Using this approach, I am able to pass the username and password to the server and the responseUrl property is correct. However, my app crashes and I keep getting the same unauthorized error in the console. Could this be an issue with the fact that the browser is sending a preflight OPTIONS request or am I overlooking something with my authorization?

How do I store JWT Token after receiving from Cognito? Logging in via the Cognito Hosted UI

Architecture: front end Angular, backend nodejs/express.
Currently the setup works as follow:
Login to the site via the Cognito Hosted UI
This redirects to our home page and sends us a code in the URL
I pull down this code in Angular
import { Component, OnInit } from '#angular/core';
import { DbService } from '../db.service';
import { Iss } from '../db.service';
import { Router, ActivatedRoute } from '#angular/router';
import { Http, Response, RequestOptions, Headers} from '#angular/http';
#Component({
selector: 'app-dashboard'
})
export class GroupSelectionComponent implements OnInit {
cognitoCode: string;
constructor(
private DbService: DbService,
private route: ActivatedRoute,
private router: Router
) {}
ngOnInit() {
this.route.queryParams
.subscribe(params => {
console.log(params);
console.log(params.code);
this.cognitoCode = params.code;
});
this.DbService.getIss(this.cognitoCode).subscribe(
iss => this.iss = iss
);
}
In the code you will see I am passing the congitocode to the dbservice for getIss.
db.service
getIss(cognitoCode ): Observable<Issuer[]> {
const url = hosturl +'i_l';
// let header: HttpHeaders = new HttpHeaders();
const httpOptions = {
headers: new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
'Authorization': cognitoCode
})
};
let params = new HttpParams()
console.log(httpOptions.headers);
return this._http.get(url, httpOptions)
.pipe(
map((res) => {
console.log(res);
return <Issuer[]> res;
})
);
}
I then send the code as part of the headers of my GET request to the backend.
The GET then hits my backend router with these settings.
var authMiddleware = require('../middleware/AuthMiddleware.js');
router.get('/i_l', authMiddleware.Validate, i_l.get);
This will then call my authMiddleware which takes the code provided by Cognito Hosted UI and use a POST against oauth2/token to get my JWT token.
That token is then parsed used to compare to the https://cognito-idp.us-east-2.amazonaws.com/REMOVED/.well-known/jwks.json for congnito.
Once validated the request continues and I get data back from the backend.
// POST that trades the code for a token with cognito
var options = {
'method': 'POST',
'url': 'https://REMOVED.amazoncognito.com/oauth2/token',
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
'grant_type': 'authorization_code',
'client_id': 'CLIENTIDREMOVED',
'code': req.headers['authorization'],
'redirect_uri': 'http://localhost/group-selection'
}
};
// First request gets the JSON request of the token using the POST above
request(options, function (error, response) {
if (error) throw new Error(error);
token = JSON.parse(response.body).access_token;
//localStorage.setItem('token', token);
// request pull down status based on validitiy of token
request({
url : `https://cognito-idp.us-east-2.amazonaws.com/REMOVED/.well-known/jwks.json`,
json : true
}, function(error, response, body){
console.log('token: ' + token);
if (!error && response.statusCode === 200) {
pems = {};
var keys = body['keys'];
for(var i = 0; i < keys.length; i++) {
var key_id = keys[i].kid;
var modulus = keys[i].n;
var exponent = keys[i].e;
var key_type = keys[i].kty;
var jwk = { kty: key_type, n: modulus, e: exponent};
var pem = jwkToPem(jwk);
pems[key_id] = pem;
}
var decodedJwt = jwt.decode(token, {complete: true});
if (!decodedJwt) {
console.log("Not a valid JWT token");
res.status(401);
return res.send("Not a valid JWT token");
}
var kid = decodedJwt.header.kid;
var pem = pems[kid];
if (!pem) {
console.log('Invalid token - decodedJwt.header.kid');
res.status(401);
return res.send("Invalid token - decodedJwt.header.kid");
}
jwt.verify(token, pem, function(err, payload) {
if(err) {
console.log("Invalid Token - verify");
res.status(401);
return res.send("Invalid token - verify");
} else {
console.log("Valid Token.");
return next();
}
});
} else {
console.log("Error! Unable to download JWKs");
res.status(500);
return res.send("Error! Unable to download JWKs");
}
});
});
Quesiton -- how I set this up so that the Token I get back continues for the user?
If I understand your question properly then you are trying to validate all your apis through cognito user right?
Then you just need to do two things.
Add in header JWT token once you are getting after login. Just store into your application scope and pass everytime whenever any API is calling.
Auth.signIn(data.username, data.password)
.then(user => {
let jwkToken = user.getSignInUserSession().getAccessToken().getJwtToken();
// Store above value in singletone object or application scope.
})
.catch(err => {
//error
});
Now When API is calling pass jwkToken as header.
Then Go AWS ApiGateWay Console and add into Authorizers.

axios post from lambda function not working

Trying to post from aws lambda using axios but it's not working...
I'm not really sure what's going on, but on postman this works.
In the call not configured correctly?
exports.handler = async (event) => {
const body = parseBody(event.body);
body.phone_number = decrypt(body.phone_number);
const username = 'SOMETOKEN';
const password = 'SOMEAPIKEY';
const token = Buffer.from(`${username}:${password}`, 'utf8').toString('base64');
const axios = require('axios');
const url = 'some_url';
const headers = {
'Authorization': `Basic ${token}`
};
const requestbody = {
To: '+12122806392',
From: '+12064622015'
};
const params = {headers: headers, body:requestbody};
console.log('posting');
axios.post(url, {
headers: headers,
body: requestbody
})
.then((response) => {
console.log(response);
}, (error) => {
console.log(error);
});
}

Resources