Token not being persisted across Cypress tests - cookies

I have created a Cypress command to fetch me a JWT token from my GQL API. I then set the token as a cookie to use in my tests that require authentication.
Here is my login command:
export function login(username, password) {
const { apiUrl: url } = Cypress.env();
cy.request({
method: 'POST',
url,
body: {
operationName: 'signin',
headers: {
'content-type': 'application/json'
},
query:
`mutation signin($email: String!, $password: String!) {
signin(input: {email: $email, password: $password}) {
id
token
__typename
}
}`,
variables: { email: username, password: password }
}
})
.then(response => {
const { token } = response.body.data.signin;
cookie.set('token', token, { expires: 10000000 });
cy.wait(3000);
});
}
I can see when I run the login command the cookie is set but when my test tries to visit a page within my app the cookie disappears.
describe('Entity Page', () => {
before(() => {
const { username, password } = Cypress.env();
cy.login(username, password);
cy.addEntity(newEntityId, {});
cy.wait(3000);
cy.get('#entityId').then(entityId => {
cy.visit(`/entity/${entityId}`)
cy.wait(6000)
});
});
By the time I get to addEntity the cookie disappears and I am unauthenticated. Is there something I need to do to persist cookies? I tried Cypress.Cookies.preserveOnce but this had no effect
I also tried adding the below to my support/index.js but the cookie is still removed.
Cypress.Cookies.defaults({
preserve: 'token'
})

Try it with cy.setCookie(name, value) docs.
It has a couple of defaults that might help.
domain - defaults to window.location.hostname. The domain the cookie is visible to.
expiry - defaults to 20 years into the future. Specified as seconds since 1 January 1970 (10,000,000 is only 115 days).

Related

how to post using a token in rest-auth with axios? POST http://localhost:8000/rest-auth/password/change/ 401 (Unauthorized)

This is my code in vue,
resetPOST(){
var formData = new FormData();
formData.append('old_password', this.oldPassword);
formData.append('new_password1', this.password1);
formData.append('new_password2', this.password2);
axios.post('http://localhost:8000/rest-auth/password/change/',
{headers: { 'Authorization' : this.token },
data: {
old_password: this.oldPassword,
new_password1: this.password1,
new_password2: this.password2
}
})
},
where the variable 'token' has a value like that : bbf957d27925a860f8c678546cf0425dbf7ddf98
I do not understand why I get this error, if I try the back part I enter the old password, and the two new passwords and it works. For some reason I it isn't taking the token parameter.
Thanks in advance
You are missing the Bearer. Most of the frameworks by default require you to send the authorization in the following format: Bearer <token>.
If you changed the Bearer word to another you should use that one but if you left it to as default in django-rest-auth you have to use the following:
axios.post('http://localhost:8000/rest-auth/password/change/',
{headers: { 'Authorization' : `Bearer ${this.token}` },
data: {
old_password: this.oldPassword,
new_password1: this.password1,
new_password2: this.password2
}
})
I had a similar issue. I realized I was using the same axios instance for users logged into the app which meant using an authentication token. Of course if you are resetting your password you do not have authentication (and therefore a token). Use a different axios instance for your reset password like this:
const instance = axios.create({
baseURL: Store.state.endpoints.baseUrl,
headers: {
'Content-Type': 'application/json'
},
// xhrFields: {
// withCredentials: true
// },
xsrfCookieName:"csrftoken",
xsrfHeaderName:'X-CSRFToken'
})
return instance;
}
Notice there is no auth token and credential are commented out (could probably set to false too). This worked for me.

React put method not updating the user from Django

I have a Django as backend and updating the user from postman is working fine. But when I update it via React Frontend, it replies with a success message just as in Postman, but the data was not updated.
This is the update function to update:
const updateData = (e) => {
e.preventDefault();
const csrftoken = getCookie("csrf");
const cookies = new Cookies();
const url = "http://localhost:8000/usercontrol/update";
setIsLoading(true);
fetch(url, {
method: "PUT",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "Token " + cookies.get("token"),
"X-CSRFToken": csrftoken,
},
body: JSON.stringify({
email: userinfo.email,
username: userinfo.username,
first_name: userinfo.first_name,
last_name: userinfo.last_name,
}),
}).then((response) => console.log("THE RESPONSE: ", response.json()));
setIsLoading(false);
};
This is what it prints out in the console
Since I am partially following CodingWithMitch for Django user creation with rest framework is similar to his.
Furthermore, since there is no error outputting and is working fine in Postman, I have no idea what is wrong with it.

Chai-http doesn't seem to accept header always sends 401

I am trying to test my API routes that are protected by using jsonwebtoken.
I have tested my routes in postman and have gotten the correct results however running the same tests using mocha/chai/chai-http is not working.
Everytime I test a protected route I receive a 401 'unauthorized'
describe('user', () => {
let user, token
beforeEach(async () => {
await dropDb()
user = await new User({ email: 'testing#test.com', password: 'password' }).save()
const payload = { userid: user.id, role: user.roles.title, status: user.roles.status }
token = jwt.sign(payload, secret, { expiresIn: 3600 })
})
it('should return a list of users when logged in', async () => {
console.log(token)
const result = await chai.request(app)
.get('/api/user')
.set('Authorization', `Bearer ${token}`)
expect(result).to.have.status(200)
expect(result).to.be.json
})
})
My gut feeling was that there was somehow a race condition where the token being passed into the set wasn't finished being signed before the test ran. But inside the result it appears that my token has been set.
Additionally if I console.log the token after I can see that it matches the token created. Anybody run into a similar issue?

How do I open a session to keep login credentials through multiple http requests?

I'm trying to make Http requests using Angular 6. My login call works, but when I try to get use a different call, it tells me I'm not logged in. I think it's because the login isn't valid, but I'm not sure how I can keep it valid for subsequent calls. Here is the code appComponent file:
ngOnInit(): void {
this.data = this.login.getData();
this.farmAccessdata = this.getFarmAccess.farmAccess();
}
And here is the login service:
export class loginService {
base_URL = "..."
login = {
username: username,
password: password
}
constructor(private http: HttpClient) {
}
getData(){
return this.http.post(this.base_URL + "...", JSON.stringify(this.login))
.subscribe(data => {
console.log("We got ", data)
})
}
And the farmaccess service:
export class GetFarmAccessService {
data = {};
baseURL = "..."
constructor(private http: HttpClient) { }
farmAccess(){
return this.http.get(this.baseURL + "...")
.subscribe(data => {
console.log("We got ", data)
})
}
When I run the farmAccess service, it gives me an error saying I'm not logged in. The login framework on the server side is cookie based auth, powered by django user module. How can I fix this? Thanks.

ember-simple-auth session.isAuthenticated is false after refresh page

I'm using ember-simple-auth with Cookie based authentication.
When i login the {{session.isAuthenticated}} is true, but when i reload the page this is FALSE, but the localStore didn't change.
This is my custom.js authenticator:
import Base from 'ember-simple-auth/authenticators/base';
import config from '../config/environment';
export default Base.extend({
tokenEndpoint: config.apiUrl + '/user/signIn',
restore(data) {
console.log(data);
return RSVP.resolve(data);
},
authenticate(username, password) {
return Ember.$.ajax({
url: this.tokenEndpoint,
type: 'POST',
data: JSON.stringify({
username: username,
password: password,
}),
contentType: 'application/json;charset=utf-8',
dataType: 'json',
});
},
invalidate: function () {
return Ember.RSVP.resolve();
},
});
I'm using the {{session.isAuthenticated}} in the application.hbs. So i'm injecting the session in application controller:
session: Ember.inject.service('session')
You are making a mistake. 'restore ' method is called each time we refresh our page or open another tab. Note that RSVP.resolve removes your local storage so all is unauthenticated. We use this when we want to log user out and by that it means Ember Simple Auth will remove its local storage cookie and when this cookie is not found, it always send false for isAuthenticated method.
RSVP.resolve(data);
change your restore function from this
restore(data) {
console.log(data);
return RSVP.resolve(data);
},
to this
restore(data) {
return new Promise((resolve, reject) => {
resolve(data);
});
},
Note that this 'restore' method is like a method which we have to override based on our site rules e.g if you have token authentication we will write this method as
restore(data) {
return new Promise((resolve, reject) => {
if (!Ember.isEmpty(data.token)) {
console.log(data);
resolve(data);
} else {
reject();
}
});
},
Note that how we are handling things with our own logic to see if localstorage has token attribute present in it.
Similarly we can do by getting session cookie in this method and check if it exists. If it exists then we resolve else we reject. Note that these resolve and reject are promise methods etc.