-
Notifications
You must be signed in to change notification settings - Fork 232
Authentication
David Graham edited this page Jun 26, 2018
·
5 revisions
In this section of the tutorial we'll look at Authentication and OAuth2...
The methods we need for Authentication in our app are the following:
-
install : This allows us to simply use
Vue.use(auth)
in ourmain.js
entry to setup authentication. - setDefaults : Setup any defaults we need.
- addInterceptors : We will need to intercept all auth http calls to do things like setting headers, refreshing tokens, and rejecting requests for invalid tokens.
- isInvalidToken : A method for determining whether a response from the server is an invalid token response.
- refreshToken : Handles making calls to the server to get a new token.
- storeToken : Handles saving the new token to our Vuex store.
- retry : A method for retrying the original request from the user (after checking that token is valid or refreshing if needed).
Work-in-progress (check back soon)...
Just like each feature in our app has it's own Vuex store module, we can have a module for our Auth functionality as well:
src/auth/store.js
const defaults = {
isLoggedIn: false,
accessToken: null,
refreshToken: null,
user: {
name: '',
id: ''
}
}
const auth = {
namespaced: true,
state: Object.assign({}, defaults),
mutations: {
update (state, data) {
state = Object.assign({}, defaults, data)
},
clear (state) {
state = Object.assign({}, defaults)
}
},
actions: {
clear ({ state, commit, rootState, dispatch }) {
commit('clear')
},
update ({ state, commit, rootState }, data) {
commit('update', data)
}
}
}
export default auth
Note: I'll clean this code up soon. I added it fairly quickly and should soon have time to update it.
Let's create some helpers to aid us in performing things like http auth requests and logging in/out:
src/auth/helpers.js
import Vue from 'vue'
import { router } from '@/http'
import store from '@/store'
import auth from './'
const LOGIN_URL = '/auth'
// const CLIENT_SECRET = 'ZGVtb2FwcDpkZW1vcGFzcw==' // Base64(client_id:client_secret) "demoapp:demopass"
export default {
URLSearchParams (obj) {
var params = new URLSearchParams()
for (var [key, value] of Object.entries(obj)) params.append(key, value)
return params
},
login (creds, redirect, callback) {
return Vue.http({
method: 'post',
url: LOGIN_URL,
// headers: {
// 'Authorization': 'Basic ' + CLIENT_SECRET,
// 'Content-Type': 'application/x-www-form-urlencoded'
// },
data: this.URLSearchParams({
grant_type: 'password',
client_id: 'demoapp',
client_secret: 'demopass',
username: creds.username,
password: creds.password
})
})
.then((response) => {
auth.storeToken(response)
if (redirect) router.push({ name: redirect })
return response
})
.catch((error) => {
let errorMessage = null
if (error.response) errorMessage = error.response.status
else if (error.request) errorMessage = 'no response from server'
else errorMessage = error.message
return errorMessage
})
},
logout () {
store.dispatch('common/clear')
router.push({ name: 'login' })
},
fakeLogin (creds, redirect) {
return new Promise((resolve, reject) => {
setTimeout(() => {
auth.storeToken({data: { accessToken: '123456789', refreshToken: '77777777' }})
if (redirect) router.push({ name: redirect })
resolve({})
}, 500)
})
},
// Standardizes errors. A place to add logging if needed.
get (url, params = {}) {
const config = {
params: {
username: store.state.auth.user.id,
orgId: store.state.auth.user.orgId
}
}
config.params = Object.assign(config.params, params)
return Vue.auth.get(url, config)
.then((response) => {
return new Promise((resolve) => {
// @TODO check for no response.data.data?
resolve(response.data.data)
})
})
.catch((error) => {
// Standardize errors.
let errorMessage = null
if (error.response) {
errorMessage = error.response.statusText || error.response.status
} else if (error.request) {
errorMessage = 'no response from server'
} else {
errorMessage = error.message
}
return new Promise((resolve, reject) => {
reject(new Error(errorMessage))
})
})
},
put (url, data = {}) {
const config = {}
const defaultData = {
username: store.state.auth.user.id,
orgId: store.state.auth.user.orgId
}
data = Object.assign(defaultData, data)
// console.log(settings.data)
return Vue.auth.put(url, data, config)
.then((response) => {
if (response.data.errors) {
return new Promise((resolve, reject) => {
reject(new Error(response.data.errors[0].user_message))
})
}
return new Promise((resolve) => {
// @TODO check for no response.data.data?
resolve(response.data.data)
})
})
.catch((error) => {
// Standardize errors.
let errorMessage = null
if (error.response) {
errorMessage = error.response.statusText || error.response.status
} else if (error.request) {
errorMessage = 'no response from server'
} else {
errorMessage = error.message
}
return new Promise((resolve, reject) => {
reject(new Error(errorMessage))
})
})
}
}