Cypress: Where does the authentication token go for an API request? - api

I am trying to request data through an API that requires authentification. I have the token and I know how to implement it using a manual tool such as postman...
How do I format the authentication using Cypress?
it('GET - read', () => {
cy.request({
method: 'GET',
url: 'https://mailtrap.io/api/v1/inboxes/123/messages?page=1&last_id=&useremail',
headers: {
Key: 'Api-Token',
Value: '1234'
}
})
})
})
Response:
The response we got was:
Status: 401 - Unauthorized

As per the Mailtrap documentation, sending an header Api-Token: {api_token} should send authenticated requests. You can write:
cy.request({
method: 'GET',
url: 'https://mailtrap.io/api/v1/inboxes/123/messages?page=1&last_id=&useremail',
headers: {
'Api-Token': 'Your Token value' //Replace with real token
},
failOnStatusCode: false
}).then((res) => {
expect(res.status).to.equal(200) //Replace with releveant 2xx response code
})

Related

Call token generation api in cypress framework

While calling the same token generation api from postman then i am getting a response
but same if i am calling through cypress i am getting byte array as response as shared in attached image.
Source code is of Cypress:-
const reqForm = new FormData();
reqForm.append('username', 'User***');
reqForm.append('password', "PWD#123#");
cy.request({
url: 'https://test.com/token-oauth',
method: 'POST',
body: reqForm,
headers: {
'accepts': "multipart/form-data",
'authorization': 'Basic MjZiMDEyZWMtY2YxYi00OTkwLWFkM2MtMzRlNWQ5ODMwYTE5Og=='
}
}).then((res) => {
debugger;
console.log(res)
});
Expected Output:-
Access token and token type
But it's giving some byte code into response
How can i call this token generation api in cypress and how i will get access token?

How to script for postman like API in cypress

I am new in Cypress,
I wanted to create my first code for API in cypress.
Here is the details
POST
https://www.mywebsite.com/myproject/get-customer-login-url
HEADER
------
KEY: token
VALUE: HKt7854UHTFGR78#78
DESCRIPTION:
KEY: Content-Type
VALUE: application/json
DESCRIPTION:
BODY
-----
RAW:
{
"customerid": "54607"
}
Using above parameters, I got below result and status in Postman.
RESULT:
"{\"url\":\"default.aspx?rootid=843&companyId=54607&eccuserid=0&isloginspecialrole=False&userid=e91zNO%2bBBCI%3d&t=view\",\"code\":\"1\"}"
STATUS"
200 OK
I need to made script for cypress using these POST URL and parameters/key.
And want response like
https://www.mywebsite.com/myproject/default.aspx?rootid=843&companyId=54607&eccuserid=0&isloginspecialrole=False&userid=e91zNO%2bBBCI%3d&t=view
can anyone help me out to my cypress script?.
Here's an example, you might have to adjust it. This example just validates that status of the response is 200 but you can validate response contents as well. Refer cypress docs for details:
describe('Test the api', function() {
it ('status should be 200', () => {
cy.request({
method: 'POST',
url: 'your-url',
followRedirect: false,
headers: {
'token': 'HKt7854UHTFGR78#78',
'Content-Type': 'application/json',
},
body: {"customerid": "54607"},
})
.then((response) => {
expect(response.status).to.equal(200)
})
})
})

how to use axios to send data to line notify

I tried to send data to line notify server by axios and it fail
I have tried 2 version of code. as shown below
version 1 :
axios({
method: "post",
url: "https://notify-api.line.me/api/notify",
data: 'message="from vue"',
config: {
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "multipart/form-data"
}
},
Authorization: "Bearer [my token]"
})
.then(function(response) {
console.log(response);
})
.catch(function(response) {
console.log(response);
});
response is
XMLHttpRequest cannot load https://notify-api.line.me/api/notify due to access control checks.
Error: Network Error
and version 2 is :
axios
.post("https://notify-api.line.me/api/notify", "message=from vue", {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Bearer [my token]"
}
})
.then(response => {
console.log(response);
});
response is
Preflight response is not successful
XMLHttpRequest cannot load https://notify-api.line.me/api/notify due to access control checks.
Error: Network Error
What wrong with is
but I have tried in postman it work fine
Oh I am too familiar with this. Heres an explanation on stackoverflow as to why your request works with postman but not in browser. Long story short browsers send a preflight options check that will ask the server if the action you're about to perform is allowed. Postman does not. Usually the "Access-Control-Allow-Origin": "*" header is sent by the server to the browser not the other way around.
Inside the docs for LINE Notify you can find:
POST https://notify-api.line.me/api/notify
Sends notifications to users or groups that are related to an access token.
If this API receives a status code 401 when called, the access token will be deactivated on LINE Notify (disabled by the user in most cases). Connected services will also delete the connection information.
Requests use POST method with application/x-www-form-urlencoded (Identical to the default HTML form transfer type).
My guess is that your access_token might have been deactivated. Try requiring a new access token and doing the request again.
I think it is impossible to connect directly to the external url for the axios cuz ajax is basically for the inner data network. But you might have a controller if you do a web project, so you can just use your controller language to make a connection with line notify. In my case, I made a rails project and used axios in the vue.js, so I made a link like this.
View(axios) => Controller(Ruby) => LineAPI
me currently work on this too.
I did my app with node js.
My way below is for your reference, it works well.
const axios = require('axios');
const querystring = require('querystring');
axios({
method: 'post',
url: 'https://notify-api.line.me/api/notify',
headers: {
'Authorization': 'Bearer ' + 'YOUR_ACCESS_TOKEN',
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*'
},
data: querystring.stringify({
message: 'something you would like to push',
})
})
.then( function(res) {
console.log(res.data);
})
.catch( function(err) {
console.error(err);
});
I try it works.
async function test() {
const result = await axios({
method: "post",
url: "https://notify-api.line.me/api/notify",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer [token]",
},
data: 'message=你好哇'
})
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
});
}
test();
I think you can check response on chrome debugger network.
or provide more information, thx.

Axios: Network Error and not sending request

I am trying to send a get request with auth headers to api from Vue using axios.
When I try to send it, it gives me a Network Error with no info about it. I have also check network tab and the request is not sending at all.
Before I checked the url using postman and https://www.hurl.it/ and it worked as expected.
Also, I have sent a request to this api using axios to get a token.
Thank you.
const token = "token";
let options = {
method: 'GET',
url: 'http://smev.test-it-studio.ru/api/analytics/PortfolioStructure',
headers: {
'Authorization': `Bearer ${token}`
},
};
axios(options).then((data) => {
console.log(data);
}).catch((error) => {
console.log(error.config);
});
EDIT: Here is the error I get:
Error
columnNumber: 15
config: {…}
adapter: function xhrAdapter()
baseURL: "http://smev.test-it-studio.ru"
data: undefined
headers: Object { Accept: "application/json", Authorization: "Bearer token"}
maxContentLength: -1
method: "GET"
timeout: 0
transformRequest: Object [ transformRequest() ]
transformResponse: Object [ transformResponse() ]
url: "http://smev.test-it-studio.ru/api/analytics/PortfolioStructure"
validateStatus: function validateStatus()
xsrfCookieName: "XSRF-TOKEN"
xsrfHeaderName: "X-XSRF-TOKEN"
__proto__: Object { … }
fileName: "http://uralsib-lk.dev/dist/build.js"
lineNumber: 19074
message: "Network Error"
response: undefined
stack: "createError#http://uralsib-lk.dev/dist/build.js:19074:15\nhandleError#http://uralsib-lk.dev/dist/build.js:18962:14\n"
__proto__: Object { … }
build.js:18589:24
With the help from Soleno, I found out that it was AdBlock what was blocking the request.
I had this problem in rails. It was cors as mentioned above.
The rails server won't show logs so it looks like axios isn't sending the request at all.
Thankfully it's an easy fix.
For rails add this to your gemfile:
gem 'rack-cors'
Then add this to config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0,Rack::Cors do
allow do
origins 'localhost:8080'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
Note: Update orgins to the origin of your front end app.

fetch: Getting cookies from fetch response

I'm trying to implement client login using fetch on react.
I'm using passport for authentication. The reason I'm using fetch and not regular form.submit(), is because I want to be able to recieve error messages from my express server, like: "username or password is wrong".
I know that passport can send back messages using flash messages, but flash requires sessions and I would like to avoid them.
This is my code:
fetch('/login/local', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
}),
}).then(res => {
console.log(res.headers.get('set-cookie')); // undefined
console.log(document.cookie); // nope
return res.json();
}).then(json => {
if (json.success) {
this.setState({ error: '' });
this.context.router.push(json.redirect);
}
else {
this.setState({ error: json.error });
}
});
The server sends the cookies just fine, as you can see on chrome's dev tools:
But chrome doesn't set the cookies, in Application -> Cookies -> localhost:8080: "The site has no cookies".
Any idea how to make it work?
The problem turned out to be with the fetch option credentials: same-origin/include not being set.
As the fetch documentation mentions this option to be required for sending cookies on the request, it failed to mention this when reading a cookie.
So I just changed my code to be like this:
fetch('/login/local', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
credentials: 'same-origin',
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
}),
}).then(res => {
return res.json();
}).then(json => {
if (json.success) {
this.setState({ error: '' });
this.context.router.push(json.redirect);
}
else {
this.setState({ error: json.error });
}
});
From Differences from jQuery section of the Fetch API on Mozilla:
fetch() won't receive cross-site cookies. You can’t establish a cross
site session using fetch(). Set-Cookie headers from other sites are
silently ignored.
fetch() won’t send cookies, unless you set the
credentials init option. Since Aug 25, 2017: The spec changed the
default credentials policy to same-origin. Firefox changed since
61.0b13.)
I spent a long time but nothing worked for me.
after trying several solutions online this one worked for me.
Hopefully it will work for you too.
{
method: "POST",
headers: {
"content-type": "API-Key",
},
credentials: "include",
}
I had to include credentials: 'include' in the fetch options:
fetch('...', {
...
credentials: 'include', // Need to add this header.
});