cypress retrieve JWToken and set as header for further requests - node.js

When trying to test a express webapplication i build the test should first authenticate to retrieve a JWT token, the token retrieving works but the method to set the header for further requests doesn't work.
This code creates the method to run when authentication is needed,
Cypress.Commands.add("userRequest", function(requestObj) {
// Make a login request, returning a JWT token
cy.request({
method: 'POST',
url: '/credentials',
body: {
"name": "test_user",
"password": "test123_"
}
}).then(function(response) {
requestObj.headers = requestObj.headers || {};
requestObj.headers.Authentication = response.body.token;
return cy.request(requestObj);
});
This is the code that runs
it('retrieves one user', function () {
cy.userRequest(cy.request({
url: '/users/1'
})).then(function (response) {
expect(response.body.name).to.equal("admin");
});
});
BUT when the test runs the console tells me
CypressError: cy.request() failed on:
http://localhost:3000/users/1
The response we received from your web server was:
401: Unauthorized
This was considered a failure because the status code was not '2xx' or '3xx'.
Can anyone help me?
thanks in advance!

As I said in my comment that cypress works on async programming, so try with in support/command.js
Cypress.Commands.add('userRequest', (email, password) => {
Cypress.log({
name: 'loginViaAuth0',
});
const options = {
method: 'POST',
url: '/credentials',
"body":'userName='+email+'&Password='+password+'
};
cy.request(options)
});
Then in your code
cy.userRequest(userName,password)
.its('body').then((response)=>{
// Do your stuffs
})

Related

'Full authentication is required to access this resource' Clockify API with Node JS

I am unable to add new clients using the Clockify API in Node js. The following axios post request returns the error message: 'Full authentication is required to access this resource'. However, I am able to get a list of clients using the axios.get() method with the same API key, so I'm not sure why the post request says I'm not authenticated. Please let me know what I'm missing
async function addNewClient(clientName) {
return response = await axios.post(`${url}/workspaces/${workspaceId}/clients`, {
data: {
'name': clientName
},
headers: {
'X-Api-Key': CLOCKIFY_API_KEY,
'Content-Type': 'application/json',
},
}).catch(function (error) {
console.log(error.response.data.message);
return
});
}
I had the same issue. Regenerating API_KEY solved it.

Nodejs - Axios not using Cookie for post request

I'm struggling with AXIOS: it seems that my post request is not using my Cookie.
First of all, I'm creating an Axios Instance as following:
const api = axios.create({
baseURL: 'http://mylocalserver:myport/api/',
header: {
'Content-type' : 'application/json',
},
withCredentials: true,
responseType: 'json'
});
The API I'm trying to interact with is requiring a password, thus I'm defining a variable containing my password:
const password = 'mybeautifulpassword';
First, I need to post a request to create a session, and get the cookie:
const createSession = async() => {
const response = await api.post('session', { password: password});
return response.headers['set-cookie'];
}
Now, by using the returned cookie (stored in cookieAuth variable), I can interact with the API.
I know there is an endpoint allowing me to retrieve informations:
const readInfo = async(cookieAuth) => {
return await api.get('endpoint/a', {
headers: {
Cookie: cookieAuth,
}
})
}
This is working properly.
It's another story when I want to launch a post request.
const createInfo = async(cookieAuth, infoName) => {
try {
const data = JSON.stringify({
name: infoName
})
return await api.post('endpoint/a', {
headers: {
Cookie: cookieAuth,
},
data: data,
})
} catch (error) {
console.log(error);
}
};
When I launch the createInfo method, I got a 401 status (Unauthorized). It looks like Axios is not using my cookieAuth for the post request...
If I'm using Postman to make the same request, it works...
What am I doing wrong in this code? Thanks a lot for your help
I finally found my mistake.
As written in the Axios Doc ( https://axios-http.com/docs/instance )
The specified config will be merged with the instance config.
after creating the instance, I must follow the following structure to perform a post requests:
axios#post(url[, data[, config]])
My requests is working now :
await api.post('endpoint/a', {data: data}, {
headers: {
'Cookie': cookiesAuth
}
});

Getting 400 Bad Request When POSTing to Get Transaction Token

I'm trying to integrate our website with Converge API with Hosted Payments Page. Here is the link to their documentation https://developer.elavon.com/#/api/eb6e9106-0172-4305-bc5a-b3ebe832f823.rcosoomi/versions/5180a9f2-741b-439c-bced-5c84a822f39b.rcosoomi/documents?converge-integration-guide/book/integration_methods/../../book/integration_methods/hosted_payments.html
I'm having troubles getting past the first step which is requesting a transaction token from their API endpoint. I'm sending a POST request from my server using axios with the correct parameters and URL, but when I try and POST i get 400 Bad Request. When I make the same request in POSTMAN I get a 200 response with the transaction token. I talked to their developers and they said that everything I was doing was correct and that nothing seemed odd within my code, so even they were stumped as to why I couldn't make a POST request to their endpoint. Obviously there is something within my code that their API is not liking, or else I wouldn't be here trying to find answers for this.
Here is how I'm making the POST request:
app.get('/converge_token_req', (request, response) => {
let params = {
ssl_merchant_id: '*****',
ssl_user_id: '*****',
ssl_pin: '*****',
ssl_transaction_type: 'ccsale',
ssl_amount: '1.00'
}
axios.post('https://api.demo.convergepay.com/hosted-payments/transaction_token', params, {
headers: { 'Content_Type' : 'application/x-www-form-urlencoded' }
}).then((res) => {
response.send(res.data)
}).catch((error) => {
console.log('there was an error getting transaction token')
response.send(error.message)
})
})
Here are the Request Headers:
I'm honestly out of ideas to try. The developers say that everything looks just fine yet I'm unable to make a successful request to their API. If anyone has any thoughts on this that would be great. Thanks!
This code below worked for me:
app.get('/converge_token_req', (request, response) => {
let params = {
ssl_merchant_id: '*****',
ssl_user_id: '*****',
ssl_pin: '*****',
ssl_transaction_type: 'ccsale',
ssl_amount: '1.00'
}
axios({
method: 'post',
url: 'https://api.demo.convergepay.com/hosted-payments/transaction_token',
params: params
}).then((res) => { response.send(res.data)
}).catch((error) => {
console.log('there was an error getting transaction token: ',
error)
})
})
I've since found out the solution to my problem. The issue here is that converge expects a x-www-form-urlencoded string that needs to be Stringified before submitting the request. I found a library that works well for this called qs and I used it like so:
let params = qs.stringify({ // need this if content_type is application/x-www-form-urlencoded
ssl_merchant_id: env.CONVERGE.MERCHANT_ID,
ssl_user_id: env.CONVERGE.USER_ID,
ssl_pin: env.CONVERGE.PIN,
ssl_transaction_type: request.query.type,
ssl_amount: request.query.amount,
ssl_email: request.query.email,
ssl_company: request.query.company,
ssl_avs_address: request.query.address,
ssl_avs_zip: request.query.zip,
ssl_description: request.query.desc,
})
axios.post('https://api.convergepay.com/hosted-payments/transaction_token', params, {
headers: {
'Content_Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).then((res) => {
response.send(res.data)
}).catch((error) => {
console.log('there was an error getting transaction token')
response.send(error.message)
})
I think you could also get away with just using JSON.stringify() but this way worked for me.

Spotify API Authorization Grant Flow status 415

I am trying to build a web app that integrates with the spotify API. For this, I am using the Authorization grant flow.
I managed to get an authorization code, but on the back end when I am testing the endpoint that should exchange the auth code with an access token, I keep getting a 415 response status.
Here is the service that the endpoint is using:
export async function getAccessAndRefresh(code: string): Promise<any> {
return axios.post(ACCESS_URL, {
data: {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": REDIRECT_URI
},
headers: {
"Authorization": " Basic " + Buffer.from(CLIENT_ID + ":" + CLIENT_SECRET).toString("base64"),
"Content-Type": "application/x-www-form-urlencoded",
},
method: "POST",
json:true
})
}
Also, I wrote this unit test in order to test the service(I got the 415 while running this unit test):
describe("Request tests", () => {
let server: Server;
function initServer() {
server = createServer(App);
server.listen(5000);
}
function destroyServer() {
server.close();
}
test("Test refresh and access token returned by spotify api", () => {
return getAccessAndRefresh(AUTH_CODE).then((value)=>{
expect(value).toHaveProperty("access_token");
})
})
beforeAll(() => {
initServer();
});
afterAll(()=>{
destroyServer();
})
})
In the test, AUTH_CODE is a code that I obtained manually in a browser by accessing the https://accounts.spotify.com/authorize endpoint with my API Key.
Can anyone help me figure this one out please? Thanks!
In the Spotify Dashboard you might need to set the Redirect URI to the URL you're using in your code, these need to match if getting the following error:
{ "error": "invalid_grant", "error_description": "Invalid redirect URI" }
That's all you need to do, just go to the Dashboard where you get the Client ID and Client Secret and then go to the Edit Settings and you'll see the option to set the Redirect URI

Node/react best practice: How do I keep track on the current client/user in OAuth2 flow?

I'm a beginner with Node and React, and web programming in general. I want to import user credentials from LinkedIn's API and for that I need to authenticate using OAuth2.
My approach so far is to make an API-call from the client side to the LinkedIn oauth API with the relevant parameters, including a redirect URI which leads to an API endpoint on my node server. When the user has been redirected and approved LinkedIn's authentication dialog box, they will be redirected to the node server with an access token.
My question is as follows: I now want to update the user in my database with their corresponding access token, but how do I know which user to update when I can't get any information about the client in my function that handles the last redirect and fetches the access token?
Here's my node function that handles the redirect from LinkedIn:
router.get('/redirect', (req, res) => {
// Handle cancel by user
if(req.query.error){
console.log(req.query.error_description)
return
}
// Extract variables
const code = req.query.code
const state = req.query.state
// Check that state matches
if (state !== testState) {
console.log("State doesnt match")
return
}
// Exchange Authorization Code for an Access Token
var options = {
method: 'POST',
url: 'https://www.linkedin.com/oauth/v2/accessToken',
form: {
client_id: 'theClientID',
client_secret: 'theClienSecret',
grant_type: 'authorization_code',
code: code,
redirect_uri: 'http://localhost:3000/api/linkedin/redirect'
},
headers:
{ 'cache-control': 'no-cache',
"content-type": "application/json",
'user-agent': 'node.js' },
json: true };
// make the actual request
request(options, (error, response, body) => {
if (error) {
res.status(500).json({
message: error
})
return
}
// Extract access token
const token = body.access_token;
// Here I want to save access token to DB with the corresponding
// user, but I don't know which user to update
})
// Redirect user to profile
res.writeHead(301, {
Location: 'http://localhost:3000/profile'
})
res.end()
})
I had a really hard time formulating this question but I hope that my message gets through.

Resources