websanova / vue-auth Goto Github PK
View Code? Open in Web Editor NEWA simple light-weight authentication library for Vue.js
License: MIT License
A simple light-weight authentication library for Vue.js
License: MIT License
When the app gets instantiated, the Refresh
method gets called to refresh the token, just in case its expired and so on, correct?
Problem I get is, right after the Refresh
request is made, and the new token is returned from the server, a new User
request is made to get the user data, but the User
request holds the old token, before the refresh was made, so I get a 401 Unauthorized request from the server. This hangs the whole Vue app, and leaves a blank screen, returning a Uncaught (in promise) TypeError: Cannot read property 'options' of undefined in auth.js?9c12:27
.
This does not happen every time. If I refresh a few times, it gets up and running.
I am getting an extra GET request using the url after a successful/fail login POST:
GET http://http://www.et.com/auth/user
main.js:
// Http
Vue.http.options.root = 'http://www.et.com';
// Vue-auth
Vue.use(VueAuth, {
router: router,
loginData: {url: 'users/auth', method: 'POST', redirect: null},
rolesVar: 'roles',
authType: 'bearer',
tokenHeader: 'Authorization'
});
components/login.vue:
methods: {
submit() {
this.$auth.login({
body: this.data.body,
rememberMe: this.data.rememberMe,
redirect: {name: 'account'},
success() {
console.log('success ' + this.context);
},
error(res) {
console.log('error ' + this.context);
this.error = res.data;
}
});
}
Hi
If I try and lazy load my components using vue-router, when I manually refresh the page the doesn't seem to activate. Requiring the component as normal works fine.
This works:
component: require('./components/pages/HomePage')
This doesn't:
component: function (resolve) {
require(['./components/pages/HomePage'], resolve)
}
Anyone else come across this?
Thanks
Martin
I use the vue-resouce
for API restful.
And I config the options Vue.http.options.root = 'v1'
like this, so if the request url is used relative path, for example:
this.$http.get('auth/user').then(function (res) {})
This will be request as v1/auth/user
.
But the vue-jwt-auth
's default options are used absolute path, like fetchUrl
will not append v1
, so I must implements all options.
Lets say you clear the browser cache and hit refresh again. Is possible to override the default login page on refresh?
In my app if the users credentials don't authenticate it returns a 401 http status code. Which causes vue-auth.js to do some mystery redirect back '/' rather than displaying the error. If a users credentials arent found a 404 is returned which prints the error returned. for the time being i am returning a 403 forbidden http status. Can you tell me how i disable this redirect for 401 responses
Not sure how this refresh token is supposed to work. When is _refreshToken
called? And even if it's called at some point it doesn't set anything after http request to tokenUrl
. Shouldn't it set the token received by the request.
function _refreshToken () {
var _this = this;
if (_getToken.call(this) && this.getOption('tokenType') === 'jwt') {
_http.call(this, {
url: this.getOption('tokenUrl'),
method: 'get',
success: () => {
var tokenJSON = _decodeToken(_getToken.call(_this)),
expireTime = _getTokenExpirationDate(tokenJSON).valueOf(),
nowTime = new Date().valueOf(),
offsetTime = this.getOption('tokenTimeoutOffset'),
timeout = expireTime - nowTime - offsetTime;
clearTimeout(_tokenRefreshTimeout);
_tokenRefreshTimeout = setTimeout(function () {
_refreshToken.call(_this);
}, timeout);
}
});
}
}
Im trying to include Nprogress inside the plugin, but Im getting the following error:
import NProgress from 'nprogress';
^
ParseError: 'import' and 'export' may appear only with 'sourceType: module'
and Im doing that at
import NProgress from 'nprogress';
module.exports = (function () {
var _tokenRefreshTimeout = null
......
at the interceptors function
function _interceptor (Vue, req, res) {
// Version 0.8.0
Vue.http.interceptors.push((request, next) => {
NProgress.start();
if (req) { req.call(this, request); }
next((response) => {
NProgress.done();
if (res) { res.call(this, response); }
});
});
Is the declaration missing something?
I also tried
import {NProgress} from 'nprogress/nprogress.js';
I think the option details should be at first rather than the methods. the method lets users think how am i supposed setup user login api url and meta data.
After logging in im trying to redirect the app to a page called "/find"
but i keep getting redirected to the 404 page.
In the fetchPerform function if i console.log(data.redirect)
the object.redirect should contain the url "/find"
but the logged data is redirect
:
Object
0
:
"/"
1
:
"f"
2
:
"i"
3
:
"n"
4
:
"d"
name
:
"/account"
the loginData object in auth.js is set like
loginData: {url: 'auth/login', method: 'POST', redirect: '/find'},
can you explain why this is doing this?
Adding as a todo.
Rob, this is fantastic. Thank you for pioneering this plugin. I've used it on a few APIs and I'm impressed.
Recently I found myself having to authenticate to a rails API using devise as their JWT provider, which seems common in the rails world. Well, the API requires 3 tokens to help facilitate simultaneous multi-user auth.
How difficult would it be to handle the config to accept an array of intercepted header tokens? Perhaps you could combine the token, tokenHeader, and authType into this format:
example config:
token: [{
name: 'Authorization',
authType: 'bearer',
foundIn: 'header', // default
},{
name: 'uid',
type: 'basic',
foundIn: 'response'
},{
name: 'client',
type: 'basic'
}],
j-toker (a jquery based auth) handles their config like this
tokenFormat: {
"access-token": "{{ access-token }}",
"token-type": "Bearer",
client: "{{ client }}",
expiry: "{{ expiry }}",
uid: "{{ uid }}"
},
I understand I can overwrite the existing methods via config (thank you!) , but just thought I would offer some suggestions to bring added flexibility out-of-the-box.
Thanks for all your work!
Hi there,
I'm trying to implement this lib to my Vue2 app. Basically, i have a problem with collecting token from response since my login response looks like this (token is located in response.data.token
):
{
data: {
...
token: "......"
}
}
Changing the response is pretty much not an option. Any suggestions? (please let me know if you need any more info)
I dont know if that is the purpose of Install function but the fact is when I login
this.$auth.login(this.user, false, '/index');
Im being redirected correctly, then I refresh the page but the function install is being called again and the $auth.data gets lost. set to null.
return function install (Vue, options, router) {
var auth = new Vue(Auth)
console.log('installing auth');
console.log('from install' , auth.$data);
auth.setOptions(options || {})
Object.defineProperties(Vue.prototype, {
$auth: {
get () {
_setRoute.call(auth, this.$route, this.$router)
return auth
}
}
});`
.....
I have the following at main.js
var Vue = require('vue');
var VueRouter = require('vue-router');
var resource = require('vue-resource');
Vue.config.debug = true;
Vue.use(resource);
Vue.use(VueRouter);
import App from './App.vue'
var router = new VueRouter(
{
hashbang: false,
history: true,
linkActiveClass: "active",
root: 'manage'
}
);
router.mode ='html5';
router.map({
'/login':{
component: require('./be-views/login.vue'),
auth:false
},
'/register': {
component: require('./be-views/register.vue'),
auth:false
},
'/logout': {
component: require('./be-views/logout.vue'),
auth: true
},
'/index': {
component: require('./be-views/index.vue'),
auth: true,
subRoutes: {
'/': {
component: require('./be-views/home.vue'),
auth: true
}
}
},
'*': {
component: require('./be-views/404.vue')
}
});
router.alias({
'/':'/index'
});
Vue.use(require('vue-jwt-auth'),
{ fetchUrl:'/api/me',
loginUrl: '/api/login',
notFoundRedirect: '/index',
tokenUrl: '/api/refresh'}, router);
router.start(App,'body');
Also one more question. Why do we need 2 requests:
loginUrl - get token
then
fetchUrl - get user data
Can't the loginUrl request provide both {token: 'asadada.....', user: {id: 1, name: 'Jon'}}
Or even add the user to the token payload.
Is there a particular reason for the second request? Flexibility?
If user has never logged in before then the condition on the line 143 is falsey. Since fetch() is the only external place where _refreshToken() is called an updating timer will never be set.
By the way, do you have any plans on covering the library with tests? The codebase is fairly large and complicated already.
It seems many people are having confusion about the auth flow and the plugins methods. Need some nice workflow documentation (or diagram) here.
I have roles in the jwt token:
"roles": {
"people": "administrator",
"house": "superadmin"
},
Can the above token map it to the router below?
Vue.router.map({
'/people': {
auth: 'administrator',
component: require('./People')
},
'/house': {
auth: ['administrator', 'superadmin'],
component: require('./Hose')
}
});
What is the official browser support for this library? Sorry, i couldn't find that info anywhere.
I migrate my application from vue-jwt-auth
to this new library.
Here's how I setup it:
window.Auth = require('@websanova/vue-auth')
export var router = new VueRouter({
history: true,
hashbang: true,
saveScrollPosition: true,
linkActiveClass: 'active'
});
Vue.use(Auth, {
router: router,
http: Vue.http,
fetchData: {
url: '/api/check',
method: 'get'
},
loginData: {
url: '/api/login',
method: 'post'
},
tokenName: 'token',
});
I can get the token via this.$auth.token()
.
And I also check on chrome developer network tab, the fetch()
has been called and returning the user object from server.
But if I call the user via this.$auth.user()
, it's still an empty object.
What I expect is the this.$auth.user()
will store the user object that I return for fetch()
function like vue-jwt-auth
did.
I'm running Vue 1.0.26, Vue-Router 0.7.13, Vue-Resource 0.8.0 and the latest version of vue-auth.
I'm experiencing Uncaught (in promise) TypeError: res.headers.get is not a function
error when I do resource.get()
, that route is not protected by vur-auth and I didn't setup the auth API url yet.
Is it normal, and is it somthing to do with vue-auth?
Uncaught (in promise) TypeError: res.headers.get is not a function(…)
_getHeaders @ vue.1.0.0.js?a52b:27
_responseIntercept @ auth.js?9c12:88
(anonymous function) @ vue.1.0.0.js?a52b:60
(anonymous function) @ vue-resource.common.js?2f13:1049
(anonymous function) @ vue-resource.common.js?2f13:1048
Just was wondering what does the API look like for token refresh. Lets say if you refresh the browser page a new token will be produced. This needs to be secure as well.
When a user logins successfully i get the following returned data.
{"token":"TOKENKEY","roles":"2"}
My Auth Options
Login Data returns both token and roles
var options = {
token: [{name: 'token', authType: 'bearer', foundIn: 'response'}],
loginData: {url: 'api/auth', method: 'POST', redirect: 'dashboard'},
fetchData: {url: 'api/acnt', method: 'GET'},
rolesVar: 'roles'
};
In My routing i have the following routes
Vue.router.map({
'/auth/login': {
component: (resolve) => { require(['./components/views/login.vue'], resolve); }
},
'dashboard': {
auth: ["1"],
name:"dashboard",
component: (resolve) => { require(['./components/views/dashboard.vue'], resolve); }
});
It Doesn't Route to the dashboard. If I remove auth: ["1"] to auth:true. It works. I am getting the following error
TypeError: this.watch.data is undefined
[Learn More]app.js:15062:58
[vue-router] Uncaught error during transition:
here is a list of vue resources i am using
"@websanova/vue-auth": "^1.4.0-beta",
"vue": "^1.0.26",
"vue-hot-reload-api": "^2.0.6",
"vue-html-loader": "1.2.3",
"vue-loader": "8.5.4",
"vue-mdl": "^0.9.4",
"vue-resource": "^1.0.3",
"vue-router": "^0.7.13",
"vue-strap": "^1.0.11",
"vue-style-loader": "^1.0.0",
"vuex": "^1.0.0-rc.2",
Hi websanova,
Thanks for creating this awesome plugin for vue.js community! It's really helpful!
I have a simple suggestion, will you consider to emit a "authentication status changed" event?
So that we can know the authentication status was changed and perform different logic without refreshing the page.
Please correct me if I'm on the wrong way to design my app, I'm still new to vue.js.
Sincerely appreciate your effort, thank you!
Hey,
Got a question, everytime I log in on my SPA (where I use your package) I go to the protected redirect route and then I can do everything I want/need, but then when I refresh it refreshes the token and sends me back to the login screen..
Can you help me with that? (if I need to give aditional information or something just tell me what you need)
Thanks in advance :)
So, vue team just announced that they will retire vue-resource
as official lib for request handling. From what they are saying, no more development or support will be put into this lib. Any thoughts on replacing this lib (or making it request lib agnostic) in near future? For example, official suggestion is axios
(https://github.com/mzabriskie/axios), but i don't think it will work out-of-the-box
because of different request/response interceptor registration. Lib itself looks good and i plan to use it in my new project. I guess i'm just not comfortable using lib that has limited support or no future development plans.
I'm just starting a new project using vue.js
and this basically means that i will abandon vue-resource
and use axios
instead.
https://medium.com/the-vue-point/retiring-vue-resource-871a82880af4#.fepyvnwbo
Could you add an option that would allow to customize the 'Bearer:' part in authorization headers?
For example express-jwt expects it to be 'Bearer' (without a colon).
When a $auth.loginOther()
is done the previous (admin) users data is wiped and replace with the "logged in as" users data. We should keep both copies as sometimes it's nice to still have the previous users (admin) info such as the name or id.
HI!
I'm using an external golang API created with labstack/echo and using HS256 as the crypt algoritm.
If I try to decode the token throught jwt.io I get the following response:
{
"name": "[email protected]",
"admin": true,
"exp": 1478820041
}
but whatever I try to write in the vue.js application the this.$auth.user()
just return an empty object.
{{ $auth.user() }}
<b>Email:</b> {{ $auth.user().name }}
I've also tried to console.log it on the Account component created method like this:
created () {
console.log(this.$auth.user().name)
},
Any ideas of what could be wrong?
I'm converting one application that is in vue js 1.x to 2.x, whats happens is that the websanova/vue-auth, when i try to login in or register, always ends up with this error
Uncaught (in promise) TypeError: t.headers.set is not a function(…)
changed my configurations from:
Vue.use(Auth, { rolesVar: 'role', router: router, http: Vue.http, loginUrl: 'auth/login', fetchUrl: 'utilizador', tokenUrl: 'refresh/token', tokenName: 'token', authType: 'bearer', tokenHeader: 'Authorization', tokenTimeoutOffset: 1 * 1000 })
to:
Vue.use(Auth, { router: router, http: Vue.http })
login request
```this.$auth.login({
params: this.form,
rememberMe: true,
redirect: '/',
success (res) {
// console.log(res.data.token)
},
error () {
this.erroform = true
}
})```
config router
Vue.use(Router)
const router = new Router({
routes: [
{ path: '/', component: Home, meta: {auth: true} },
{ path: '/login', component: Login, meta: {auth: false} },
{ path: '/registar', component: Register, meta: {auth: false} },
{ path: '*', component: NotFound }
],
mode: 'history',
base: __dirname
})````
thanks
I init my project with vue-cli
, and use vue-jwt-auth
like this:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App'
Vue.use(require('vue-resource'))
Vue.use(VueRouter)
let router = new VueRouter()
router.map({
'/admin': {
auth: 'admin',
component: require('./Admin')
},
'/login': {
auth: false,
component: require('./Login')
}
})
Vue.use(require('vue-jwt-auth'))
router.start(App, 'app')
It is complied well, but the browser console logged :
vue-jwt-auth.js?0fa3:329 Uncaught TypeError: Cannot read property 'beforeEach' of undefined...
I have a laravel API, pretty similar to the test one on your repo. On login I return an Authorization header with the token, your controller is pretty much the same.
On the APP part, when I call
login () {
this.$auth.login({
body: this.auth.body,
rememberMe: this.auth.rememberMe,
redirect: {name: 'account'},
success () {
Toast.create.positive({
html: 'Login Successful'
})
},
error (res) {
Toast.create.negative({
html: (typeof res.data.msg !== 'undefined') ? res.data.msg : 'Error'
})
this.error = res.data
}
})
}
I get a successful login response in the console, but then the auth/user
request which gets the user data is sent without the Authorization token that was just provided on the previous response.
Doing manual HTTP requests yields proper responses.
Am I suppose to handle this, or is it done behind the scenes? I tried reading the code behind on auth.js, but I got pretty much lost with all those __d*ckPunch()
calls 😄
Can you make the http method configurable on _login like this?
function _login (path, data, rememberMe, redirectUrl, options) {
options = options || {}
_http.call(this, {
url: path,
method: options.method || 'post',
data: data, ...
Hi Rob,
Does vue-jwt-auth
work with Vue 2.0? I've been trying to make it work but without any luck.
Uncaught TypeError: Cannot read property 'router' of undefined
Above error is displayed when I run below code:
import Vue from 'vue/dist/vue'
import VueRouter from 'vue-router'
import VueResource from 'vue-resource'
import VueAuth from 'vue-jwt-auth'
Vue.use(VueRouter)
Vue.use(VueResource)
var router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
auth: true,
component: require('./pages/Home.vue')
},
{
path: '/login',
name: 'login',
component: require('./pages/Login.vue')
}
]
})
Vue.use(VueAuth, {}, router)
const app = new Vue({
router,
template: `<router-view></router-view>`
}).$mount('#app')
Hello! @websanova Thank you for the Plugin.
I know it is asking too much, but your plugin is so good, it would be very helpfull If you could make a demo page for making it work !
I landed to your github account because Im having an Issue with my authenticated user trying to reach the /register page or /login page when he/she is already In. The strange situation is
the this.$root.authenticated tell me false even it is set to True look at this image.
I post email, and password, but when I debug the body, it only has password data:
context.$auth.login({
body: {
email: creds.email,
password: creds.password
},
I believe that tokenTimeoutOffset: 5 * 1000, // 5 minutes.
is seconds because setTimeout param is in milliseconds... so 5 * 60 * 1000
will be in minutes.
Edit: there were 2 questions here but i decided to create separate issues for them
Thanks :)
It isn't clear to me as to how my server should respond with a token (jwt in my case) to my vue app at login. Is it supposed to supply the token in the response body, or a response header? If the body, in what property? If a header, what should that header look like?
One of these?
Authorization: Bearer myTokenContents
Authorization: myTokenContents
How can I prevent login from redirect if the response is successful/200
, but the body result is fail
?
Response body:
HTTP/1.1 200 OK
{
status: 'fail',
resut: 'Not found.'
}
Code:
Vue.use(VueAuth, {
router: router,
loginData: {url: 'users/auth', method: 'POST', redirect: '/'},
rolesVar: 'roles',
authType: 'bearer',
tokenHeader: 'Authorization'
});
context.$auth.login({
body: {
email: creds.email,
password: creds.password
},
success: function (data) {
if (data.body.status == 'fail'){
context.error = data
} else {
this.user.authenticated = true
}
},
error: function (err) {
context.error = err
},
rememberMe: creds.rememberMe,
redirect: redirect
});
},
Adding this as a todo.
Hi, I'm wondering if there's a way to turn of the request to /auth/user
that happens after each login?
I can see it happening on this line, and I tried passing an empty object for fetchPerform
and fetchData
options, but it had no effect.
I got build.js:37247 Uncaught TypeError: Cannot read property 'beforeEach' of undefined with the following code:
import VueResource from 'vue-resource';
import VueRouter from 'vue-router';
import VueAuth from '@websanova/vue-auth';
import App from './components/app.vue';
import Login from './components/login.vue';
import Signup from './components/signup.vue';
Vue.use(VueResource);
Vue.use(VueRouter);
export var router = new VueRouter();
// Set up routing and match routes to components
router.map({
'/login':{
component: Login
},
'/signup': {
component: Signup
}
});
// Redirect to the home route if any routes are unmatched
router.redirect({
'*': '/home'
});
// Vue Auth
Vue.use(VueAuth, {
rolesVar: 'roles',
}, router);
Is there some kind of settings I should pass, when I instantiate Auth? Or should I override some method to get token from reponse data?
Response body looks like this:
{ token: 'TOKEN_BODY' }
and of course header Content-Type:'application/json'
is present.
Can I set my login API URL using loginData? Is Params the POST body?
login(context, creds, redirect) {
context.$auth.loginData = {url: API_URL + LOGIN_URL, method: 'POST'}
context.$auth.login({
params: {
email: creds.email,
password: creds.password
},
success: function (data) {
localStorage.setItem('esy_token', data.token)
this.user.authenticated = true
},
error: function (err) {
console.log(err)
},
rememberMe: creds.rememberMe,
redirect: redirect
});
},
Hi
I am looking at implementing vue-auth into an upcoming app and was wondering how I would make this work with a Passport (JWT) backed. The documentation is a little confusing on how I set the endpoints and receive back the token from Passport.
Does vue-auth just "auto-magically" handle all the Token handling?
Also, if I wanted to send the token along with a post request to a REST endpoint protected by Passport, how do I get access to the Token the I have already received from Passport (if vue-auth even works that way as I know it is a client only auth engine)
Thanks in advance.
So I am just wondering lets say if you have a login called /admin/login. How can we define a different login like /users/login. Because lets say if you have admin rights you want to redirect to a dashboard. If you have normal user rights you get redirected to a totally different path. Does loginOther and logoutOther take care of this?
Hi there, really excited to start using this - it's exactly what I need.
I've got a Node backend with Express + RethinkDB using Passport JS for server-side authentication.
How exactly would I implement this plugin with that?
I tried to look into your demo server source but I don't use Laravel so that looks like a total mess to me sadly.
For example, I've got my /login and /register route on the server like this -
app.post('/signup', function(req, res) {
var user = new User({
email: req.query.email,
password: req.query.password
});
user.save().then(function(result) {
res.send(result);
console.log("Worked");
}).error(handleError(res));
});
app.post('/login', passport.authenticate('local'), function(req, res) {
res.json({ loggedin: true });
console.log(res);
});
In your demo code for login, you are calling this $auth property like this -
login() {
this.$auth.login({
body: this.data.body,
rememberMe: this.data.rememberMe,
redirect: {name: 'account'},
success() {
console.log('success ' + this.context);
},
error(res) {
console.log('error ' + this.context);
this.error = res.data;
}
});
}
How does the plugin know to go to /login route or /signup or /register or whatever the route may be?
I know we initialize in the HTTP route in the app.js like this:
Vue.http.options.root = 'https://api-demo.websanova.com/api/v1';
but I'm confused after that point.
Any pointers would be greatly appreciated, thanks so much.
Hi Rob,
I was reading the latest commits and I was wondering why tokenVar
has been removed and has been merged with tokenHeader
.
The new syntax of token
option is cool, but it would be great if we could set two different names:
Say it is needed to send an Authorization: bearer ...
header but the server sends the token with something like: id_token: ...
.
Any thoughts? I can send a PR if you don't mind.
i found that if i cann't import vue-resource and use vue-resource by Vue.use(VueResource)
i'll get error like this this.options.http is undefinded
;
so i think in the readme or doc ,you shoude add someline about this.
If I'm sitting on a route that fetches data from the server, let's say an index view of something (http://localhost:8080/#/companies) and I manually refresh the browser I get an authentication failure. This is because vue-auth has fired a token refresh request, and at the same my app fires a request for the resource. So before the token can be refreshed the regular request has fired, using the old token, which fails authentication.
Perhaps this is a job for vue-resource but how do I get the app to wait until the token refresh completes, and updates localstorage with the new token, before making additional requests?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.