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