Using Axios to send a token to the backend - javascript

I am new to this
I am writing a Vue app that connects to a Wordpress backend and I need to log in. I am using a plugin called Simple JWT-Login and I am able to send the email and password to the back end and i get the JWT back. But trying to log in and sending the jWT back to the back end gets me an error Bad Request.
Here is the function that is supposed to handle the login
async login(){
try{
const response = await axios.post('/?rest_route=/simple-jwt-login/v1/auth&email=email&password=password',
{
email: this.email,
password: this.password,
}
);
const token = response.data.data.jwt
localStorage.setItem('token', token)
console.log(token)
const login = await axios.get('/?rest_route=/simple-jwt-login/v1/autologin&JWT=token')
console.log(login)
// this.$router.push("/");
} catch(err){
console.log(err)
// if(err.response.status === 400){
// this.error = "Wrong credentials! Please make sure"
// }
} finally{
}
}

The issue was a setting in the plugin that the docs does not explain to you and unless you are an expert the only way to find out is by trial and error.
The setting under general for SESSION must be On

Looking at the docs for Login User, it seems you just need to pass the previous token value as the JWT query parameter.
I've always found it best to use the params option in Axios for query params
const login = await axios.get("/", {
params: {
rest_route: "/simple-jwt-login/v1/autologin",
JWT: token,
}
})
Your issue was that in this string...
'/?rest_route=/simple-jwt-login/v1/autologin&JWT=token'
token was not interpolated; you were literally sending "token".
You should do the same with your first request. The email and password should not be in the query string for this one.
axios.post("/", {
email: this.email,
password: this.password,
}, {
params: {
rest_route: "/simple-jwt-login/v1/auth",
}
})

Related

How can I access the token which is saved in the header using angular

I am sending the 'auth-token' which is generated with JWT to the frontend which is built in angular. The backend is built in nodejs. when I try to access the auth-token variable from the frontend it is saying syntax error. How can access this header token in my angular code?
Frontend Request in the component
onSubmit(){
if(!this.signinForm.valid){
return;
}
const userDetails: SigninAccount = {
email: this.signinForm.controls.email.value,
password: this.signinForm.controls.password.value
}
this.loginservice.loginUser(userDetails).subscribe(
data => { console.log(data);
this.router.navigate(['/'])
},
error => { console.log(error.error)}
)
}
Frontend service and the headeroptions
const loginhttpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
}
loginUser(user: SigninAccount): Observable<SigninAccount> {
const makeReqURL = `${this.apiURL}/login`;
const loginUser = this.http.post<SignupAccount>(makeReqURL, user, httpOptions)
return loginUser;
}
Backend response
const userToken = jwt.sign({ _id: user._id }, process.env.TOKEN);
res.header('auth-token', userToken).send(userToken)
Screenshot of the image in the browser and the syntax error message which is given because of the console.log(data).
the "text" has the JWT token too which is the same as the "auth-token" but don't know how to access it in the code and I don't know what is the syntax error either.
Please help. Thank you very much in advance.
There must be some syntax issue in backend code that's why you getting the error. Use some linter like EsLint which can help detecting the error.
How to access the authToken?
Here is your new backend code.
don't set token in header instead send as a json.
const userToken = jwt.sign({ _id: user._id }, process.env.TOKEN);
res.json({token: userToken});
The frontend code is correct you gonna get your token in console.
this.loginservice.loginUser(userDetails).subscribe(
data => {
console.log(data);
const token = data.token;
//Save to localStorage
localStorage.setItem('token',token);
this.router.navigate(['/']);
},
error => { console.log(error.error)}

Javascript script-src makes page load twice?

I'm working on a "forgot password" link that runs a function that creates a new JWT, then redirects to reset-password.html and works properly.
However this page needs a <script src="updatePassword.js"></script> for the user to save the new password.
The problem is: the simple presence of the script src... on the html page makes the resetPassword function to run twice and mess up the token creation.
Console logging shows a proper token on the first run and then: token: updatePassword.js followed by jwt malformed. If I remove the script from the html page this doesnt happen. How do I fix this?
Here's the code for the forgot password link:
module.exports.resetPassword = asyncHandler(async(req, res) => {
const {id, token } = req.params
const user = await User.findById(id)
console.log('token:', token)
//check user
if(id != user._id) {
res.send('Invalid ID')
return
}
const secret = process.env.JWT_SECRET + user.password
try {
const payload = jwt.verify(token, secret)
console.log('works')
res.render('reset-password.html', {email: user.email, userName: user.userName})
} catch (error) {
console.log('doesnt work')
console.log(error.message)
res.send(error.message)
}
})

How to validate firebase user current password

I am creating a form, in react-redux to change user password. I am wondering how can I validate the user current password in order to change to new one.
in my form I have 2 fields: old password, new password.
this is my action:
const { currentUser } = auth
currentUser.updatePassword(newPassword)
.then(
success => {
dispatch({
type: CHANGE_USER_PASSWORD_SUCCESS,
payload: currentUser
})
},
error => {
dispatch({
type: CHANGE_USER_PASSWORD_FAIL,
error: error.message
})
}
)
I am wondering, how to validate the old password in firebase? Should I use signInWithEmailAndPassword()? Or, is there a function to validate the current password without calling the signIn again, since my user is already logged in?
Thanks
Well, I believe you want the user to enter the old password just to verify whether it's the actual owner of the account or not.
Firebase handles this situation very well, you just need to call the updatePassword method on the user object and pass in the new password.
const changePassword = async newPassword => {
const user = firebase.auth().currentUser;
try {
await user.updatePassword(newPassword)
console.log('Password Updated!')
} catch (err) {
console.log(err)
}
}
If it's been quite a while that the user last logged in then firebase will return back an error -
"This operation is sensitive and requires recent authentication. Log in before retrying this request."
Thus, you don't really need to check the old password as firebase does it for you.
But if you just want to do it in one go, without having the user to log in again.
There's a way for that as well.
There is a method on user object reauthenticateAndRetrieveDataWithCredential you just need to pass in a cred object(email and password) and it refreshes the auth token.
const reauthenticate = currentPassword => {
const user = firebase.auth().currentUser;
const cred = firebase.auth.EmailAuthProvider.credential(
user.email, currentPassword);
return user.reauthenticateAndRetrieveDataWithCredential(cred);
}
In your particular case, you can have something like this
const changePassword = async (oldPassword, newPassword) => {
const user = firebase.auth().currentUser
try {
// reauthenticating
await this.reauthenticate(oldPassword)
// updating password
await user.updatePassword(newPassword)
} catch(err){
console.log(err)
}
}
Learn more about firebase reauth - https://firebase.google.com/docs/auth/web/manage-users#re-authenticate_a_user
Hope it helps

Getting Correct Info in Console, But Angular 2 Login Not Working as Expected

I have a login in my Angular 2 app, and I have been converting it from using a fake backend (which works) to connect to our mongoDB-based API instead.
This is the login function I am using in the authentication service:
login(username: string, password: string) {
const u = encodeURIComponent(username);
const p = encodeURIComponent(password);
this._url = `https://api.somesite.com/v0/staff/login/${u}/${p}?apikey=somekey`;
console.log(this._url);
return this.http.post(this._url, JSON.stringify({ username: username, password: password }))
.map((response: Response) => {
// login successful if there's a jwt token in the response
const user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
In my login component I am subscribing like this:
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.router.navigate(['/']);
console.log('User logged in as: ' + this.model.username);
},
error => {
this.alertService.error(error);
this.loading = false;
});
this.authenticationService.username = this.model.username;
}
When I try this, and log to the console "this_url", I get what I would expect. For instance, if the user typed in "billsmith" for username, and "parisnow" for password, I see this in the console for "this_url":
https://api.somesite.com/v0/staff/login/billsmith/parisnow?apikey=somekey
Furthermore, I can type that url directly into the browser address window and see data (when the username and password correctly correspond to actual records in our database). So it's accessing the correct info in that sense.
But in the console I get a "404" error for that generated url. It also doesn't "do anything". In other words, it doesn't correctly redirect to the main component as it did with the fakeBackend-enabled login. And the only thing that's different now is the url that I am calling (because I'm connecting to our actual API now, as opposed to a fake backend provider).
FYI, the url when using the fake backend looked like this:
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password}))
What am I missing here?
By the way, this is how things look on the server side re: our mongoDB:
exports.byLogin = function(req, res, next) {
let ioOnly = false, username, password;
if (_.isUndefined(req.params)){
ioOnly=true;
username = req.username;
password = req.password;
}
else {
username = req.params.username;
password = req.params.password;
}
staff.findOne({username: username, password: password}, function(err, doc) {
if (err) { if (!ioOnly) { return next(err) } else { return res(err)}}
else if(doc) ((!ioOnly) ? res.send(doc) : res(doc));
else ((!ioOnly) ? res.sendStatus(204) : res(doc));
});
};

Switching from MockBackend to Actual API in Angular 2 App

I am working on login functionality for my Angular 2 app. I've got it working with a MockMackend and fakeBackendProvider. Now I'm in the process of connecting to our actual API. I am running into an issue with that, though.
First off, let me show what I have that IS working by using the MockBackend and fakeBackendProvider.
This is my authentication service function:
login(username: string, password: string) {
return this.http.post('/api/authenticate', JSON.stringify({ username: username, password: password}))
.map((response: Response) => {
// login successful if there's a jwt token in the response
const user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
Again, then, in my login component, I am calling that function like this:
login() {
this.loading = true;
this.authenticationService.login(this.model.username, this.model.password)
.subscribe(
data => {
this.router.navigate(['/']);
console.log('User logged in as: ' + this.model.username);
},
error => {
this.alertService.error(error);
this.loading = false;
});
this.authenticationService.username = this.model.username;
}
Again, all of the above IS working.
So, I assume all I should need to do is replace '/api/authenticate' in the login function, with our actual api + api string. So this is what I've been trying:
login(username: string, password: string) {
return this.http.post('https://api.somesite.com&apikey=843c-4932-ckd33', JSON.stringify({ username: username, password: password}))
.map((response: Response) => {
// login successful if there's a jwt token in the response
const user = response.json();
if (user && user.token) {
// store user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
});
}
This isn't working. In the console I get a "ERR_NAME_NOT_RESOLVED" error. Any ideas here?

Categories

Resources