I want to automate the OAuth 2.0 token automatically via javascript. Is there any way I can do that and obtain the token to use it in the artillery scrtips.
For the OAuth token generation I have below details:
Auth URL
Client ID
Scope
It is done by client authentication credentials.
Below is the sample code I am using to generate the token:
var ClientOAuth2 = require('client-oauth2')
var Auth = new ClientOAuth2({
clientId: 'ClientID',
accessTokenUri: 'https://Auth_URL/v2.0/token',
authorizationUri: 'https://Auth_URL/v2.0/authorize',
redirectUri: 'https://Auth_URL/',
scope: 'api://Scope/access_as_user'
})
Auth.owner.getToken('Username', 'password')
.then(async (user) => {
await console.log(user) //=> { accessToken: '...', tokenType: 'bearer', ... }
}).catch((e) => { console.log('error show',e); })
.finally( () => console.log('end'));
You can declare your custom JS files which will be triggered every time before the request:
Your YAML file can be like here:
config:
target: "https://baseUrl.com"
phases:
- duration: 60
arrivalRate: 100
processor: "./customFile.js"
scenarios:
- flow:
- post:
url: "/pathInYourApi"
headers:
Content-Type: "application/json"
Accept: application/json
json: {}
beforeRequest: "beforeRequest"
and then your customFile.js script:
module.exports = {
beforeRequest: beforeRequest,
};
function beforeRequest(requestParams, context, ee, next) {
// Call your OAuth client, and after you obtain token you can assign it to requestParams Authorization header
// eg. requestParams.headers.Authorization = `Bearer + ${token}`
return next(); // MUST be called for the scenario to continue
}
Related
am very new to Pact-js and contract testing I'll try my best to explain my issue.
for now, I am only trying to generate the consumer contract
here is my pact provider:
export const provider = new Pact({
consumer: 'Users',
provider: 'UsersService',
port: 1234,
log: path.resolve(process.cwd(), 'logs', 'pact.log'),
pactfileWriteMode: 'overwrite',
logLevel: "DEBUG",
dir: path.resolve(process.cwd(), 'pacts'),
});
and here is my test:
jest.mock("axios");
const EXPECTED_BODY = {...}
describe("Pact tests axios", () => {
describe("/GET login", () => {
beforeAll(() => provider.setup());
afterEach(()=> provider.verify())
afterAll(() => provider.finalize());
it("should login user and response with user object", async () => {
await provider.addInteraction({
state: 'user logged', uponReceiving: 'request logged user', withRequest: {
method: 'GET',
path: '/users/login',
body: {username: "test", password: "11223344"},
}, willRespondWith: {
status: 200, headers: {
'Content-Type': 'application/json',
}, body: eachLike(EXPECTED_BODY),
},
});
axios.get.mockResolvedValueOnce(EXPECTED_BODY);
const loggedUser = await loginUser("test", "11223344")
expect(axios.get).toHaveBeenCalledTimes(1)
expect(axios.get).toHaveBeenLastCalledWith("http://localhost:8080/users/login", {"headers": {"Content-Type": "application/json"}, "params": {"password": "11223344", "username": "test"}})
expect(loggedUser).toEqual(EXPECTED_BODY)
})
});
})
I should say that my original request takes two parameters username and password and returns an object containing all that user's information of course the user exists if not it returns null
here is the API call function if needed:
export default async function loginUser(username, password) {
try{
return await axios.get(("http://localhost:8080/users/login"), {
headers: {
"Content-Type": "application/json"
},
params: {
username: username,
password: password
}
})
}catch (e){
return null
}
}
Pact expects you to actually make the call to the endpoint you're mocking in Pact.
Missing requests: GET /users/login
This error says "you said you'd make a GET call to /users/login but I didn't receive it".
jest.mock("axios");
This looks like you're mocking the HTTP client Axios. Now you have a mock for the thing that needs to send requests to the Pact Mock.
In a Pact test, think of it as a unit tests for your API client code. The actual request needs to be sent to the Pact Mock and Pact will check the correct request was made, and return back the mocked response.
So the solution is simple:
Remove all of the axios mocking
Provide a way to modify the API target for loginUser
Configure your API client to send the request to localhost:1234 instead of the real thing before running the tests
(NOTE: you can have pact find a free port dynamically by not setting the port option, and take the host from the response from the setup() call)
I am trying to write a pre-request script for getting JWT for my postman tests using Laravel. I tried the js code that works perfect when I use .NET REST API, but now in Laravel it is not working. If I hit the login endpoint it works I got my JWT, and the response look like this:
{
"status_code": 200,
"access_token": "15|we59pMz1wA6TqwALTJg9IT8pNs3mc4Omwibm7Lkd",
"token_type": "Bearer"
}
Here is my pre-request JS script:
const requestBody =
{
"Email" : "username",
"Password" : "password"
}
pm.sendRequest
({
url: 'http://localhost:8000/api/login',
method: 'POST',
header:
{
'content-type': 'application/json'
},
body:
{
mode: 'raw',
raw: requestBody
}
}, function (err, res)
{
if(err)
{
console.log("Login failed:");
console.log(JSON.stringify(err));
return;
}
else
{
const response = res.json();
const token = 'Bearer ' + response.access_token;
pm.environment.set("TOKEN", token);
console.log("Login succeeded!");
}
});
The response in pre-request is this:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="refresh" content="0;url='http://localhost:8000'" />
<title>Redirecting to http://localhost:8000</title>
</head>
<body>
Redirecting to http://localhost:8000.
</body>
</html>
Your token doesn't seem like a JWT.
This is not base64 and does not contain the 3 parts: header, payload, signature.
Don't hesitate to look at my Postman pre request gist for JWT there are some explanations here too.
It contains one function to check the token validity:
/** Checks if the JWT is present and not expired
The token is expected to be found in `token` environment variable
*/
function isValidToken() {
const token = pm.environment.get("token");
if (!token) {
console.log("Token is missing");
return false;
}
// Payload is retrieved by
// JSON parsing the base64 decoded `atob()` 2nd part of the JWT `[1]`
// (1st is the header, 3rd is the signature)
const payload = JSON.parse(atob(token.split('.')[1]));
// Expiration timestamp (in seconds) is located in the `exp` key
const millisecBeforeExpiration = (payload.exp * 1000) - (new Date()).getTime();
if (millisecBeforeExpiration <= 0) {
console.log("Token is expired");
return false;
}
console.log("Token is valid",
`will expire in ${millisecBeforeExpiration / 1000} seconds`);
return true;
}
and one to get a new token
/** Gets a new JWT
This can be entirely custom authentication.
Here we rely on `user`/`pass` environment variables.
`host` also needs to be set, feel free to use another route instead of /give-me-a-jwt :)
*/
function login() {
const body = JSON.stringify({
"user": pm.collectionVariables.get("user"),
"pass": pm.collectionVariables.get("pass")
});
const request = {
url: pm.collectionVariables.get("host") + "/give-me-a-jwt",
method: "POST",
header: {
"Content-Type": "application/json",
"Accept": "application/json",
},
body,
};
pm.sendRequest(request, (err, res) => {
if (res.code !== 200) throw new Error(res.status);
console.log("Token refreshed");
pm.environment.set("token", res.json().token);
});
}
Now you can just get a new token if not valid:
if (!isValidToken()) login();
Of course don't forget to use your brand new token in your Postman's Bearer Token authentication type
I am new in Node.js. I am using express, passport, passport-oauth2 strategy for authentication for my react application.
My react application is running on 'https//localhost:8060'
My Passport.js auth service is running on 'http://localhost:8080'
Below is the passport.js strategy configuration present in my node service index.js
passport.use(
new OAuth2Strategy(
{
authorizationURL: 'https://idp-portal-URL', // IDP portal url
tokenURL: 'https://token.oauth2', // token URL
callbackURL: 'https://localhost:8060/auth', // **REACT application call back URL**
clientID: clientCreds.clientID,
clientSecret: clientCreds.clientSecret,
scope: 'openid profile',
},
function(accessken, refreshToken, user, profile, done) {
const ca = user.id_token;
return done(null, user);
},
),
);
Then authenticating below route: This is route which i am calling from my React application e.g: 'http://localhost:8080/login'
app.get(
'/login',
passport.authenticate('oauth2', { failureRedirect: '/failed' }),
function(req, res, next) {
next();
const config = {
method: 'post',
url: `https://idp-a/authorization.oauth2?token=${req.user.access_token}`,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data: {
client_id: clientCreds.clientID,
client_secret: clientCreds.clientSecret
},
};
axios(config)
.then(function(response) {
res.redirect(`https://localhost:8060/#/auth?ssoParams=${queryParam}`);
})
.catch(function(error) {
console.log(error);
});
// Successful authentication, redirect home.
},
);
with this above code user able to successfully authenticate and redirecting back to my react application URL which is configured in as callback URL with appending auth code in query param. like below:
"https://localhost:8060/auth?code=***************"
But before that in node service itself I want to retrieve access token using the auth code received in query param.
How can I retrieve access token using auth code by making API call and then redirect back to my react application with access code. The axios call which I wrote in call back function is not executing and nothing printing in console or no error.
Please help here, will appreciate your help.
I am very new to the Google OAUth2.0 authentication and thus my question sounds like dumb. However, I am stuck with this problem quite a time and need your input to solve it.
I was integrating the Globus login within my app. Globus login using Google OAuth-2 protocol for authentication. According to the Globus Auth developer guide, I successfully redirect the app to their authorization service, the user can put their credential to authenticate, and the app receives the code returned from the Globus Auth server upon successful authentication. Next step is sending the code to the Token endpoint to get the access token. I used the following code:
var querystring = require('querystring');
export const logInGlobus = (payload) => {
let tokenUri = encodeURIComponent(payload.redirect_uri);
let client_id = 'out app client id'
let client_secret = 'client secret generated for authentication'
let cred = btoa(client_secret);
return axios.post('https://auth.globus.org/v2/oauth2/token',
querystring.stringify({
grant_type: 'authorization_code',
code: payload.code,
redirect_uri: tokenUri,
client_id: client_id
}),
{
headers:{
Authorization: 'Basic '+ cred,
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(response => {
return{
res: response,
success: true
}
})
.catch(err => {
return{
res: err,
success: false
}
})
}
I am getting 401 {"error":"invalid_client"} code for this post request from the server. What am I missing?
N.B: I have tried without client secret, client id, not encoding redirect URL. No luck so far>
I would really appreciate your effort if you show me some light. Thanks for your time.
====Edited====
The error from the console at the browser is attached
I solved the problem. I had to put the client secret at the body of the post request. The following code resolves my problem.
var querystring = require('querystring');
export const logInGlobus = (payload) => {
let client_id = 'app client id'
let client_secret = 'client secret generated for authentication'
return axios.post('https://auth.globus.org/v2/oauth2/token',
querystring.stringify({
grant_type: 'authorization_code',
code: payload.code,
redirect_uri: payload.redirect_uri,
client_id: client_id,
client_secret: client_secret
}),
{
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(response => {
return{
res: response,
success: true
}
})
.catch(err => {
return{
res: err,
success: false
}
})
}
I saw many tutorials on jwt authentication but every video maker uses Postman to show what's happening and they pass on the header in the headers section while requesting a URL in Postman. I tried to do it with JavaScript but I was not able to do it.
I want to do jwt authentication but after token generation, I send it to client side to use it for further requests but I failed to do so after trying it a few times. I also tried to set req.headers in server side but it didn't do what I wanted to..
I want to set request headers for authentication of the form "Bearer {token}" for every request after token generation. How to do it with JS??
What I am most concerned about is that every tutorial does it with postman but they didn't show how they implemented it in their own app. I hope my question is clear.
You can easily add header on your http request like that
it has been solved here Node.JS: How to send headers with form data using request module
In vanilla nodejs:
const uri = "http://example.com";
const options = {
headers: {
"Authorization": "Bearer ...."
}
}
// require http/https lib
let req = require("http").request(uri, options, (res) => {
const chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.once("end", () => {
// concat body chunks
let body = Buffer.concat(chunks);
console.log(body.toString());
});
});
req.on("error", (err) => {
console.log(err);
});
req.end();
https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_options_callback
Something like that:
$.ajax({
url: url,
beforeSend: function(xhr) {
xhr.setRequestHeader("custom_header", "value");
},
success: function(data) {
}
});
First install jwt and express framework using npm then make a middleware file which will check if the tokek is set or not.
Middleware.js :
let jwt = require('jsonwebtoken');
const config = require('./config.js');
let checkToken = (req, res, next) => {
let token = req.headers['authorization']; // Express headers are auto converted to lowercase
if (token) {
if (token.startsWith('Bearer ')) { // Checks if it contains Bearer
// Remove Bearer from string
token = token.slice(7, token.length); //Separate Bearer and get token
}
jwt.verify(token, config.secret, (err, decoded) => { //Inser the token and verify it.
if (err) {
return res.json({
status: false,
message: 'Token is not valid'
});
} else {
req.decoded = decoded;
next();
}
});
} else {
return res.json({
status: false,
message: 'Access denied! No token provided.'
});
}
};
Next, create a config file which will contain the secrets.
Config js:
module.exports = {
secret: 'worldisfullofdevelopers'
};
Finally, create a token route which will create your token and after that the rest of the calls will be authenticated for that token.
Index.js :
const middleware = require('./middleware');
const jwt = require("jsonwebtoken");
const config = require('./config.js');
//Call token Route
app.use('/token', (req, res, next) => {
//Generate Token
let token = jwt.sign({ username: "test" },
config.secret,
{
expiresIn: '1h' // expires in 1 hours
}
);
//Send Token
res.json({
success: true,
message: 'Authentication successful!',
token: token
});
});
//Add Authentication to all routes
app.use(middleware.checkToken);
//===> All the routes after middleware will be checked for token
app.use('/getUser', (req, res, next) => {;
console.log('do something')
});
If I understand correctly, you want to set the HTTP header on the client, in order to pass an authentication token to the server. I would recommend that you use a library like **axios*.
Using axios, once you receive the toke, set the header for every outgoing communication with the following line of code:
axios.defaults.headers.common['Authorization'] = "Bearer " + token;
This will set the authentication http header to the form you need.