NodeJS / Express: Get Username and Password from Request - node.js

I am using NodeJS and Express, and I want to get the Username and Password parameters from a request. I've searched for a while now, and I can't find my answer.
I want to accept a user parameter from a cURL command:
curl --request --POST -u USERNAME:PASSWORD -H "Content-Type:application/json" -d "{\"key":\"value\"}" --url https://api.example.com/my_endpoint
In my application:
app.post('/my_endpoint', async (req, res, next) => {
const kwargs =. req.body;
const userName = req['?'];
const password = req['?'];
});

You are sending the credentials as a basic-auth header (since you're using curl's -u option). So in order to get the credentials from your request, you need to access this header and decode it. Here's one way to do this:
app.post('/my_endpoint', async (req, res, next) => {
if(req.headers.authorization) {
const base64Credentials = req.headers.authorization.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('utf8');
const [username, password] = credentials.split(':');
console.log(username, password);
}
});

How do I consume the JSON POST data in an Express application
I would do it this way
Assuming your call includes json content like this :
Remove -u USERNAME:PASSWORD
Edit -d "{ "username": "user", "password": "test" }"
curl --request --POST -H "Content-Type:application/json" -d "{ "username": "user", "password": "test" }" --url https://api.example.com/my_endpoint
Then you can access those variables with :
const userName = req.body.username;
const password = req.body.password;
Be careful, you need to use bodyParser middleware in express in order to be able to access the body variables.

Related

Send message with Google Business Messages using access token

Currently I can send a message with Google Business Messages API from an agent to a user from NodeJS code.
const bmApi = new businessmessages.businessmessages_v1.Businessmessages({});
This requires an auth client for a given service account key/secret.
const auth = new GoogleAuth({
keyFilename: '/home/my-keyfile.json',
scopes: 'https://www.googleapis.com/auth/businessmessages',
});
const authClient = await auth.getClient();
// and logic to send message
However the key/secret is hard-coded at the moment.
But at this point in the flow I have the access token.
And want to use that instead of the .json file.
But it will not accept the access token.
Another approach is to directly call the REST interface.
https://developers.google.com/business-communications/business-messages/guides/how-to/message/send
curl -X POST https://businessmessages.googleapis.com/v1/conversations/__CONVERSATION_ID__/messages \
-H "Content-Type: application/json" \
-H "User-Agent: curl/business-messages" \
-H "$(oauth2l header --json ./service_account_key.json businessmessages)" \
-d "{
'messageId': '$(uuidgen)',
'text': 'Hello world!',
'representative': {
'avatarImage': 'https://developers.google.com/identity/images/g-logo.png',
'displayName': 'Chatbot',
'representativeType': 'BOT'
}
}"
Added a header with token.
access_token: <access-token>
But again no joy.
{
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
}
I know this should work as we do it for calls to Google Play Store:
try {
let response = await this.httpClient.post({
url: `${process.env.PLAYSTORE_URL}/${packageName}/reviews/${reviewId}:reply`,
body : {
"replyText" : replyText
},
query: {
access_token: access_token <----
}
});
Any help would be much appreciated.
i think you need to use the variable that match the current CONVERSATION_ID in the url path, with the currently one of each agent message received.
Example:
curl -X POST https://businessmessages.googleapis.com/v1/conversations/$(uuidgen)/messages \
-H "Content-Type: application/json" \
-H "User-Agent: curl/business-messages" \
-H "$(oauth2l header --json ./service_account_key.json businessmessages)" \
-d "{
'messageId': '$(uuidgen)',
'text': 'Hello world!',
'representative': {
'avatarImage': 'https://developers.google.com/identity/images/g-logo.png',
'displayName': 'Chatbot',
'representativeType': 'BOT'
}
}"

Basic authentication and passing token to next endpoint

I am new to basic authentication and tokens.
I have been playing around with postman in order to get a token using basic authentication and then passing the token as a bearer token to access another endpoint. I wanted to know how I would code this into api calls using node and express.
I know that for Basic auth I need to encode the client id and secret into base64
curl --request POST \
--url http://localhost:8080/token/ \
--header 'authorization: Basic ***' \
--header 'content-type: application/x-www-form-urlencoded' \
--data
grant_type=credentials
The token I get from the above call I want to pass onto the below call
curl --request POST \
--url http://localhost:8080/login \
--header 'authorization: Bearer ***' \
--header 'content-type: application/x-www-form-urlencoded' \
--data
user=1
How would this like as code in a node application
I would recommend json web token aka jwt for this purpose.
Right now I code REST API in express, mongodb, and I am using jwt for auth.
Since I dont use any frontend framework or lib, I use cookie for jwt token storage.
const jwt = require('jsonwebtoken');
const generateToken = (res, id, auth_level) => {
const token = jwt.sign({id,
auth_level
}, process.env.JWT_KEY, {
expiresIn: '7d'
});
return res.cookie('token', token, {
expires: new Date(Date.now() + 1000 * 60 * 15),
secure: false,
httpOnly: true,
});
};
module.exports = generateToken
In this example I call this function on sucessful login try. And after that on every route access, using middleware I try to resolve if user have this token and try to resolve token.
const jwt = require('jsonwebtoken');
// Verify user token from cookie
const verifyToken = async (req, res, next) => {
// Get token from cookie named token
const token = req.cookies.token || '';
try {
// Check if cookie exists, maybe expired maybe user didnt have one - no login
if (!token) {
return next();
}
// Decrypt users jwt token and get information
const decrypt = await jwt.verify(token, process.env.JWT_KEY);
// Pass that infomation to request user object
req.user = {
id: decrypt.id,
auth_level: decrypt.auth_level,
test: 'test'
};
// Continue with exectution of app
return next();
} catch (err) {
return res.status(500).json(err.toString());
}
};
module.exports = verifyToken;
If this token is valid, I pass custom user object to req object.
After this I protect routes with custom middlewares. Code is inspired by this tutorial, would recommend it.

Axios Basic Auth with API key Example in Node

There is a curl request like this:
curl -X GET --header 'Accept: application/json' --header 'Authorization: Basic [==APIKEYHERE==]' 'https://apipath.com/path?verbose=true'
I removed the APIKEY and the API path for privacy.
The curl request is working fine, I can't figure out how to convert this into an Axios request since it only needs an API key and not a username and password.
Here is the example I found:
axios.get('https://apipath.com/path?verbose=true', {}, {auth: {username: 'username', password: 'password'}})
.then(function(response) {
console.log(response.data, 'api response');
})
I'm not sure how to get this to work for my case?
The short answer to adding an X-Api-Key to an http request with axios can be summed up with the following example:
const url =
"https://someweirdawssubdomain.execute-api.us-east-9.amazonaws.com/prod/custom-endpoint";
const config = {
headers: {
"Content-Type": "application/json",
},
};
// Add Your Key Here!!!
axios.defaults.headers.common = {
"X-API-Key": "******this_is_a_secret_api_key**********",
};
const smsD = await axios({
method: "post",
url: url,
data: {
message: "Some message to a lonely_server",
},
config,
});
I was stuck for 8 hours trying to figure this out as the errors lined up in the queue, adding the key to the default headers was the only way I could get this to work.
Given the cURL command including --header 'Authorization: Basic [==APIKEYHERE==]', you know that the server wants a header sent using the Basic authentication scheme. That means that your API key is both the username and password joined by a : and encoded with Base64. So, you can decode what the username and password should be by decoding your API key with Base64 and seeing the values joined by the colon.
Consider the spec detailed on MDN: Authorization Header
So if your API key is Ym9iOnBhc3N3b3JkMQ==, and you decode it with Buffer.from("API_KEY", "base64").toString(), you would get the value bob:password1 meaning your username is bob and your password is password1 making your request:
const [username, password] = Buffer.from("YOUR_API_KEY", "base64").toString().split(":");
axios.get('https://apipath.com/path?verbose=true', {}, {
auth: {
username,
password
}
})
.then(function(response) {
console.log(response.data, 'api response');
})
You can define a function like this, then you can pass the token to header after login success.
import axios from "axios";
const setAuthToken = token => {
if (token) {
// Apply to every request
axios.defaults.headers.common["Authorization"] = token;
} else {
// Delete auth header
delete axios.defaults.headers.common["Authorization"];
}
};
axios.get('https://apipath.com/path?verbose=true', {}, {auth: {username: 'username', password: 'password'}})
.then(() => setAuthToken(response.token));

How to get the equivalent nodejs Requst to CURL command?

I have following CURL command
curl -u YOUR_API_KEY:x \
-H 'Content-Type: application/json' \
-X POST \
-d '{"first_name":"Tony", "kind":"person", "contact_name":"Stark"}' \
'https://ACCOUNT_NAME.quadernoapp.com/api/contacts.json'
I want do this request in NodeJS using the request module.
This is the code I have written.
var options = {
uri: 'https://ACCOUNT_NAME.quadernoapp.com/api/contacts.json',
json: true,
auth: {
user: 'YOUR_API_KEY'
}
data: {"first_name" : "Tonsdfasdy", "kind":"peasdfarson", "contact_name":"Staasdfadfadrk"}
}
request.post(options, function cb(){})
But it is not authenticatd properly. What is the error here?
You're authenticating using HTTP Basic authentication in your cURL command, where username and password are provided with the -u option and separated by :, so you need to provide your code with the password, like so :
var options = {
uri: 'https://ACCOUNT_NAME.quadernoapp.com/api/contacts.json',
json: true,
auth: {
user: 'YOUR_API_KEY',
password: 'x'
},
body: {
first_name : "Tonsdfasdy", kind:"peasdfarson", contact_name:"Staasdfadfadrk"
}
}
request.post(options, function cb(){})
And please try to pass your JSON object in an attribute named body rather than data (it will be transformed to a JSON string thanks to the json: trueoption).
You may also want to check this one : how to do Auth in node.js client
Hope this helps!

curl req into firebase functions req

Hello I am following the instructions to implement an encryption payment from from Adyen. I am using Firebase as my backend. Now the Dokumentation want that I make a backend req like this:
curl -u "ws#Company.SomeCompany":"SomePassword" \
-H "Content-Type: application/json" \
-X POST \
--data \
'{
"additionalData": {
"card.encrypted.json":"adyenjs_0_1_4p1$..."
},
"amount" : {
"value" : 10000,
"currency" : "EUR"
},
"reference" : "Your Reference Here",
"merchantAccount" : "TestMerchant" }'\
https://pal-test.adyen.com/pal/servlet/Payment/v30/authorise
Can someone please help me to convert this curl request into an firebase functions request? For example:
exports.helloWorld = (req, res) => {
if (req.body.message === undefined) {
// This is an error case, as "message" is required
res.status(400).send('No message defined!');
} else {
// Everything is ok
console.log(req.body.message);
res.status(200).end();
}
};
You need to pass your Adyen credentials as data in http post request. Add firebase user token as Bearer token in Authroization token. So now your function will be:
exports.helloWorld = (req, res) => {
// check authorization of firebase.
if (!req.headers.authorization || !req.headers.authorization.startsWith('Bearer ')) {
res.status(403).send('Unauthorized');
return;
}
const idToken = req.headers.authorization.split('Bearer ')[1];
this.admin.auth().verifyIdToken(idToken).then(decodedIdToken => {
// new read the data like below
// req.body.username , req.body.additionalData
})
};

Resources