Vue-Cookies Can't Get Cookie - javascript

I am trying to setup an OAuth service from my Node.js back-end to my Vue front-end. Currently, the back-end appears to be working correctly; I am able to authenticate successfully with my google account and then am redirected to the appropriate UI View upon authentication. The cookie is also being stored.
My node service is running on localhost:3000
My Vue UI is running on localhost:8080
I can access the cookie using
document.cookie, and it shows:
"express:sess=<Data here>; express:sess.sig=<Data here>"
The problem is that I am using vue-cookies, and can't retrieve the cookie using window.$cookies.get(...);
In my main.js file I am importing vue-cookies:
import VueCookies from "vue-cookies";
Vue.use(VueCookies);
window.$cookies.config("7D", "", "localhost");
new Vue({
router,
store,
vuetify,
render: h => h(App)
}).$mount("#app");
Here is my router/index.js where I am using that code:
import Vue from "vue";
...
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
debugger;
if (!window.$cookies) {
next({
path: "/login",
params: { nextUrl: to.fullPath }
});
} else {
const cookie = window.$cookies;
if (to.matched.some(record => record.meta.isAdmin)) {
if (cookie.isAdmin) {
next();
} else {
next({
path: "/login",
params: { nextUrl: to.fullPath }
});
}
} else {
next();
}
}
} else {
next();
}
});
If I try to log window.$cookies.get("express:sess"), it returns null. Not sure what I am doing wrong. I know that window.$cookies is defined from the console as well, because I can see all the methods/properties on that object.
If I create a cookie from the developer tools, with a name of "test", I can retrieve it:
> window.$cookies.get("test")
> "value"
EDIT:
If I change the cookie that I manually create to have a name of test:test, the output is null! Does the : character have something to do with why I can't retrieve the cookie??
> window.$cookies.get("test:test")
> null
EDIT 2:
I can do the following and see the cookies are there, but cannot access them for some reason.
window.$cookies.keys()
(3) […]
​
0: "express:sess"
​
1: "express:sess.sig"
​
2: "test"
​
length: 3

Your problem relies on how vue-cookie manages cookies. if you take a look a the set method you can see that vue-cookie encodes your values before storing the cookie.
Example:
let's say you store a cookie using vue-cookie:
$cookies.set('express:sess')
this will store the name of the cookie as express%3Asess
which is the result of encodeURIComponent('express:sess')
I recommend using a different library or just using native browser API's

Related

Keycloak Javascript failed to inicialize

I'm trying to use Keycloak with JavaScript and these are the steps that I followed.
I create a client inside KeyCloak admin panel.
Link to image
I copy the .json file to my apache folder.
{
"realm": "master",
"auth-server-url": "http://localhost:8080/auth",
"ssl-required": "external",
"resource": "test",
"public-client": true,
"confidential-port": 0
}
I go to my index.html and I add these two lines for calling the script.
<script src="keycloak.js"></script>
<script>
function initKeycloak() {
const keycloak = new Keycloak();
keycloak.init().then(function(authenticated) {
alert(authenticated ? 'authenticated' : 'not authenticated');
}).catch(function() {
alert('failed to initialize');
});
}
</script>
this is what i have in myLogical.js
var keycloak = new Keycloak();
function initKeycloak() {
keycloak.init({onLoad: 'login-required'}).then(function() {
constructTableRows(keycloak.idTokenParsed);
pasteToken(keycloak.token);
}).catch(function() {
alert('failed to initialize');
});
}
function constructTableRows(keycloakToken) {
document.getElementById('row-username').innerHTML = keycloakToken.preferred_username;
document.getElementById('row-firstName').innerHTML = keycloakToken.given_name;
document.getElementById('row-lastName').innerHTML = keycloakToken.family_name;
document.getElementById('row-name').innerHTML = keycloakToken.name;
document.getElementById('row-email').innerHTML = keycloakToken.email;
}
function pasteToken(token){
document.getElementById('ta-token').value = token;
document.getElementById('ta-refreshToken').value = keycloak.refreshToken;
}
var refreshToken = function() {
keycloak.updateToken(-1)
I tried to download the file keycloak.js and put it directly on my root folder but it happen the same problem.
These is the message I got when I try to open the page
I'm confused about point 1, does keycloak automatically load configuration from json file in Apache folder? Let's assume that no, and I think that where your problem lies, you're not passing config param to keycloak constructor.
How to initialize keycloak:
const initKeycloak = async () => {
//you can hardcode these values for now just to see if everything works
const config = { url: 'http://localhost:8080/auth', realm: 'master', clientId: 'test'};
const keycloak = new Keycloak(config);
await keycloak
.init({ onLoad: 'login-required' })
.then(isAuthenticated => {
//user is authenticated
})
.catch(error => { console.log('keycloak error', error); });
}
Another important thing is that keycloak-js library version (in package.json) must match keycloak server version. Sometimes different versions work with each other but it's always best practice that keycloak-js version matches keycloak server version.
You can also look here: https://github.com/m-s7/react-core/blob/devel/src/services/keycloak-service.ts this is my repo with working keycloak-js implementation.

Get localStorage data in nuxt layout function

I have such a problem: I need to get localStorage data before nuxt layout is loaded in pages/index.vue
/pages/index.vue
<script>
export default {
layout (context) {
if (localStorage.getItem('AUTH_TOKEN')){
this.$store.dispatch('changeAuthStatus', {
authStatus: true,
accessToken: localStorage.getItem('AUTH_TOKEN'),
profileData: JSON.parse(localStorage.getItem('PROFILE_DATA'))
}).then(() => {
this.$store.dispatch('changeLoadedStatus', {
isLoaded: true
})
})
}
else {
this.$router.push('/auth')
}
}
</script>
The error when the page is loaded: localStorage is not defined
Maybe I can get localStorage data using context? Or maybe you can suggest to me any package so I can use it in the layout function?
I found the solution:
I just installed nuxt-universal-storage module, that Amirhossein Shahbazi suggested. So I have just done this:
/pages/index.vue:
<script>
export default {
middleware: ['auth'],
layout (context) {
let currentRole = context.app.$storage.getUniversal('PROFILE_DATA')
console.log(currentRole)
let currentLayout = 'default'
let defaultRoles = ['customer_support_manager', 'checker', 'storekeeper']
let tabletRoles = ['deputy_cutting_shop']
if (defaultRoles.includes(currentRole.role)) {
currentLayout = 'default'
}
else if (tabletRoles.includes(currentRole.role)) {
currentLayout = 'tablet'
}
return currentLayout
}
</script>
/middleware/auth.js:
export default function ({ redirect, app, store }) {
// some token checkers for existing, for 401 error and for their validity
}
If I'm not mistaken, Nuxt is the SSR solution for Vue (same as Next for React), right?
If so, you don't have access to the localStorage. Server Side is not running in your browser!
This kind of code works fine
<script>
export default {
layout({ store }) {
if (process.client) {
console.log('localStorage?', localStorage.getItem('myCat'))
console.log('store?', store)
}
},
}
</script>
Because localStorage is not available on the server.
Try to use localStorage.setItem('myCat', 'Tom'), move to your page and see how it displays the localStorage and the store (don't forget to use the context since this is not available here).
You can use cookie-universal-nuxt
After login you can set "AUTH_TOKEN" as cookie instead of localStorage
window.$cookies.set('AUTH_TOKEN', token)
and you can access it in layout function as
layout (context) {
let token=context.app.$cookies.get('AUTH_TOKEN')
}

Laravel CRUD Axios Vue

Im creating my first CRUD in Vue/Laravel and now I'm trying to send a create to my backend application, this is my code:
Frontend:
async addDespesa() {
let uri = "api/despesas/create";
const response = await axios.get(uri, this.despesa).then((response) => {
this.$router.push({ name: "despesas" });
});
},
Backend:
public function create()
{
//
}
Errors in inspect on Browser:
>[vue-router] Route with name 'despesas' does not exist
>Uncaught (in promise) NavigationDuplicated: Avoided redundant navigation to current location: "/".
at createRouterError
at createNavigationDuplicatedError
at HashHistory.confirmTransition
at HashHistory.transitionTo
at eval
at HashHistory.push
at new Promise
at VueRouter.push
at eval
Your backend seems fine, the problem is in the .then part of your Axios call:
this.$router.push({ name: "despesas" });
You should check your frontend routes (probably in a file called routes.js) and make sure you have a route named despesas. So something like this:
let routes = [
{
'path': '/path/to/despesas',
'name': 'despesas',
component: require('./path/to/despesas-component').default
},
...
other routes
];

Nuxt: Auth + Axios setup

I'm struggling with the configuration of auth + Axios.
I'm currently working on our social login (FB and google). It half works.
First of all, I have my Axios instance configured as a plugin. We do have two instances, one that we use for general API requests and another one that we will use for logged user requests.
plugins/axios.js
export default function({ $axios, redirect, app }) {
$axios.defaults.baseURL = process.env.baseUrl
$axios.defaults.headers = {
Authorization: `Bearer ${process.env.APIKey}`,
Accept: 'application/json',
'Content-Type': 'application/json',
lang: app.i18n.locale
}
$axios.onError(error => {
const code = parseInt(error.response && error.response.status)
if (code === 400) {
redirect('/400')
}
if (code === 404) {
redirect('/404')
}
if (code === 500) {
redirect('/500')
}
})
}
plugins/auth-axios.js
export default function({ $axios }, inject) {
const authAxios = $axios.create()
// authAxios.setToken('123', 'Bearer')
inject('authAxios', authAxios)
}
The first client works perfectly in the whole app.
Now I'm configuring the auth plugin. When I log in through Facebook or google I need to take the response data of the logged user from the social network and send it to my API, expecting a user with the token as the response. This will be the user that I'll set in the auth plugin. Every time I log in with Facebook it appears to work well except when It arrives at the plugin code. $auth.loggedIn is always false.
I've made it work forcing $auth.fetchUser at the beginning of the code but it doesn't work well at all. It shows an Axios error when console.log($auth). This is my auth code:
plugins/auth.js
export default async function({ app: { $auth, $axios } }) {
$auth.fetchUser()
console.log($auth)
if (!$auth.loggedIn) {
return
}
const authStrategy = $auth.strategy.name
if (authStrategy === 'facebook' || authStrategy === 'google') {
if ($auth.user.google_id || $auth.user.fb_id) return
try {
const url = `/client/social`
var postData
if (authStrategy == 'facebook')
postData = {
name: $auth.user.name,
email: $auth.user.email,
fb_id: $auth.user.id,
avatar: $auth.user.picture.data.url,
birthday: $auth.user.birthday
}
else
postData = {
name: $auth.user.given_name,
surname: $auth.user.family_name,
email: $auth.user.email,
google_id: $auth.user.sub,
avatar: $auth.user.picture,
locale: $auth.user.locale
}
const { data } = await $axios.post(url, postData)
$auth.setToken('client', data.access_token)
$auth.setUser(data.client)
} catch (e) {
console.log(e)
}
}
}
The console.log($auth) error:
'$state': {
user: null,
loggedIn: false,
strategy: 'facebook'
},
error: TypeError: Cannot set property 'Authorization' of undefined
at Function.setHeader (server.js:1556:42)
at Oauth2Scheme._setToken (server.js:1014:31)
at Oauth2Scheme.mounted (server.js:1001:12)
at Auth.mounted (server.js:516:42)
at Auth.init (server.js:459:18)
at module.exports../.nuxt/auth/plugin.js._webpack_exports_.default (server.js:939:16)
at createApp (server.js:2432:87)
}
And my auth module config:
import dotenv from 'dotenv'
dotenv.config()
export const auth = {
plugins: [
// {
// src: '~/plugins/axios',
// ssr: true
// },
{
src: '~/plugins/auth-axios',
ssr: true
},
'~/plugins/auth.js'
],
redirect: {
login: '/',
callback: '/callback'
},
strategies: {
local: false,
facebook: {
client_id: '#############',
userinfo_endpoint:
'https://graph.facebook.com/v2.12/me?fields=about,name,picture{url},email,birthday',
scope: ['public_profile', 'email', 'user_birthday']
},
google: {
client_id:
'#####################'
}
}
}
Seems that auth when login is trying to set the Axios token (also when I log out it tries to remove it) but it fails. If I go to the Chrome dev tools and debug it to see which Axios instance is trying to use for that. Every time is the main Axios instance and it's supposed to be accessible there.
Screenshot from DevTools:
Screenshot from DevTools
Does someone know what I'm missing? Can I prevent auth facebook strategy to update any Axios instance? Or, can I specify which Axios instance to update (set / remove token)?
EDIT: Forcing the $auth.fetchUser my auth plugin code does work but with the error mentioned before. When I try to logOut it doesn't work due to the same error when trying to remove the token automatically)
I'm going crazy with this issue for two weeks now.
Thanks so much!

I have removed the `Cookies`'s token and csrftoken, why still have them?

I have a
This is my key code:
var that = this
// clear sessionid, csrftoken
that.$Cookies.remove('sessionid');
that.$Cookies.remove('csrftoken');
// login
that.$http.post(Urls.users.login(), params).then((response) => {
setTimeout(loading, 0)
that.$Cookies.set('token', response.data.key);
that.get_user_info()
}).catch((response) => {
debugger
setTimeout(loading, 0)
}
)
in the main.js I configure like this, so the the component I can use the this.$Cookies:
import Cookies from 'js-cookie';
Object.defineProperty(Vue.prototype, "$Cookies", { value: Cookies })
You see I have removed the token and csrftoken, but when I access the login api, there still has the token and csrftoken in the request:
Whether I clear the token and csrftoken in the this.$Cookies it did not clear success essentially.
I am so interested in this question. Why I have deleted some cookie, but when I send a request, the cookie is Still in header?
So I find you use js-cookie, and I go to the github and get this:
Delete a cookie valid to the path of the current page:
Cookies.set('name', 'value', { path: '' });
Cookies.remove('name'); // fail!
Cookies.remove('name', { path: '' }); // removed!
IMPORTANT! When deleting a cookie, you must pass the exact same path and domain attributes that were used to set the cookie, unless you're relying on the default attributes.
Hope can help you~

Categories