Skip to content

Commit

Permalink
prefix tokens for each strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
Pooya Parsa committed Feb 22, 2018
1 parent 71589d0 commit fdb98d2
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 67 deletions.
40 changes: 32 additions & 8 deletions lib/auth/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,27 +301,28 @@ export default class Auth {

this.setState('loggedIn', false)
this.setState('user', null)
this.setToken(null)

this.setToken(this.state.strategy, null)
}

// ---------------------------------------------------------------
// Token helpers
// ---------------------------------------------------------------

getToken (name) {
const _key = '_' + (name || this.options.token.name)
getToken (strategy) {
const _key = this.options.token.prefix + strategy

return this.getUniversal(_key)
}

setToken (token, name) {
const _key = '_' + (name || this.options.token.name)
setToken (strategy, token) {
const _key = this.options.token.prefix + strategy

return this.setUniversal(_key, token)
}

syncToken (name) {
const _key = '_' + (name || this.options.token.name)
syncToken (strategy) {
const _key = this.options.token.prefix + strategy

return this.syncUniversal(_key)
}
Expand Down Expand Up @@ -355,7 +356,10 @@ export default class Auth {
// ---------------------------------------------------------------

request (endpoint, defaults) {
const _endpoint = Object.assign({}, defaults, endpoint)
const _endpoint =
typeof defaults === 'object'
? Object.assign({}, defaults, endpoint)
: endpoint

return this.ctx.app.$axios
.request(_endpoint)
Expand All @@ -375,6 +379,26 @@ export default class Auth {
})
}

requestWith (strategy, endpoint, defaults) {
const token = this.getToken(strategy)

if (isUnset(token)) {
return Promise.reject(new Error('No Token'))
}

const _endpoint = Object.assign({}, defaults, endpoint)

if (!_endpoint.headers) {
_endpoint.headers = {}
}

if (!_endpoint.headers['Authorization']) {
_endpoint.headers['Authorization'] = token
}

return this.request(_endpoint)
}

onError (listener) {
this._errorListeners.push(listener)
}
Expand Down
56 changes: 28 additions & 28 deletions lib/auth/schemes/auth0.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { WebAuth } from 'auth0-js'

const DEFAULTS = {
responseType: 'token id_token',
scope: 'openid profile email'
}

export default class Auth0Scheme {
constructor (auth, options) {
this.auth = auth
this.name = options._name

// -- Assign defaults and normalize options --
this.options = Object.assign({
responseType: 'token id_token',
scope: 'openid profile email'
}, options)
this.options = Object.assign({}, DEFAULTS, options)

if (!this.options.audience) {
this.options.audience = 'https://' + this.options.domain + '/userinfo'
Expand All @@ -20,27 +23,33 @@ export default class Auth0Scheme {

mounted () {
// Sync token
this.auth.syncToken()
this.auth.syncToken(this.name)

// Handle callbacks on page load
this._handleCallback()
}

login (options) {
this.auth0.authorize(Object.assign({
redirectUri: window.location.href.split('#')[0]
}, this.options, options))

return Promise.resolve()
this.auth0.authorize(
Object.assign(
{
redirectUri: window.location.href.split('#')[0]
},
this.options,
options
)
)
}

fetchUser () {
if (!this.auth.token) {
return Promise.resolve()
const token = this.auth.getToken(this.name)

if (!token) {
return
}

return new Promise((resolve, reject) => {
this.auth0.client.userInfo(this.auth.token, (err, user) => {
this.auth0.client.userInfo(token, (err, user) => {
if (err) {
return reject(err)
}
Expand All @@ -55,33 +64,24 @@ export default class Auth0Scheme {
_handleCallback () {
// Callback flow is not supported in server side
if (process.server) {
return Promise.resolve()
return
}

return new Promise((resolve, reject) => {
this.auth0.parseHash((err, authResult) => {
if (err) {
return reject(err)
console.error(err) // eslint-disable-line no-console
return resolve()
}

if (!authResult) {
return Promise.resolve()
return resolve()
}

// Update token
this.auth.setToken(authResult.accessToken)

// Try directly parsing idToken
if (typeof authResult.idToken === 'string') {
try {
const user = JSON.parse(atob(authResult.idToken.split('.')[1]))
this.auth.setUser(user)
return Promise.resolve()
} catch (e) {
// ...
}
}
this.auth.setToken(this.name, authResult.accessToken)

// Fetch user
return this.fetchUser()
})
})
Expand Down
72 changes: 44 additions & 28 deletions lib/auth/schemes/local.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,81 @@
const DEFAULTS = {
tokenRequired: true,
tokenType: 'Bearer',
globalToken: true
}

export default class LocalScheme {
constructor (auth, options) {
this.auth = auth
this.options = Object.assign(
{ tokenRequired: true, tokenType: 'Bearer' },
options
)
this.name = options._name

this.options = Object.assign({}, DEFAULTS, options)
}

_setToken (token) {
// Set Authorization token for all axios requests
this.auth.ctx.app.$axios.setToken(token, this.options.tokenType)
if (this.options.globalToken) {
// Set Authorization token for all axios requests
this.auth.ctx.app.$axios.setToken(token, this.options.tokenType)
}
}

mounted () {
if (this.options.tokenRequired) {
const token = this.auth.syncToken()
const token = this.auth.syncToken(this.name)
this._setToken(token)
}
}

login (endpoint) {
async login (endpoint) {
if (!this.options.endpoints.login) {
return Promise.resolve()
return
}

return this.auth
.request(endpoint, this.options.endpoints.login)
.then(token => {
if (this.options.tokenRequired) {
this.auth.setToken(token)
this._setToken(token)
}
})
.then(() => this.fetchUser())
const result = await this.auth.request(
endpoint,
this.options.endpoints.login
)

if (this.options.tokenRequired) {
const token = this.options.tokenType
? this.options.tokenType + ' ' + result
: result

this.auth.setToken(this.name, token)
this._setToken(token)
}

return this.fetchUser()
}

fetchUser (endpoint) {
async fetchUser (endpoint) {
// User endpoint is disabled.
if (!this.options.endpoints.user) {
this.auth.setUser({})
return Promise.resolve()
return
}

// Token is required but not available
if (this.options.tokenRequired && !this.auth.getToken()) {
return Promise.resolve()
if (this.options.tokenRequired && !this.auth.getToken(this.name)) {
return
}

// Try to fetch user and then set loggedIn to true
return this.auth
.request(endpoint, this.options.endpoints.user)
.then(user => this.auth.setUser(user))
// Try to fetch user and then set
const user = await this.auth.requestWith(
this.name,
endpoint,
this.options.endpoints.user
)
this.auth.setUser(user)
}

logout (endpoint) {
if (!this.options.endpoints.logout) {
return Promise.resolve()
return
}

return this.auth
.request(endpoint, this.options.endpoints.logout)
.requestWith(this.name, endpoint, this.options.endpoints.logout)
.catch(() => {})
}
}
13 changes: 10 additions & 3 deletions lib/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ module.exports = {
// Token

token: {
name: 'token'
prefix: '_token.'
},

// Strategies
Expand All @@ -56,8 +56,15 @@ module.exports = {
method: 'post',
propertyName: 'token'
},
logout: { url: '/api/auth/logout', method: 'post' },
user: { url: '/api/auth/user', method: 'get', propertyName: 'user' }
logout: {
url: '/api/auth/logout',
method: 'post'
},
user: {
url: '/api/auth/user',
method: 'get',
propertyName: 'user'
}
}
}
}
Expand Down

0 comments on commit fdb98d2

Please sign in to comment.