CSRF token mismatch when using nuxt/auth + Laravel Sanctum - laravel

CSRF token mismatch. error on register page when I try to login it was working good.
my register page
<template>
<b-container>
<b-row>
<b-col cols="6" class="mx-auto">
<b-card title="Register">
<b-button variant="primary" #click="register()">Register</b-button>
</b-card>
</b-col>
</b-row>
</b-container>
</template>
<script>
export default {
auth: 'guest',
data() {
return {
name: "john",
email: "john#email.com",
password: "123321"
};
},
methods: {
async register() {
const data = {
'name': this.name,
'email': this.email,
'password': this.password
}
console.log(data);
try {
const res = await this.$axios.post('/register', data)
console.log(res)
}
catch(e) {
console.log(e.message)
}
}
}
};
</script>
nuxt.config.js
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'hello',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
router: {
middleware: ['auth'],
},
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://go.nuxtjs.dev/bootstrap
'bootstrap-vue/nuxt',
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
// https://go.nuxtjs.dev/pwa
'#nuxtjs/pwa',
'#nuxtjs/auth-next',
],
axios: {
baseURL: "http://localhost:8000/api"
},
auth: {
strategies: {
'laravelSanctum': {
provider: 'laravel/sanctum',
url: 'http://localhost:8000',
endpoints: {
login: {
url: "/api/login"
},
logout: {
url: "/api/logout"
},
user: {
url: "/api/user"
}
},
user: {
property: false
}
}
},
redirect: {
login: "/login",
logout: "/",
home: "/dashboard"
}
},
// PWA module configuration: https://go.nuxtjs.dev/pwa
pwa: {
manifest: {
lang: 'en'
}
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
babel: {
plugins: [
['#babel/plugin-proposal-private-methods', { loose: true }]
]
}
}
}
Login Page
<template>
<b-container>
<b-row>
<b-col cols="6" class="mx-auto">
<b-card title="Login">
<b-button variant="primary" #click="login()">Login</b-button>
</b-card>
</b-col>
</b-row>
</b-container>
</template>
<script>
export default {
middleware: ["guest"],
data() {
return {
form: {
email : "john#email.com",
password : "123321"
}
};
},
methods: {
login() {
this.$auth
.loginWith("laravelSanctum", {
data: this.form
})
.then(response => console.log(response))
.catch(error => console.log(error));
}
}
};
</script>
EDIT: I do have the following error in my network tab devtools.
network tab error xhr.js?b50d:177 POST localhost:8000/api/register 419 (unknown status) "message": "CSRF token mismatch.", "exception": "Symfony\Component\HttpKernel\Exception\HttpException",

Related

Nuxtjs and Scatum duplicate requests and no cookie stored

I am facing a weird problem. I have a Laravel API server setup and a Nuxtjs frontend. I am using LaravelSanctum Provider in Nuxtjs. I am able to send request and the authentication and data retrival is fine. However, the cookies doesn't seem to get stored in my local storage.
login.vue
<script>
export default {
async login() {
this.$auth.loginWith('laravelSanctum', {
data: {
email: 'test#gmail.com',
password: 'test',
},
})
},
}
</script>
nuxt.config.js
axios: {
baseURL: 'http://local.api.test/api/v1/',
proxy: true,
credentials: true,
},
proxy: {
'/laravel': {
target: 'http://local.api.test/api/v1/',
pathRewrite: { '^/laravel': '/' },
},
},
auth: {
strategies: {
laravelSanctum: {
provider: 'laravel/sanctum',
url: 'http://local.api.test',
endpoints: {
login: {
url: '/api/v1/login/admin',
},
user: {
url: '/api/v1/admin',
},
},
},
},
},

in nuxt.js SSR i was created authentication system using laravel sactum im facing redirecting error

nuxt.js I'm implemented an SSR authentication system using Laravel sanctum but I'm facing Redirecting issue.
When I have entered login credentials after summited my LOGIN button it Was not redirected to Dashboard it still on the login page if I need to visit Dashboard I need to manually enter the dashboard URL same thing on logout.
nuxt.config.js
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
title: 'hello',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
router: {
middleware: ['auth'],
},
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
// https://go.nuxtjs.dev/bootstrap
'bootstrap-vue/nuxt',
// https://go.nuxtjs.dev/axios
'#nuxtjs/axios',
// https://go.nuxtjs.dev/pwa
'#nuxtjs/pwa',
'#nuxtjs/auth-next',
],
// Axios module configuration: https://go.nuxtjs.dev/config-axios
axios: {},
auth: {
strategies: {
'laravelSanctum': {
provider: 'laravel/sanctum',
url: 'http://localhost:8000',
endpoints: {
login: {
url: "/api/login"
},
logout: {
url: "/api/logout"
},
user: {
url: "/api/user"
}
},
user: {
property: false
}
}
},
redirect: {
login: "/login",
logout: "/",
home: "/dashboard"
}
},
// PWA module configuration: https://go.nuxtjs.dev/pwa
pwa: {
manifest: {
lang: 'en'
}
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
babel: {
plugins: [
['#babel/plugin-proposal-private-methods', { loose: true }]
]
}
}
}
middleware
export default ({ app, redirect }) => {
if (app.$auth.loggedIn) {
return redirect("/");
}
};
Login Page
<template>
<b-container>
<b-row>
<b-col cols="6" class="mx-auto">
<b-card title="Login">
<b-button variant="primary" #click="login()">Login</b-button>
</b-card>
</b-col>
</b-row>
</b-container>
</template>
<script>
export default {
middleware: ["guest"],
data() {
return {
form: {
email : "john#email.com",
password : "123321"
}
};
},
methods: {
login() {
this.$auth
.loginWith("laravelSanctum", {
data: this.form
})
.then(response => console.log(response))
.catch(error => console.log(error));
}
}
};
</script>
Layout default
<template>
<div>
<div>
<b-navbar type="dark" variant="dark">
<b-navbar-brand href="/">NavBar</b-navbar-brand>
<b-navbar-nav class="ml-auto">
<template v-if="$auth.loggedIn">
<b-nav-item to="/dashboard">Dashboard</b-nav-item>
<b-nav-item href="#" #click.prevent="logout()">Logout</b-nav-item>
</template>
<template v-else>
<b-nav-item to="/login">Login</b-nav-item>
</template>
</b-navbar-nav>
</b-navbar>
</div>
<Nuxt />
</div>
</template>
<script>
export default {
methods: {
async logout() {
try {
await this.$auth.logout();
} catch (error) {
console.log(error);
}
}
}
};
</script>
#nuxt/auth do have a middleware for the auth already, you don't need to do it yourself.
To benefit of it, you can add this to your nuxt.config.js file
router: {
middleware: ['auth'],
},
In any .vue file that you want to whitelist (aka if you do not want to check if loggedIn is true), you can use the auth key
<script>
export default {
auth: false, // will bypass the middleware's verification
}
</script>
Everywhere else, it will double check that you're logged in before proceeding. Otherwise, it will bring you to the login page that you've specified.

Nuxt Auth Redirect Me Back to Login Page After Refresh Even a Successfull Login

I'm using #nuxt/auth module with Laravel Passport I'm facing a problem when a I attempt to login it logged me in successfully but when I refresh the page it redirect me back to login page I checked the cookies and it's set and has the token but i don't why this is happening?
Login.vue
<template>
<v-parallax
dark
:src="require(`../assets/images/auth-bg.jpg`)"
height="100%"
>
<v-app id="app-container" dark>
<v-container fill-height fluid>
<v-card
class="mx-auto"
justify="center"
width="512"
max-width="512"
elevation="2"
outlined
>
<v-form
ref="form"
v-model="valid"
lazy-validation
>
<v-card-title>Login</v-card-title>
<v-card-text>
<v-text-field
v-model="form.username"
:counter="32"
type="text"
label="Username"
name="usermame"
required
/>
<v-text-field
v-model="form.password"
type="password"
label="Password"
name="password"
required
/>
</v-card-text>
<v-alert
v-if="error"
border="left"
close-text="Close Alert"
color="#C51162"
dark
dismissible
>
{{ error }}
</v-alert>
<v-card-actions>
<v-btn
block
outlined
shaped
#click="loginPassport"
>
Login
</v-btn>
</v-card-actions>
</v-form>
</v-card>
</v-container>
</v-app>
</v-parallax>
</template>
<script>
export default {
layout: 'auth',
auth: 'guest',
data: () => ({
valid: false,
loader: null,
loading: false,
usernameRules: [
v => !!v || 'Username is required',
v => v.length <= 32 || 'Name must be less than 32 characters'
],
passwordRules: [
v => !!v || 'Password is required',
v => v.length <= 32 || 'Password must be less than 32 characters'
],
form: {
username: '',
password: ''
},
error: null
}),
watch: {
loader () {
const status = this.loader
this[status] = !this[status]
setTimeout(() => (this[status] = false), 500)
this.loader = null
}
},
methods: {
async loginPassport () {
this.error = null
await this.$auth
.loginWith('DersTVCentral', { data: this.form })
.then(() => this.$router.push('/'))
.catch(() => (this.error = 'Incorrect email or password.'))
}
}
}
</script>
<style>
#app-container {
background-color: transparent;
}
</style>
Nuxt.config.js
import colors from 'vuetify/es5/util/colors'
export default {
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
titleTemplate: '%s - DersTV-Cloud-UI',
title: 'DersTV-Cloud-UI',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
// runtime config
publicRuntimeConfig: {
apiURL: process.env.API_URL
},
privateRuntimeConfig: {
apiId: process.env.PASSPORT_CLIENT_ID,
apiSecret: process.env.PASSPORT_CLIENT_SECRET
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
// https://go.nuxtjs.dev/eslint
'#nuxtjs/eslint-module',
// https://go.nuxtjs.dev/vuetify
'#nuxtjs/vuetify'
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth-next',
'#nuxtjs/pwa',
'#nuxtjs/dotenv'
],
axios: {
proxy: true,
baseURL: process.env.API_URL
},
proxy: {
'/backend': {
target: process.env.API_URL,
pathRewrite: { '^/backend': '/' }
}
},
router: {
middleware: ['auth']
},
// PWA module configuration: https://go.nuxtjs.dev/pwa
pwa: {
manifest: {
lang: 'en'
}
},
// Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
vuetify: {
customVariables: ['~/assets/variables.scss'],
theme: {
dark: true,
themes: {
dark: {
primary: colors.blue.darken2,
accent: colors.grey.darken3,
secondary: colors.amber.darken3,
info: colors.teal.lighten1,
warning: colors.amber.base,
error: colors.deepOrange.accent4,
success: colors.green.accent3
}
}
}
},
auth: {
redirect: {
home: '/profile'
},
cookie: {
options: {
secure: false
}
},
strategies: {
DersTVCentral: {
name: 'DersTVCentral',
provider: 'laravel/passport',
url: '/backend',
endpoints: {
user: 'api/v1/user',
userInfo: 'api/v1/user'
},
responseType: 'token',
clientId: process.env.PASSPORT_CLIENT_ID,
clientSecret: process.env.PASSPORT_CLIENT_SECRET,
grantType: 'password'
}
}
},
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
}
}
Screenshot of successfull login:

Inline Editor - disable editor and display HTML / render content (Vue)

I am using CKEditor5 with Vue. In my Vuex store, I have the following property:
const state = {
EditMode: false,
}
On a button click by a user with permission, I modify the Vuex store. If EditMode: true, I want to display the in-line editor. Else, display the raw HTML editorData (the user is not authorized to edit, or not in edit mode). I do that below:
<template>
<vx-card :title="editorName" v-if="this.$store.state.EditMode">
<ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
</vx-card>
<vx-card :title="editorName" v-else>
<div v-html="editorData"></div>
</vx-card>
</template>
<script>
import InlineEditor from '#ckeditor/ckeditor5-build-inline'
export default {
name: "RichTextEditor",
props: {
editorName: {
type: String,
required: true,
},
},
data() {
return {
loaded: false,
time: null,
timeElapsedSinceEdit: 0,
editor: InlineEditor,
editorData: 'New entry!',
editorConfig: {
toolbar: {
items: [
'|',
'heading',
'fontFamily',
'fontSize',
'fontColor',
'bold',
'underline',
'italic',
'alignment',
'link',
'highlight',
'superscript',
'subscript',
'|',
'indent',
'outdent',
'|',
'blockQuote',
'horizontalLine',
'imageUpload',
'insertTable',
'mediaEmbed',
'undo',
'redo'
]
},
language: 'en',
image: {
toolbar: [
'imageTextAlternative',
'imageStyle:full',
'imageStyle:side'
]
},
table: {
contentToolbar: [
'tableColumn',
'tableRow',
'mergeTableCells',
'tableCellProperties',
'tableProperties'
]
},
},
}
},
// Below code is situation-specific and not completely relevant
watch: {
editorData: function() {
if (this.loaded) {
this.upsertData()
}
}
},
methods: {
async pollData() {
await
this.$http.get('/api/rte/' + this.editorName)
.then((response) => {
this.editorData = response.data.content
})
.catch((error) => {
if (window.environment == "production") {
location.href = 'pages/error-500/'
} else {
console.log(error.stack)
}
})
this.loaded = true;
},
async upsertData() {
console.log('up')
await
this.$http.post('/api/rte/' + this.editorName + '/upsert', {
data: this.editorData,
})
.then((response) => {
this.$vs.notify({
title: 'Action Completed',
text: response.data.message,
color: 'success',
position: 'top-right'})
})
.catch((error) => {
if (window.environment == "production") {
location.href = 'pages/error-500/'
} else {
console.log(error)
}
})
},
},
created() {
this.pollData();
},
}
</script>
This works, but the in-line styling isn't respected with v-html (sizing and centering). If this.$store.state.EditMode: false, I get the following output:
If this.$store.state.EditMode: true I get this in the in-line editor (as expected).
Raw HTML (editorData property after pollData() is called)
<figure class="image image_resized" style="width:25.51%;"><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTRJO0xRohucbxcjlRoiRaw2cWYTbilYch5NQ&usqp=CAU" alt="Free clipart megaphone announcement public domain vectors - Clipartix"></figure><h2 style="text-align:center;"><span style="color:hsl(30,75%,60%);"><strong>We have a new Intranet!</strong></span></h2><p style="text-align:center;">Summer / Fall Wellness Challenge Link</p>
Research showed that Vue's v-html doesn't respect scoped styling. I'm not entirely sure how that applies to in-line styling. To test output, I replaced my else with the raw HTML and got the same visual output as when I used v-html:
<vx-card :title="editorName" v-else>
<figure class="image image_resized" style="width:25.51%;"><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTRJO0xRohucbxcjlRoiRaw2cWYTbilYch5NQ&usqp=CAU" alt="Free clipart megaphone announcement public domain vectors - Clipartix"></figure><h2 style="text-align:center;"><span style="color:hsl(30,75%,60%);"><strong>We have a new Intranet!</strong></span></h2><p style="text-align:center;">Summer / Fall Wellness Challenge Link</p>
</vx-card>
What is the proper way to disable the inline editor and maintain visual consistency?
<template>
<vx-card :title="editorName" v-if="loaded">
<ckeditor :editor="editor" v-model="editorData" :config="editorConfig" :readonly="editorDisabled" :disabled="editorDisabled" ></ckeditor>
</vx-card>
</template>
//...
watch:{
'$store.state.EditMode'(value, oldValue) {
if(value) {
this.editorDisabled = false;
} else {
this.editorDisabled = true;
}
},
},
//...
Question answered here:
https://github.com/ckeditor/ckeditor5-vue/issues/154

Vue: event emitted is not getting picked up

I am able to pick up fire emitgetcartitems but for some reason the other listener, emitaddnotes, is not firing handleAddNotes(). I checked in context of the component as well by checking this.$listeners and I only saw emitgetcartitems listed for it. I'm not sure why the other event is not working at all.
blade template
<div id = "app">
<Modal
:modal-type="modalType"
:selected-product="selectedProduct"
:variant-data="variantData"
#emitgetcartitems="handleGetCartItems"
#emitaddnotes="handleAddNotes"
>
</Modal>
<Cart>
</Cart>
</div>
app.js
window.Vue = require('vue');
window.axios = require('axios');
Vue.component('Modal',
require('./components/Modal.vue').default);
new Vue({
el: "#app",
data() {
return {
modalType: null,
orderNotes: null,
couponCode: null,
selectedProduct: {},
variantData: [],
cart: {}
}
},
methods: {
handleChangeTab: function(tab) {
this.activeTab = tab
},
handleHideFlashMsg: function() {
this.flashStatus = false
},
handleAddNotes: function(){
console.log("!!!!!!!")
},
handleGetCartItems: function() {
axios
.get('/api/a-cart')
.then(response => {
this.cart = response.cart;
});
},
}
)}
Modal.vue
<template>
<div>
<button v-on:click="addNotes()"></button>
</div>
</template>
<script>
export default {
data() {
return {
couponInput: '',
}
},
props: {
selectedProduct: {type: Object},
orderNotes: {type: String},
couponCode: {type: String}
},
methods: {
getCartItems: function() {
console.log("GET CART")
this.$emit('emitgetcartitems')
},
addNotes: function() {
console.log("ADD NOTES")
this.$emit('emitaddnotes')
},
}
}
</script>

Resources