Continue auth upgrades
Something's still not quite right...
This commit is contained in:
parent
d95e2bf483
commit
a392c8f22a
@ -72,7 +72,8 @@ module Configure =
|
|||||||
fun opts ->
|
fun opts ->
|
||||||
let jwtCfg = cfg.GetSection "Auth0"
|
let jwtCfg = cfg.GetSection "Auth0"
|
||||||
opts.Authority <- sprintf "https://%s/" jwtCfg.["Domain"]
|
opts.Authority <- sprintf "https://%s/" jwtCfg.["Domain"]
|
||||||
opts.Audience <- jwtCfg.["Id"])
|
opts.Audience <- jwtCfg.["Id"]
|
||||||
|
)
|
||||||
|> ignore
|
|> ignore
|
||||||
sc.AddSingleton<IJsonSerializer> (NewtonsoftJsonSerializer jsonSettings)
|
sc.AddSingleton<IJsonSerializer> (NewtonsoftJsonSerializer jsonSettings)
|
||||||
|> ignore
|
|> ignore
|
||||||
|
@ -35,6 +35,7 @@ import Vue from 'vue'
|
|||||||
|
|
||||||
import Navigation from '@/components/common/Navigation'
|
import Navigation from '@/components/common/Navigation'
|
||||||
|
|
||||||
|
import actions from '@/store/action-types'
|
||||||
import { version } from '../package.json'
|
import { version } from '../package.json'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -57,21 +58,12 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created () {
|
async mounted () {
|
||||||
try {
|
|
||||||
await this.$auth.renewTokens()
|
|
||||||
} catch (e) {
|
|
||||||
if (e !== 'Not logged in') {
|
|
||||||
// eslint-disable-next-line
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
this.progress.events.$on('show', this.showProgress)
|
this.progress.events.$on('show', this.showProgress)
|
||||||
this.progress.events.$on('done', this.hideProgress)
|
this.progress.events.$on('done', this.hideProgress)
|
||||||
this.snackbar.events.$on('info', this.showInfo)
|
this.snackbar.events.$on('info', this.showInfo)
|
||||||
this.snackbar.events.$on('error', this.showError)
|
this.snackbar.events.$on('error', this.showError)
|
||||||
|
await this.$store.dispatch(actions.CHECK_AUTHENTICATION)
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
version () {
|
version () {
|
||||||
|
@ -15,12 +15,12 @@ export default {
|
|||||||
* Set the bearer token for all future requests
|
* Set the bearer token for all future requests
|
||||||
* @param {string} token The token to use to identify the user to the server
|
* @param {string} token The token to use to identify the user to the server
|
||||||
*/
|
*/
|
||||||
setBearer: token => { http.defaults.headers.common['authorization'] = `Bearer ${token}` },
|
setBearer: token => { http.defaults.headers.common['Authorization'] = `Bearer ${token}` },
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the bearer token
|
* Remove the bearer token
|
||||||
*/
|
*/
|
||||||
removeBearer: () => delete http.defaults.headers.common['authorization'],
|
removeBearer: () => delete http.defaults.headers.common['Authorization'],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a note for a prayer request
|
* Add a note for a prayer request
|
||||||
|
@ -11,15 +11,10 @@ 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'
|
||||||
})
|
})
|
||||||
|
|
||||||
const ACCESS_TOKEN = 'access_token'
|
|
||||||
const ID_TOKEN = 'id_token'
|
|
||||||
const EXPIRES_AT = 'expires_at'
|
|
||||||
|
|
||||||
class AuthService extends EventEmitter {
|
class AuthService extends EventEmitter {
|
||||||
|
|
||||||
id = {
|
id = {
|
||||||
@ -32,14 +27,10 @@ class AuthService extends EventEmitter {
|
|||||||
}
|
}
|
||||||
profile = null
|
profile = null
|
||||||
|
|
||||||
auth0 = new auth0.WebAuth({
|
ACCESS_TOKEN = 'access_token'
|
||||||
domain: AUTH_CONFIG.domain,
|
ID_TOKEN = 'id_token'
|
||||||
clientID: AUTH_CONFIG.clientId,
|
EXPIRES_AT = 'expires_at'
|
||||||
redirectUri: AUTH_CONFIG.appDomain + AUTH_CONFIG.callbackUrl,
|
USER_PROFILE = 'user_profile'
|
||||||
audience: `https://${AUTH_CONFIG.domain}/userinfo`,
|
|
||||||
responseType: 'token id_token',
|
|
||||||
scope: 'openid profile email'
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the user log in flow
|
* Starts the user log in flow
|
||||||
@ -55,7 +46,7 @@ class AuthService extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
parseHash () {
|
parseHash () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.auth0.parseHash((err, authResult) => {
|
webAuth.parseHash((err, authResult) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err)
|
reject(err)
|
||||||
} else {
|
} else {
|
||||||
@ -65,32 +56,12 @@ class AuthService extends EventEmitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Promisified userInfo function
|
|
||||||
*
|
|
||||||
* @param token The auth token from the login result
|
|
||||||
*/
|
|
||||||
userInfo (token) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.auth0.client.userInfo(token, (err, user) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err)
|
|
||||||
} else {
|
|
||||||
resolve(user)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleAuthentication (store) {
|
handleAuthentication (store) {
|
||||||
this.parseHash()
|
this.parseHash()
|
||||||
.then(authResult => {
|
.then(authResult => {
|
||||||
if (authResult && authResult.accessToken && authResult.idToken) {
|
if (authResult && authResult.accessToken && authResult.idToken) {
|
||||||
this.setSession(authResult)
|
this.setSession(authResult)
|
||||||
this.userInfo(authResult.accessToken)
|
store.commit(mutations.USER_LOGGED_ON, this.profile)
|
||||||
.then(user => {
|
|
||||||
store.commit(mutations.USER_LOGGED_ON, user)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
@ -100,15 +71,16 @@ class AuthService extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setSession (authResult) {
|
setSession (authResult) {
|
||||||
|
this.profile = authResult.idTokenPayload
|
||||||
this.id.token = authResult.idToken
|
this.id.token = authResult.idToken
|
||||||
this.id.expiry = new Date(this.profile.exp * 1000);
|
this.id.expiry = new Date(this.profile.exp * 1000);
|
||||||
this.profile = authResult.idTokenPayload
|
|
||||||
this.access.token = authResult.accessToken
|
this.access.token = authResult.accessToken
|
||||||
this.access.expiry = new Date(Date.now() + authResult.expiresIn * 1000)
|
this.access.expiry = new Date(Date.now() + authResult.expiresIn * 1000)
|
||||||
|
|
||||||
localStorage.setItem(ACCESS_TOKEN, authResult.accessToken)
|
localStorage.setItem(this.ACCESS_TOKEN, authResult.accessToken)
|
||||||
localStorage.setItem(ID_TOKEN, authResult.idToken)
|
localStorage.setItem(this.ID_TOKEN, authResult.idToken)
|
||||||
localStorage.setItem(EXPIRES_AT, this.id.expiry)
|
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,
|
||||||
@ -119,7 +91,7 @@ class AuthService extends EventEmitter {
|
|||||||
|
|
||||||
renewTokens () {
|
renewTokens () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (localStorage.getItem(ID_TOKEN)) {
|
if (localStorage.getItem(this.ID_TOKEN) !== null) {
|
||||||
webAuth.checkSession({}, (err, authResult) => {
|
webAuth.checkSession({}, (err, authResult) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err)
|
reject(err)
|
||||||
@ -136,9 +108,10 @@ class AuthService extends EventEmitter {
|
|||||||
|
|
||||||
logout (store, router) {
|
logout (store, router) {
|
||||||
// Clear access token and ID token from local storage
|
// Clear access token and ID token from local storage
|
||||||
localStorage.removeItem(ACCESS_TOKEN)
|
localStorage.removeItem(this.ACCESS_TOKEN)
|
||||||
localStorage.removeItem(ID_TOKEN)
|
localStorage.removeItem(this.ID_TOKEN)
|
||||||
localStorage.removeItem(EXPIRES_AT)
|
localStorage.removeItem(this.EXPIRES_AT)
|
||||||
|
localStorage.removeItem(this.USER_PROFILE)
|
||||||
|
|
||||||
this.idToken = null
|
this.idToken = null
|
||||||
this.idTokenExpiry = null
|
this.idTokenExpiry = null
|
||||||
@ -154,7 +127,7 @@ class AuthService extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAuthenticated () {
|
isAuthenticated () {
|
||||||
return Date().now() < this.id.Expiry && localStorage.getItem(ID_TOKEN)
|
return Date.now() < this.id.Expiry && localStorage.getItem(this.ID_TOKEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
isAccessTokenValid () {
|
isAccessTokenValid () {
|
||||||
|
@ -38,15 +38,12 @@ export default {
|
|||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isAuthenticated () {
|
|
||||||
return this.$auth.isAuthenticated()
|
|
||||||
},
|
|
||||||
hasSnoozed () {
|
hasSnoozed () {
|
||||||
return this.isAuthenticated &&
|
return this.isAuthenticated &&
|
||||||
Array.isArray(this.journal) &&
|
Array.isArray(this.journal) &&
|
||||||
this.journal.filter(req => req.snoozedUntil > Date.now()).length > 0
|
this.journal.filter(req => req.snoozedUntil > Date.now()).length > 0
|
||||||
},
|
},
|
||||||
...mapState([ 'journal' ])
|
...mapState([ 'isAuthenticated', 'journal' ])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
logOn () {
|
logOn () {
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
export default {
|
export default {
|
||||||
/** Action to add a prayer request (pass request text) */
|
/** Action to add a prayer request (pass request text) */
|
||||||
ADD_REQUEST: 'add-request',
|
ADD_REQUEST: 'add-request',
|
||||||
|
/** Action to check if a user is authenticated, refreshing the session first if it exists */
|
||||||
|
CHECK_AUTHENTICATION: 'check-authentication',
|
||||||
/** Action to load the user's prayer journal */
|
/** Action to load the user's prayer journal */
|
||||||
LOAD_JOURNAL: 'load-journal',
|
LOAD_JOURNAL: 'load-journal',
|
||||||
/** Action to update a request */
|
/** Action to update a request */
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
|
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import AuthService from '@/auth/AuthService'
|
import auth from '@/auth/AuthService'
|
||||||
|
|
||||||
import mutations from './mutation-types'
|
import mutations from './mutation-types'
|
||||||
import actions from './action-types'
|
import actions from './action-types'
|
||||||
@ -13,37 +13,45 @@ import actions from './action-types'
|
|||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
const auth0 = new AuthService()
|
|
||||||
|
|
||||||
const logError = function (error) {
|
const logError = function (error) {
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
// The request was made and the server responded with a status code
|
// The request was made and the server responded with a status code
|
||||||
// that falls out of the range of 2xx
|
// that falls out of the range of 2xx
|
||||||
console.log(error.response.data)
|
console.error(error.response.data)
|
||||||
console.log(error.response.status)
|
console.error(error.response.status)
|
||||||
console.log(error.response.headers)
|
console.error(error.response.headers)
|
||||||
} else if (error.request) {
|
} else if (error.request) {
|
||||||
// The request was made but no response was received
|
// The request was made but no response was received
|
||||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||||
// http.ClientRequest in node.js
|
// http.ClientRequest in node.js
|
||||||
console.log(error.request)
|
console.error(error.request)
|
||||||
} else {
|
} else {
|
||||||
// Something happened in setting up the request that triggered an Error
|
// Something happened in setting up the request that triggered an Error
|
||||||
console.log('Error', error.message)
|
console.error('Error', error.message)
|
||||||
|
}
|
||||||
|
console.error(`config: ${error.config}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the "Bearer" authorization header with the current access token
|
||||||
|
*/
|
||||||
|
const setBearer = async function () {
|
||||||
|
try {
|
||||||
|
await auth.getAccessToken()
|
||||||
|
api.setBearer(localStorage.getItem(auth.ID_TOKEN))
|
||||||
|
} catch(err) {
|
||||||
|
if (err === 'Not logged in') {
|
||||||
|
console.warn('API request attempted when user was not logged in')
|
||||||
|
} else {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.log(error.config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
user: JSON.parse(localStorage.getItem('user_profile') || '{}'),
|
user: JSON.parse(localStorage.getItem(auth.USER_PROFILE) || '{}'),
|
||||||
isAuthenticated: (() => {
|
isAuthenticated: auth.isAuthenticated(),
|
||||||
auth0.scheduleRenewal()
|
|
||||||
if (auth0.isAuthenticated()) {
|
|
||||||
api.setBearer(localStorage.getItem('id_token'))
|
|
||||||
}
|
|
||||||
return auth0.isAuthenticated()
|
|
||||||
})(),
|
|
||||||
journal: {},
|
journal: {},
|
||||||
isLoadingJournal: false
|
isLoadingJournal: false
|
||||||
},
|
},
|
||||||
@ -62,15 +70,16 @@ export default new Vuex.Store({
|
|||||||
if (request.lastStatus !== 'Answered') jrnl.push(request)
|
if (request.lastStatus !== 'Answered') jrnl.push(request)
|
||||||
state.journal = jrnl
|
state.journal = jrnl
|
||||||
},
|
},
|
||||||
|
[mutations.SET_AUTHENTICATION] (state, value) {
|
||||||
|
state.isAuthenticated = value
|
||||||
|
},
|
||||||
[mutations.USER_LOGGED_OFF] (state) {
|
[mutations.USER_LOGGED_OFF] (state) {
|
||||||
state.user = {}
|
state.user = {}
|
||||||
api.removeBearer()
|
api.removeBearer()
|
||||||
state.isAuthenticated = false
|
state.isAuthenticated = false
|
||||||
},
|
},
|
||||||
[mutations.USER_LOGGED_ON] (state, user) {
|
[mutations.USER_LOGGED_ON] (state, user) {
|
||||||
localStorage.setItem('user_profile', JSON.stringify(user))
|
|
||||||
state.user = user
|
state.user = user
|
||||||
api.setBearer(localStorage.getItem('id_token'))
|
|
||||||
state.isAuthenticated = true
|
state.isAuthenticated = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -78,6 +87,7 @@ export default new Vuex.Store({
|
|||||||
async [actions.ADD_REQUEST] ({ commit }, { progress, requestText, recurType, recurCount }) {
|
async [actions.ADD_REQUEST] ({ commit }, { progress, requestText, recurType, recurCount }) {
|
||||||
progress.$emit('show', 'indeterminate')
|
progress.$emit('show', 'indeterminate')
|
||||||
try {
|
try {
|
||||||
|
await setBearer()
|
||||||
const newRequest = await api.addRequest(requestText, recurType, recurCount)
|
const newRequest = await api.addRequest(requestText, recurType, recurCount)
|
||||||
commit(mutations.REQUEST_ADDED, newRequest.data)
|
commit(mutations.REQUEST_ADDED, newRequest.data)
|
||||||
progress.$emit('done')
|
progress.$emit('done')
|
||||||
@ -86,11 +96,19 @@ export default new Vuex.Store({
|
|||||||
progress.$emit('done')
|
progress.$emit('done')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async [actions.CHECK_AUTHENTICATION] ({ commit }) {
|
||||||
|
try {
|
||||||
|
await auth.renewTokens()
|
||||||
|
commit(mutations.SET_AUTHENTICATION, auth.isAuthenticated())
|
||||||
|
} catch(_) {
|
||||||
|
commit(mutations.SET_AUTHENTICATION, false)
|
||||||
|
}
|
||||||
|
},
|
||||||
async [actions.LOAD_JOURNAL] ({ commit }, progress) {
|
async [actions.LOAD_JOURNAL] ({ commit }, progress) {
|
||||||
commit(mutations.LOADED_JOURNAL, {})
|
commit(mutations.LOADED_JOURNAL, {})
|
||||||
progress.$emit('show', 'query')
|
progress.$emit('show', 'query')
|
||||||
commit(mutations.LOADING_JOURNAL, true)
|
commit(mutations.LOADING_JOURNAL, true)
|
||||||
api.setBearer(localStorage.getItem('id_token'))
|
await setBearer()
|
||||||
try {
|
try {
|
||||||
const jrnl = await api.journal()
|
const jrnl = await api.journal()
|
||||||
commit(mutations.LOADED_JOURNAL, jrnl.data)
|
commit(mutations.LOADED_JOURNAL, jrnl.data)
|
||||||
@ -105,6 +123,7 @@ export default new Vuex.Store({
|
|||||||
async [actions.UPDATE_REQUEST] ({ commit, state }, { progress, requestId, status, updateText, recurType, recurCount }) {
|
async [actions.UPDATE_REQUEST] ({ commit, state }, { progress, requestId, status, updateText, recurType, recurCount }) {
|
||||||
progress.$emit('show', 'indeterminate')
|
progress.$emit('show', 'indeterminate')
|
||||||
try {
|
try {
|
||||||
|
await setBearer()
|
||||||
let oldReq = (state.journal.filter(req => req.requestId === requestId) || [])[0] || {}
|
let oldReq = (state.journal.filter(req => req.requestId === requestId) || [])[0] || {}
|
||||||
if (!(status === 'Prayed' && updateText === '')) {
|
if (!(status === 'Prayed' && updateText === '')) {
|
||||||
if (status !== 'Answered' && (oldReq.recurType !== recurType || oldReq.recurCount !== recurCount)) {
|
if (status !== 'Answered' && (oldReq.recurType !== recurType || oldReq.recurCount !== recurCount)) {
|
||||||
@ -125,6 +144,7 @@ export default new Vuex.Store({
|
|||||||
async [actions.SHOW_REQUEST_NOW] ({ commit }, { progress, requestId, showAfter }) {
|
async [actions.SHOW_REQUEST_NOW] ({ commit }, { progress, requestId, showAfter }) {
|
||||||
progress.$emit('show', 'indeterminate')
|
progress.$emit('show', 'indeterminate')
|
||||||
try {
|
try {
|
||||||
|
await setBearer()
|
||||||
await api.showRequest(requestId, showAfter)
|
await api.showRequest(requestId, showAfter)
|
||||||
const request = await api.getRequest(requestId)
|
const request = await api.getRequest(requestId)
|
||||||
commit(mutations.REQUEST_UPDATED, request.data)
|
commit(mutations.REQUEST_UPDATED, request.data)
|
||||||
@ -137,6 +157,7 @@ export default new Vuex.Store({
|
|||||||
async [actions.SNOOZE_REQUEST] ({ commit }, { progress, requestId, until }) {
|
async [actions.SNOOZE_REQUEST] ({ commit }, { progress, requestId, until }) {
|
||||||
progress.$emit('show', 'indeterminate')
|
progress.$emit('show', 'indeterminate')
|
||||||
try {
|
try {
|
||||||
|
await setBearer()
|
||||||
await api.snoozeRequest(requestId, until)
|
await api.snoozeRequest(requestId, until)
|
||||||
const request = await api.getRequest(requestId)
|
const request = await api.getRequest(requestId)
|
||||||
commit(mutations.REQUEST_UPDATED, request.data)
|
commit(mutations.REQUEST_UPDATED, request.data)
|
||||||
|
@ -9,6 +9,8 @@ export default {
|
|||||||
REQUEST_ADDED: 'request-added',
|
REQUEST_ADDED: 'request-added',
|
||||||
/** Mutation to replace a prayer request at the top of the current journal */
|
/** Mutation to replace a prayer request at the top of the current journal */
|
||||||
REQUEST_UPDATED: 'request-updated',
|
REQUEST_UPDATED: 'request-updated',
|
||||||
|
/** Mutation for setting the authentication state */
|
||||||
|
SET_AUTHENTICATION: 'set-authentication',
|
||||||
/** Mutation for logging a user off */
|
/** Mutation for logging a user off */
|
||||||
USER_LOGGED_OFF: 'user-logged-off',
|
USER_LOGGED_OFF: 'user-logged-off',
|
||||||
/** Mutation for logging a user on (pass user) */
|
/** Mutation for logging a user on (pass user) */
|
||||||
|
Loading…
Reference in New Issue
Block a user