I'm using laravel/passport for authentication in the backend and nuxtjs as frontend when I send a login request from nuxtjs, in case login success, I get back as a response a token and user informations and then the user will be redirected to /profile page, however in /profile page when I return this.$auth.loggedIn I'm getting false!
login.vue
<script>
export default {
data() {
return {
auth: false,
email: "",
password:""
}
},
methods: {
async login() {
try {
const data = { email: this.email, password: this.password }
await this.$auth.loginWith('local', { data:data})
.then(() => this.$router.push('/profile'))
} catch (e) {
}
}
}
}
</script>
profile.vue
<template>
<div class="mt-6">loggedInUser: {{ loggedInUser }}</div>
</template>
<script>
export default{
data() {
return {
loggedInUser:this.$auth.loggedIn
}
}
}
nuxt.config.js
auth: {
strategies: {
provider: 'laravel/passport',
local: {
user: {
property: false,
autoFetch: true
},
endpoints: {
login: { url: '/login', method: 'post', propertyName: 'token' },
user: { url: '/user', method: 'get' }
},
clientId: 'cleint_id',
clientSecret: 'client_secret'
}
}
},
modules: [
'#nuxtjs/axios',
// https://go.nuxtjs.dev/bootstrap
'bootstrap-vue/nuxt',
'#nuxtjs/auth',
],
axios: {
baseURL: "http://prostudent.test/api"
},
and how nuxt knows that a user is logged in since logging in happens in the backend?
this is directly after I click on login, I get redirected to profile and the response of login is as expected, message, token and infos, but in /profile page seems like I'm not logged in!
Even if you're not using Vuex with your own modules, nuxt/auth creates some state for you. Hence the the presence of this.$store.state.auth.loggedIn. Btw, did you tried appending $store on your profile.vue file? As shown in the documentation.
Like this
<template>
<div class="mt-6">
loggedInUser: {{ $store.state.auth.loggedIn }}
</div>
</template>
Also, open your vue devtools and check the vuex tab, you'll find some nice state there.
This also answers your other question
and how nuxt knows that a user is logged in since logging in happens in the backend?
Nuxt checks the response from the server and depending of it, sets the state of auth.loggedIn to either true or false.
Those are the 2 steps that you need to do to achieve a successful login (use loginWith + setUser).
const succesfulLogin = await this.$auth.loginWith('local', {
data: {
email: this.email,
password: this.password,
},
})
if (succesfulLogin) {
await this.$auth.setUser({
email: this.email,
password: this.password,
})
}
After those, loggedIn may pass to true.
Of course, the user info can be fetched from the backend too. Depends of your use case.
Use a computed property instead of data property :
<template>
<div class="mt-6">loggedInUser: {{ loggedInUser }}</div>
</template>
<script>
export default{
computed: {
loggedInUser(){
return this.$auth.loggedIn
}
}
}
Related
I currently have a frontend auth app somewhat made with NuxtJS, where it will take in username/password fields and then use this.$auth.login to login.
I'm confused, though, on how to pass this info to the backend so it can verify that the username/password combination is correct. Currently my code will direct to the next page no matter what I put in the fields (makes sense since I haven't configured anything yet). I understand I need to use Axios POST requests somehow and I made an attempt at that but I don't really know what to do next. I don't know how to grab the token that contains my user data and push it to my backend (adonisJS) so I can check it against the database.
My login.vue component
<template>
<div>
<v-form #submit.prevent="loginUser">
<div>
<v-label>Username</v-label>
<v-text-field color='red' v-model="login.username" />
</div>
<div>
<v-label>Password</v-label>
<v-text-field color='red' v-model="login.password" />
</div>
<div>
<v-btn type="submit" color='purple'>Submit</v-btn>
</div>
</v-form>
</div>
</template>
<script>
export default {
data() {
return {
login: {
username: '',
password: ''
}
}
},
methods: {
async loginUser() {
const response = await this.$axios.post("/auth/users", {
email: this.email,
password: this.password,
}).then(
await this.$auth.login({
data: {
email: this.email,
password: this.password
}
}).then(() => {
this.$router.push('/dashboard')
}).catch(err => {
console.log(err)
})
).catch(err => console.log(err));
}
}
}
</script>
My nuxt.js.config (relevant parts)
axios: {
baseURL: 'http://localhost:3000/api', // Used as fallback if no runtime config is provided
},
auth: {
strategies: {
local: {
token: {
property: 'access_token',
required: true,
type: 'Bearer'
},
user: {
property: false, // <--- Default "user"
autoFetch: true
},
endpoints: {
login: { url: '/auth/login', method: 'post' },
logout: { url: '/auth/logout', method: 'post' },
user: { url: '/user', method: 'get' }
}
}
}
},
router: {
middleware: ['auth']
},
Can anyone help me out with what I need to do with axios? (I checked my storage to see if there was a token there and it just says "false".) Thank you!
You don't need to use axios post, this is how you should log in
methods: {
async loginUser() {
try {
//this will attempt to log in, and if successful it'll go to the home page unless you change the default redirects
const fields = {email: this.email, password: this.password};
await this.$auth.loginWith("local", { data: fields });
console.log("login successful");
} catch (errors) {
//an error occurred, could be wrong password or any other type of error
console.error(errors);
}
}
}
local is the strategy name and means that it's your own auth server, if you were using google for example you'd put google there, check out loginwith and local
the auth library already knows that your login url is /auth/login since you stated that in the nuxt config.
if you want to control where it goes after the login, look into the redirect options in the nuxt.config from the docs and specifically in this case home.
auth: {
redirect: {
home: '/'
}
}
I am using the following config for nuxt-auth-next in my nuxt application
nuxt.config.js
auth: {
strategies:{
google: {
clientId: "my_client_id.apps.googleusercontent.com",
redirectUri: `http://localhost:3000/apps`,
codeChallengeMethod: '',
scope: ['profile', 'email'],
responseType: 'token id_token'
}
},
redirect: {
login: '/login',
logout: false,
home: '/apps',
callback: false
}
},
router: {
middleware: ['auth']
}
And this is my login.vue file
<template>
<div>
<div>
<template>
<b-button #click="loginClicked()">Login with Google</b-button>
</template>
</div>
</div>
</template>
<script>
export default {
methods: {
async loginClicked() {
try {
await this.$auth.loginWith('google');
} catch (err) {
console.log("login error: " + err);
}
}
}
}
</script>
When I press Login with Google button from my login page, it goes to Google authentication page, successfully passes authentication, goes to localhost:3000/apps page(my redirect url) and then immediately returns to localhost:3000/login - and this.$auth.loggedIn is false.
I've already visited https://github.com/nuxt-community/auth-module/issues/1127, but that did not help. Am I missing something?
"#nuxtjs/auth-next": "5.0.0-1624817847.21691f1",
"nuxt": "^2.15.8"
Vue devtools after I press 'Login with Google'
As stated on this page, auth-next aka v5 is still in beta and you may encounter some bugs, even tho it is more rich in terms of features.
If you are fine with what the Nuxt module provides with the v4, sticking to it may be a more stable solution.
I'm using nuxt.js, after I send a login request with email and password to the backend I get a response which contains a message, token and user informations, how can I access user informations in the response and save it inside some state in store.js after a successful login?
I wanted to save user object in user state down in store/index.js using an action saveUserAction which might be dispatched after a successful login, i dont know if thats right or not, any advise would be very helpful
Response
{
"message":"success",
"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiNzFkYjA1MWM2MTYxMmE4YzAyNWI2YjU3N2xMzJiNzJjMjI0MzRlY2IzNzYwNTg2N2NjOWQ5ZWEwY2MiMJM3uYEiZ8GSlPlQhIctVErO2KzwXOBxifWWoM7et_qT-mgvfsk3ljwiQF9iPQw-WeekBx8J8lcmxDLESa3tfE1Re1Xk2flkcBLmiI4JN2YHh08U1U",
"user":{
"id":1,
"role_id":4587,
"firstname":"Hans",
"lastname":"newman",
"email":"newman#gmail.com",
"email_verified_at":null,
"phone":"89498",
"skype":"gdgdfg",
"birthdate":"2021-05-02",
"address":"asdfaf",
"postalcode":14984,
"city":"jisf",
"country":"isfisf",
"status":"mfof",
"created_at":"2021-06-16T09:33:08.000000Z",
"updated_at":"2021-06-16T09:39:41.000000Z",
"image":"1623835988-carlsen.png",
"description":"sfdgg",
"geo_lat":5.5,
"geo_lng":8.1
}
}
login.vue
<script>
import { mapActions } from 'vuex'
export default {
data() {
return {
auth: false,
email: '',
password: '',
}
},
methods: {
async login() {
const succesfulLogin = await this.$auth.loginWith('local', {
data: {
email: this.email,
password: this.password,
},
})
if (succesfulLogin) {
await this.$auth.setUser({
email: this.email,
password: this.password,
})
this.$router.push('/profile')
}
},
},
}
</script>
store/index.js
export const state = () => ({
user:{}
})
export const mutations = {
saveUser(state, payload) {
state.user=payload;
}
}
export const actions = {
saveUserAction({commit}, UserObject){
commit('saveUser');
}
}
Go to your vue devtools, vuex tab and look for auth, it should already be available. This answer may help you during your debugging: https://stackoverflow.com/a/68081536/8816585
Since you do have your user object in the response, this kind of configuration should do it, as shown in the documentation. No need to make some other vuex actions.
auth: {
strategies: {
local: {
token: {
property: 'token',
global: true,
},
user: {
property: 'user', // the name of your object in your backend response payload
},
endpoints: {
[...]
}
}
}
}
I'm going straight to the point here. I'm doing an authentication on the login page, after clicking the login page it redirects me to a product's component and on that product's component, I do an HTTP request to get all the products. However, after logging in and redirecting on the products page the product's component seems it can't run my HTTP request on the created() lifecycle hooks. Is this a normal behaviour?
Here's my code:
LOGIN:
export default{
data(){
return {
email: '',
password: ''
}
},
methods:{
login(){
var data = {
client_id: 2,
client_secret: 'TOKEN_HERE,
grant_type: 'password',
username: this.email,
password: this.password
}
this.$http.post("oauth/token", data).then(response => {
this.$auth.setToken(response.body.access_token, response.body.expires_in + Date.now())
this.$router.push('/products')
})
}
}
PRODUCTS.VUE
import Products from './product/Products.vue'
export default {
components: {
'my-products' : Products
},
created(){
this.$http.get('api/products')
.then(response => {
alert("products from feed");
this.products = response.body
})
}
}
after redirecting to products.vue created lifecycle hook, it can't run my http request.
Thanks in advance.
I seems like you need mounted hook instead.
https://v2.vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks
I'm building an application with JWT Login and i check if the user is logged in (when visit /) and then i redirect to Dashboard:
let routes = [
{ path: '', component: Login,
beforeEnter(to, from, next) {
if (auth.loggedIn()) {
next({ path: '/dashboard' });
} else {
next();
}
}
},
{ path: '/dashboard', component: Dashboard }
];
The Dashboard component is simple:
export default {
created() {
this.loadOrders();
},
methods: {
loadOrders() {
// Load Orders
}
},
watch: {
'$route': 'loadOrders'
},
}
If i Login, i will be redirected to /dashboard and the data is fetched.
If i'm on Dashboard (http://localhost:8080/dashboard) and i hit "refresh" on browser, this works too.
But, if i'm on this url http://localhost:8080/dashboard and i delete dashboard (so i just digit http://localhost:8080) the beforeEnter see that i'm authenticated and redirect me to /dashboard, but the data is not fetched (created, mounted etc are not called).
Why there is no data section on your Dashboard component? If you use some data (ex: loading, error, post) on template, then you need to return them in data section. Try to add that section.
example:
<template>
<div>
<div v-if="loading">
Loading...
</div>
<div v-if="!loading">
{{ error }}
</div>
<div>
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
</div>
</template>
export default {
data () {
return {
loading: false,
error: null,
post: null
}
},
created () {
this.fetchData()
},
watch: {
'$route': 'fetchData'
},
methods: {
fetchData () {
this.loading = true
...
this.error = msg;
this.post = post
}
}
};
When any action is taken against an API, the server responds with relevant status.
So when you are deleting the product, you have to ignore the response from the server and then push the new path to Vue router.