myPrayerJournal v2 #27
@ -93,6 +93,11 @@ export default {
|
|||||||
},
|
},
|
||||||
hideProgress () {
|
hideProgress () {
|
||||||
this.progress.visible = false
|
this.progress.visible = false
|
||||||
|
},
|
||||||
|
handleLoginEvent (data) {
|
||||||
|
if (!data.loggedIn) {
|
||||||
|
this.showInfo('Logged out successfully')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
provide () {
|
provide () {
|
||||||
|
@ -7,30 +7,31 @@ import AUTH_CONFIG from './auth0-variables'
|
|||||||
import mutations from '@/store/mutation-types'
|
import mutations from '@/store/mutation-types'
|
||||||
/* es-lint-enable*/
|
/* es-lint-enable*/
|
||||||
|
|
||||||
|
// Auth0 web authentication instance to use for our calls
|
||||||
const webAuth = new auth0.WebAuth({
|
const webAuth = new auth0.WebAuth({
|
||||||
domain: AUTH_CONFIG.domain,
|
domain: AUTH_CONFIG.domain,
|
||||||
clientID: AUTH_CONFIG.clientId,
|
clientID: AUTH_CONFIG.clientId,
|
||||||
redirectUri: AUTH_CONFIG.appDomain + AUTH_CONFIG.callbackUrl,
|
redirectUri: AUTH_CONFIG.appDomain + AUTH_CONFIG.callbackUrl,
|
||||||
|
audience: `https://${AUTH_CONFIG.domain}/userinfo`,
|
||||||
responseType: 'token id_token',
|
responseType: 'token id_token',
|
||||||
scope: 'openid profile email'
|
scope: 'openid profile email'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to handle all authentication calls and determinations
|
||||||
|
*/
|
||||||
class AuthService extends EventEmitter {
|
class AuthService extends EventEmitter {
|
||||||
|
|
||||||
id = {
|
// Local storage key for our session data
|
||||||
token: null,
|
AUTH_SESSION = 'auth-session'
|
||||||
expiry: null
|
|
||||||
}
|
|
||||||
access = {
|
|
||||||
token: null,
|
|
||||||
expiry: null
|
|
||||||
}
|
|
||||||
profile = null
|
|
||||||
|
|
||||||
ACCESS_TOKEN = 'access_token'
|
// Received and calculated values for our ssesion (initially loaded from local storage if present)
|
||||||
ID_TOKEN = 'id_token'
|
session = {}
|
||||||
EXPIRES_AT = 'expires_at'
|
|
||||||
USER_PROFILE = 'user_profile'
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.refreshSession()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the user log in flow
|
* Starts the user log in flow
|
||||||
@ -56,31 +57,37 @@ class AuthService extends EventEmitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAuthentication (store) {
|
/**
|
||||||
this.parseHash()
|
* Handle authentication replies from Auth0
|
||||||
.then(authResult => {
|
*
|
||||||
if (authResult && authResult.accessToken && authResult.idToken) {
|
* @param store The Vuex store
|
||||||
this.setSession(authResult)
|
*/
|
||||||
store.commit(mutations.USER_LOGGED_ON, this.profile)
|
async handleAuthentication (store) {
|
||||||
}
|
try {
|
||||||
})
|
const authResult = await this.parseHash()
|
||||||
.catch(err => {
|
if (authResult && authResult.accessToken && authResult.idToken) {
|
||||||
console.log(err)
|
this.setSession(authResult)
|
||||||
alert(`Error: ${err.error}. Check the console for further details.`)
|
store.commit(mutations.USER_LOGGED_ON, this.session.profile)
|
||||||
})
|
}
|
||||||
|
} catch(err) {
|
||||||
|
console.error(err)
|
||||||
|
alert(`Error: ${err.error}. Check the console for further details.`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up the session and commit it to local storage
|
||||||
|
*
|
||||||
|
* @param authResult The authorization result
|
||||||
|
*/
|
||||||
setSession (authResult) {
|
setSession (authResult) {
|
||||||
this.profile = authResult.idTokenPayload
|
this.session.profile = authResult.idTokenPayload
|
||||||
this.id.token = authResult.idToken
|
this.session.id.token = authResult.idToken
|
||||||
this.id.expiry = new Date(this.profile.exp * 1000);
|
this.session.id.expiry = this.session.profile.exp * 1000
|
||||||
this.access.token = authResult.accessToken
|
this.session.access.token = authResult.accessToken
|
||||||
this.access.expiry = new Date(Date.now() + authResult.expiresIn * 1000)
|
this.session.access.expiry = authResult.expiresIn * 1000 + Date.now()
|
||||||
|
|
||||||
localStorage.setItem(this.ACCESS_TOKEN, authResult.accessToken)
|
localStorage.setItem(this.AUTH_SESSION, JSON.stringify(this.session))
|
||||||
localStorage.setItem(this.ID_TOKEN, authResult.idToken)
|
|
||||||
localStorage.setItem(this.EXPIRES_AT, this.id.expiry)
|
|
||||||
localStorage.setItem(this.USER_PROFILE, JSON.stringify(this.profile))
|
|
||||||
|
|
||||||
this.emit('loginEvent', {
|
this.emit('loginEvent', {
|
||||||
loggedIn: true,
|
loggedIn: true,
|
||||||
@ -89,9 +96,32 @@ class AuthService extends EventEmitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh this instance's session from the one in local storage
|
||||||
|
*/
|
||||||
|
refreshSession () {
|
||||||
|
this.session =
|
||||||
|
localStorage.getItem(this.AUTH_SESSION)
|
||||||
|
? JSON.parse(localStorage.getItem(this.AUTH_SESSION))
|
||||||
|
: { profile: {},
|
||||||
|
id: {
|
||||||
|
token: null,
|
||||||
|
expiry: null
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
token: null,
|
||||||
|
expiry: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renew authorzation tokens with Auth0
|
||||||
|
*/
|
||||||
renewTokens () {
|
renewTokens () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (localStorage.getItem(this.ID_TOKEN) !== null) {
|
this.refreshSession()
|
||||||
|
if (this.session.id.token !== null) {
|
||||||
webAuth.checkSession({}, (err, authResult) => {
|
webAuth.checkSession({}, (err, authResult) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err)
|
reject(err)
|
||||||
@ -106,45 +136,58 @@ class AuthService extends EventEmitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
logout (store, router) {
|
/**
|
||||||
|
* Log out of myPrayerJournal
|
||||||
|
*
|
||||||
|
* @param store The Vuex store
|
||||||
|
*/
|
||||||
|
logout (store) {
|
||||||
// Clear access token and ID token from local storage
|
// Clear access token and ID token from local storage
|
||||||
localStorage.removeItem(this.ACCESS_TOKEN)
|
localStorage.removeItem(this.AUTH_SESSION)
|
||||||
localStorage.removeItem(this.ID_TOKEN)
|
this.refreshSession()
|
||||||
localStorage.removeItem(this.EXPIRES_AT)
|
|
||||||
localStorage.removeItem(this.USER_PROFILE)
|
|
||||||
|
|
||||||
this.idToken = null
|
|
||||||
this.idTokenExpiry = null
|
|
||||||
this.profile = null
|
|
||||||
|
|
||||||
store.commit(mutations.USER_LOGGED_OFF)
|
store.commit(mutations.USER_LOGGED_OFF)
|
||||||
|
|
||||||
webAuth.logout({
|
webAuth.logout({
|
||||||
// navigate to the home route
|
returnTo: `${AUTH_CONFIG.appDomain}/`,
|
||||||
returnTo: '/'
|
clientID: AUTH_CONFIG.clientId
|
||||||
})
|
})
|
||||||
this.emit('loginEvent', { loggedIn: false })
|
this.emit('loginEvent', { loggedIn: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check expiration for a token (the way it's stored in the session)
|
||||||
|
*/
|
||||||
|
checkExpiry = (it) => it.token && it.expiry && Date.now() < it.expiry
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is there a user authenticated?
|
||||||
|
*/
|
||||||
isAuthenticated () {
|
isAuthenticated () {
|
||||||
return Date.now() < this.id.Expiry && localStorage.getItem(this.ID_TOKEN)
|
return this.checkExpiry(this.session.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the current access token valid?
|
||||||
|
*/
|
||||||
isAccessTokenValid () {
|
isAccessTokenValid () {
|
||||||
return this.access.token && this.access.expiry && Date.now() < this.access.expiry
|
return this.checkExpiry(this.session.access)
|
||||||
}
|
}
|
||||||
|
|
||||||
getAccessToken () {
|
/**
|
||||||
return new Promise((resolve, reject) => {
|
* Get the user's access token, renewing it if required
|
||||||
if (this.isAccessTokenValid()) {
|
*/
|
||||||
resolve(this.access.token)
|
async getAccessToken () {
|
||||||
} else {
|
if (this.isAccessTokenValid()) {
|
||||||
this.renewTokens()
|
return this.session.access.token
|
||||||
.then(authResult => {
|
} else {
|
||||||
resolve(authResult.accessToken)
|
try {
|
||||||
}, reject)
|
const authResult = await this.renewTokens()
|
||||||
|
return authResult.accessToken
|
||||||
|
} catch (reject) {
|
||||||
|
throw reject
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,30 +1,29 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.md-toolbar-row
|
.md-toolbar-row
|
||||||
md-tabs(md-sync-route).md-primary
|
md-tabs(md-sync-route).md-primary
|
||||||
md-tab(v-if='isAuthenticated'
|
template(v-if='isAuthenticated')
|
||||||
md-label='Journal'
|
md-tab(md-label='Journal'
|
||||||
to='/journal')
|
to='/journal')
|
||||||
md-tab(v-if='isAuthenticated'
|
md-tab(md-label='Active'
|
||||||
md-label='Active'
|
to='/requests/active')
|
||||||
to='/requests/active')
|
md-tab(v-if='hasSnoozed'
|
||||||
md-tab(v-if='hasSnoozed'
|
md-label='Snoozed'
|
||||||
md-label='Snoozed'
|
to='/requests/snoozed')
|
||||||
to='/requests/snoozed')
|
md-tab(md-label='Answered'
|
||||||
md-tab(v-if='isAuthenticated'
|
to='/requests/answered')
|
||||||
md-label='Answered'
|
md-tab(md-label='Log Off'
|
||||||
to='/requests/answered')
|
href='/user/log-off'
|
||||||
md-tab(v-if='isAuthenticated'
|
@click.prevent='logOff()')
|
||||||
md-label='Log Off'
|
md-tab(md-label='Docs'
|
||||||
href='#'
|
href='https://docs.prayerjournal.me'
|
||||||
@click.stop='logOff()')
|
@click.prevent='showHelp()')
|
||||||
md-tab(v-if='!isAuthenticated'
|
template(v-else)
|
||||||
md-label='Log On'
|
md-tab(md-label='Log On'
|
||||||
href='#'
|
href='/user/log-on'
|
||||||
@click.stop='logOn()')
|
@click.prevent='logOn()')
|
||||||
md-tab(md-label='Docs'
|
md-tab(md-label='Docs'
|
||||||
href='https://docs.prayerjournal.me'
|
href='https://docs.prayerjournal.me'
|
||||||
target='_blank'
|
@click.prevent='showHelp()')
|
||||||
@click.stop='')
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -51,6 +50,9 @@ export default {
|
|||||||
},
|
},
|
||||||
logOff () {
|
logOff () {
|
||||||
this.$auth.logout(this.$store, this.$router)
|
this.$auth.logout(this.$store, this.$router)
|
||||||
|
},
|
||||||
|
showHelp () {
|
||||||
|
window.open('https://docs.prayerjournal.me','_blank')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@ article.mpj-main-content(role='main')
|
|||||||
export default {
|
export default {
|
||||||
name: 'log-on',
|
name: 'log-on',
|
||||||
inject: ['progress'],
|
inject: ['progress'],
|
||||||
created () {
|
async created () {
|
||||||
this.progress.$emit('show', 'indeterminate')
|
this.progress.$emit('show', 'indeterminate')
|
||||||
this.$auth.handleAuthentication(this.$store)
|
await this.$auth.handleAuthentication(this.$store)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleLoginEvent (data) {
|
handleLoginEvent (data) {
|
||||||
|
@ -38,7 +38,7 @@ const logError = function (error) {
|
|||||||
const setBearer = async function () {
|
const setBearer = async function () {
|
||||||
try {
|
try {
|
||||||
await auth.getAccessToken()
|
await auth.getAccessToken()
|
||||||
api.setBearer(localStorage.getItem(auth.ID_TOKEN))
|
api.setBearer(auth.session.id.token)
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
if (err === 'Not logged in') {
|
if (err === 'Not logged in') {
|
||||||
console.warn('API request attempted when user was not logged in')
|
console.warn('API request attempted when user was not logged in')
|
||||||
@ -50,7 +50,7 @@ const setBearer = async function () {
|
|||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
user: JSON.parse(localStorage.getItem(auth.USER_PROFILE) || '{}'),
|
user: auth.session.profile,
|
||||||
isAuthenticated: auth.isAuthenticated(),
|
isAuthenticated: auth.isAuthenticated(),
|
||||||
journal: {},
|
journal: {},
|
||||||
isLoadingJournal: false
|
isLoadingJournal: false
|
||||||
@ -98,7 +98,7 @@ export default new Vuex.Store({
|
|||||||
},
|
},
|
||||||
async [actions.CHECK_AUTHENTICATION] ({ commit }) {
|
async [actions.CHECK_AUTHENTICATION] ({ commit }) {
|
||||||
try {
|
try {
|
||||||
await auth.renewTokens()
|
await auth.getAccessToken()
|
||||||
commit(mutations.SET_AUTHENTICATION, auth.isAuthenticated())
|
commit(mutations.SET_AUTHENTICATION, auth.isAuthenticated())
|
||||||
} catch(_) {
|
} catch(_) {
|
||||||
commit(mutations.SET_AUTHENTICATION, false)
|
commit(mutations.SET_AUTHENTICATION, false)
|
||||||
|
Loading…
Reference in New Issue
Block a user