how to pass token to browser url in vue js - vue.js

i've an app whcih sends email to users to reset their passwords
this is the link i send to the user email to be able to do password reset
http://localhost:8081/reset/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MmU2YWJmMmMzMzI0Mjk1NGQyNmVjZjIiLCJpYXQiOjE2NTk0ODkzODEsImV4cCI6MTY1OTQ5MDI4MX0.6omB-TkXXcwrjv0MaJQxltyERIoJZmkm8sY74AAqgxo
but each time i try to access the link i get
Cannot GET /reset/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
this is my route
{ name: "reset", path: "/reset/:token", component: Reset },
this is my script tag
<script>
import axios from "axios";
export default {
data: () => ({
valid: true,
password: "",
}),
mounted() {
console.log("the id is :" + this.$route.params.token);
},
methods: {
async handleSubmit() {
const response = await axios
.post("http://localhost:5000/api/auth/reset-password", {
newPassword: this.password,
token: this.$route.params.token
})
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
});
},
}
};
</script>
please how can i go about these

Related

Is Auth.js compatible with Sveltekit SSR?

I am trying to create a Sveltekit app where users can log in. The login process is handled by a self-created API, so I would like to use the Auth.js Credentials Provider.
When I call the SignIn method as the FormAction in the +page.server.ts file, I get the error message 'window is not defined', which makes sense. Does this mean that Auth.js is not compatible with server-side rendering, or is there something else that I can adjust?
My Code:
//hooks.server.ts
SvelteKitAuth({
providers: [
// #ts-ignore
Credentials({
name: "credentials",
async authorize(credentials, req) {
// TODO: Call Api
const user = { id: "1", name: "J Smith", email: "jsmith#example.com" }
if (user) {
return user
} else {
return null
}
}
})
],
});
//+page.server.ts
export const actions = {
default: async ({ cookies, request }: { cookies: any, request: any }) => {
const data = await request.formData();
const credentials = {
username: data.get('username'),
password: data.get('password')
};
signIn('credentials', credentials)
.then(response => {
console.log('Success');
})
.catch(error => {
console.error('error', error);
});
}
};

How do I mock authenticate with Nuxt and Cypress?

How do I mock authenticate with Nuxt and Cypress?
I have a FastAPI backend that issues a JWT to a frontend NuxtJS application. I want to test the frontend using Cypress. I am battling to mock authenticate.
Here is a simple Cypress test:
// cypress/e2e/user_authentication_test.cy.js
describe("A User logging in", () => {
it.only("can login by supplying the correct credentials", () => {
cy.mockLogin().then(() => {
cy.visit(`${Cypress.env("BASE_URL")}/dashboard`)
.window()
.its("$nuxt.$auth")
.its("loggedIn")
.should("equal", true);
});
});
});
The test above fails at the should assertion, and the user is not redirected.
The mockLogin command is defined as:
// cypress/support/commands.js
Cypress.Commands.add(
'mockLogin',
(username = 'someone', password = 'my_secret_password_123') => {
cy.intercept('POST', 'http://localhost:5000/api/v1/auth/token', {
fixture: 'auth/valid_auth_token.json',
}).as('token_mock')
cy.visit(`${Cypress.env('BASE_URL')}/login`)
cy.get('#login-username').type(username)
cy.get('#login-password').type(`${password}{enter}`)
cy.wait('#token_mock')
}
)
Where valid_auth_token.json contains a JWT.
The actual login is done as follows:
<!-- components/auth/LoginForm.vue -->
<template>
<!-- Login form goes here -->
</template>
<script>
import jwt_decode from 'jwt-decode' // eslint-disable-line camelcase
export default {
name: 'LoginForm',
data() {
return {
username: '',
password: '',
}
},
methods: {
async login() {
const formData = new FormData()
formData.append('username', this.username)
formData.append('password', this.password)
try {
await this.$auth
.loginWith('cookie', {
data: formData,
})
.then((res) => {
const decode = jwt_decode(res.data.access_token) // eslint-disable-line camelcase
this.$auth.setUser(decode)
this.$router.push('/')
})
} catch (error) {
// error handling
}
},
},
}
</script>

Vue API data is gone on window refresh

When I login I am redirected to secret page which needs JWT authentication. Data is loaded on secret page. And when I refresh the window - data is lost. How can I fix it?
I use eventBus to send a JWT token to sibling template.
Login view method on submit:
submitSignin() {
console.log("submit!");
this.submitted = true;
this.$v.$touch();
if (this.$v.$invalid) {
return; // stop here if form is invalid
}
axios
.post("http://localhost:3000/auth/login", this.authData)
.then((res) => {
this.token = res.data.token;
this.authData.email = "";
this.authData.password = "";
this.$v.$reset();
this.successMsg = "You Sign in Successfully!";
this.$router.push({ path: "/auth/all-users" });
this.$nextTick(() => {
eventBus.$emit("sendtoken", this.token);
});
})
.catch((err) => {
console.log(err.response.data.message);
this.errorMsg = err.response.data.message;
});
},
SecretPage view:
<script>
export default {
name: "SecretPage",
data() {
return {
users: [],
};
},
methods: {
loadUsers() {
let self = this;
eventBus.$on("sendtoken", (token) => {
axios
.get("http://localhost:3000/auth/all-users", {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((response) => {
console.log(token);
console.log(response.data.users);
self.users = response.data.users;
})
.catch((err) => {
console.log(err);
});
});
},
},
mounted() {
this.loadUsers();
},
};
</script>
loaded users

How to save Simple JWT Token in local storage using vue.js, vuex and django rest framework?

I have a problem to save JWT Token in Local Storage (or cookie). Now, when I refresh my page, I need to login again. When I POST to /api-token with username and password in response I've got access token and refresh token, and now, don't now how to store them and where.
My loginForm.vue:
(<form...)
<script>
import axios from 'axios';
export default {
name: 'LoginForm',
data(){
return{
username: '',
password: '',
}
},
methods: {
login(){
this.$store.dispatch('userLogin', {
username: this.username,
password: this.password
})
.then(() => {
this.$router.push({ name: 'home'})
})
.catch(err => {
console.log(err)
})
}
}
}
</script>
and my store.js:
import Vue from 'vue'
import Vuex from 'vuex'
import { getAPI } from './api'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
accessToken: null,
refreshToken: null,
},
mutations: {
updateStorage (state, { access, refresh }) {
state.accessToken = access
state.refreshToken = refresh
},
destroyToken (state) {
state.accessToken = null
state.refreshToken = null
}
},
getters: {
loggedIn (state) {
return state.accessToken != null
}
},
actions: {
userLogin (context, usercredentials){
return new Promise((resolve, reject) => {
getAPI.post('/api-token/', {
username: usercredentials.username,
password: usercredentials.password
})
.then(response => {
context.commit('updateStorage', {access: response.data.access, refresh: response.data.refresh})
resolve()
})
})
},
userLogout (context) {
if (context.getters.loggedIn) {
context.commit('destroyToken')
}
}
}
})
I'm assuming I need to save them in local storage by store.js, after update and before destroy. Could you help me?
You need something like this:
You must save access token in default header's requests to auth user after every requests . also save token in localstorage:
axios.post('login', this.user)
.then(r=>
{
axios.defaults.headers.common['Authorization'] = 'Bearer ' + r.data.token;
localStorage.setItem( 'token', JSON.stringify(r.data.token) );
}
and add to default headers on refresh: (top of main.js file)
let token = JSON.parse( localStorage.getItem('token') );
if( token ){
window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
}
now you can send request from every component
in the login page in (script) tag add this code
axios.post('/api/v1/token/login/', this.form)
.then((r) => {
axios.defaults.headers.common['Authorization']='Bearer'+r.data.auth_token;
localStorage.setItem('token', JSON.stringify(r.data.auth_token));
})
and in the main.js add
let token = JSON.parse( localStorage.getItem('token') );
if( token ){
window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
}

Access Vue app (this) from non vue file

I'm new to vue (started using vue 2) I'm using Store (vuex) and I'm trying to acheive something.
basically I managed to install the vue-auth plugin : I have this.$auth that I can call from within .vue files.
Now using the store I wanna call the userLogin function by dispatching the call like this from a vue file :
<script>
export default {
computed: {
comparePasswords() {
return this.password === this.passwordConfirm
? true
: "Passwords don't match";
}
},
methods: {
userSignUp() {
if (this.comparePasswords !== true) {
return;
}
this.$store.dispatch("userSignUp", {
email: this.email,
password: this.password
});
}
},
data() {
return {
email: "",
password: "",
passwordConfirm: ""
};
}
};
</script>
in the store/index I'm trying to access the 'this.$auth' I do understand is some kind of context switching but I don't know how to access the vue app instance. :
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let app = this
export const store = new Vuex.Store({
state: {
appTitle: 'LiveScale Dashboard',
user: null,
error: null,
loading: false
},
mutations: {
setUser(state, payload) {
state.user = payload
},
setError(state, payload) {
state.error = payload
},
setLoading(state, payload) {
state.loading = payload
}
},
actions: {
userLogin({ commit }, payload) {
commit('setLoading', true)
var redirect = this.$auth.redirect(); // THIS IS WRONG.
this.$auth.login({ // THIS IS WRONG.
body: payload, // Vue-resource
data: payload, // Axios
rememberMe: this.data.rememberMe,
redirect: { name: redirect ? redirect.from.name : 'account' },
fetchUser: this.data.fetchUser
})
.then(() => {
commit('setUser', this.context)
commit('setLoading', false)
router.push('/home')
}, (res) => {
console.log('error ' + this.context);
commit('setError', res.data)
commit('setLoading', false)
});
},
userSignUp({ commit }, payload) {
// ...
}
},
getters: {}
})
Thanks for your help
try using Vue.$auth in index.js it should work
The idea (so far) is to pass the instance as an argument to the function as follows :
this.$store.dispatch("userSignUp", {
email: this.email,
password: this.password,
auth: this.$auth //added this line
});
and then in the store -> actions , payload.auth will contain my auth plugin :
userLogin({ commit }, payload) {
commit('setLoading', true)
var redirect = payload.auth.redirect();
payload.auth.login({
body: payload, // Vue-resource
data: payload, // Axios
rememberMe: this.data.rememberMe,
redirect: { name: redirect ? redirect.from.name : 'account' },
fetchUser: this.data.fetchUser
})
.then(() => {
commit('setUser', this.context)
commit('setLoading', false)
router.push('/home')
}, (res) => {
console.log('error ' + this.context);
commit('setError', res.data)
commit('setLoading', false)
});
},
I don't know if it's the best practice or not, but this is how I managed to do it. Please feel free to suggest anything.