Obtener el token

7/27

Lectura

En el fichero main.js tenemos la instancia principal de Vue. Aqu铆 es donde vamos a trabajar para obtener el token y posteriormente guardarlo en el Store con Vuex.

El proceso que hay que seguir es el siguiente:

  • En el momento en el que la instancia principal de Vue dispare el hook created, hay que llamar a la funci贸n que acabamos de crear para obtener el token
  • Lo segundo es guardar el token en el estado de nuestra aplicaci贸n con la ayuda de Vuex

Existen varias formas de hacer esto. Vamos a aprender a llamar a una acci贸n (dispatch) de Vuex desde la instancia principal de Vue, que aunque no es la mejor forma de hacerlo, a efectos pr谩cticos es muy efectivo.

Creamos una funci贸n llamada init dentro de methods y el 煤nico c贸digo que vamos a poner de momento es un console.log. A continuaci贸n, llamamos a esta funci贸n desde el hook created.
Tu c贸digo se ver铆a as铆:

// main.js

new Vue({
  router,
  store,
  methods: {
    // Nuestra funci贸n
    init () {
      console.log('Hola 馃対')
    }
  },
  // Hook created
  created () {
    this.init()
  },
  render: h => h(App)
}).$mount('#app')

Ve al navegador, abre la consola y f铆jate que se imprima el mensaje.

c.log

Vuex + M贸dulos

En nuestra funci贸n init vamos a llamar a otra funci贸n que estar谩 en Vuex. Vamos a crear dicha funci贸n en el m贸dulo correspondiente.

Para ello, abrimos la carpeta del store de nuestra app /src/store y creamos un nuevo directorio llamado modules. Dentro, creamos un archivo JavaScript: oauth.js. Deber铆as tener algo como esto:

馃搨 /src
鈹斺攢鈹馃搨 /store
   鈹溾攢鈹馃搨 /modules
   鈹  鈹斺攢鈹 oauth.js
   鈹斺攢鈹 index.js

Como buenos profesionales que somos, vamos a separar nuestro store en m贸dulos (aunque, para este proyecto tan peque帽o, no sea necesario), para tenerlo mejor ordenado, y, adem谩s, estaremos usando namespaces, para que nos sea m谩s f谩cil gestionar el estado en caso de que nuestro proyecto crezca, por lo tanto, m谩s escalable.

馃摋 Puedes leer m谩s acerca de los m贸dulos en Vuex en este enlace: https://vuex.vuejs.org/guide/modules.html

Abrimos el reci茅n creado m贸dulo oauth.js y escribimos lo siguiente:

// oauth.js

// Importamos nuestra funci贸n que obtiene el token
// @ es un alias para /src
import * as oauth from '@/api/oauth'

// Creamos el objeto con "Espacio de Nombres"
export default {
  namespaced: true,
  state: {},
  mutations: {},
  actions: {}
}

Estos son los tres bloques que vamos a usar en nuestro m贸dulo:

  • state (el estado de nuestro m贸dulo)
  • mutations (las mutaciones que, valga la redundancia, mutar谩n nuestro estado)
  • actions (las acciones que llamar谩n a nuestras mutaciones).

Necesitamos hacer varios cambios en nuestro c贸digo. Lo primero es crear una variable que guarde el token, que por defecto tendr谩 null como valor. Lo creamos de la siguiente forma:

state: {
  accessToken: null
},

Lo segundo es crear la funci贸n que cambie (mute) el estado que le estemos pasando. Esta funci贸n recibe 2 par谩metros como argumentos: el estado de nuestro m贸dulo y el payload (o valor que queremos guardar). Con esto podemos indicarle que cambie el accessToken por el valor que le pasemos en el payload. Cuando lo queramos borrar, le pasamos null.

mutations: {
  SET_ACCESS_TOKEN (state, payload) {
    state.accessToken = payload
  }
}

Ya tienes la variable y la funci贸n que cambia el valor de dicha variable. Veamos ahora c贸mo se obtiene el token y c贸mo se guarda en el estado de nuestra aplicaci贸n. Entra en juego el bloque de actions:

actions: {
  
  // Creamos la funci贸n getToken, que recibe como par谩metro el objeto `context`
  // Gracias a la asignaci贸n de desestructuraci贸n de JavaScript, recogemos `commit` como argumento
  getToken ({ commit }) {
    // Pasos:
    //  1 - Hacer llamada HTTP para obtener el token
    //  2 - Si va OK, guardar el token en 'accessToken'. Continuar el flujo normal
    //  3 - Si hay errror, limpiar el token de 'accessToken', mostrar log del error
    
    // Paso 1
    oauth.getToken()
      .then(({ data }) => {
      	// Paso 2: Guardamos el valor del token llamando a nuestra mutaci贸n
      	commit('SET_ACCESS_TOKEN', data.access_token)
      })
      .catch((err) => {
      	// Paso 3: En caso de error limpiamos el token
        commit('SET_ACCESS_TOKEN', null)
        console.log('Error OAuth: ', err)
      })
      .finally(() => {
      	// Por ahora no hacemos nada m谩s aqu铆
      	console.log('Done!')
      })
  }
}

馃摋 Puedes ver la documentaci贸n relativa al constructor de Vuex aqu铆: https://vuex.vuejs.org/api/

Ya tenemos nuestra funcionalidad para obtener el token creada. Ahora solo queda llamarla desde la instancia principal de Vue y probar que todo funciona.

Las acciones en Vuex se llaman a trav茅s de dispatch. Esto es lo que vamos a hacer desde nuestro m茅todo init en el archivo main.js.

// main.js

methods: {
  init () {
    store.dispatch('oauth/getToken', null, { root: true })
  }
}

Si abres la consola de tu navegador, ver谩s que hay un error:

馃毇 [vuex] unknown action type: oauth/getToken

Eso quiere decir que Vuex no sabe de que le estamos hablando. Es normal, ya que no hemos dado de alta nuestro m贸dulo de OAuth en Vuex. 隆Vamos a ello!

Tenemos que editar el archivo /store/index.js:

Antes ten铆amos esto:

// store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules: {}
})

Lo que vamos a hacer ahora es borrar todo, excepto el bloque de modules, a la vez que importamos el m贸dulo de oauth.js y lo damos de alta en el Store.

// store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

// Importar oauth
import oauth from './modules/oauth'

Vue.use(Vuex)

export default new Vuex.Store({
  // Aquu铆 registramos todos los m贸dulos
  modules: {
    oauth
  }
})

Si cargas la aplicaci贸n y abres la consola del navegador, deber铆as ver el mensaje que pusiste en el finally(), en este caso ver铆as el log del Hola y del Done!.
Si revisas la pesta帽a de 鈥淣etwork鈥 o 鈥淩ed鈥 en las herramientas para desarrolladores de tu navegador, deber铆as ver algo como esto:

network-tab

Vemos que la petici贸n se est谩 haciendo y nos devuelve los datos. Para comprobar si est谩n guard谩ndose o no, tienes que ir a las DevTools de Vue y revisar la pesta帽a de Vuex.

Si no conoces las Vue DevTools, una extensi贸n para el navegador, 隆inst谩lalas ahora mismo!: https://github.com/vuejs/vue-devtools

dev-tools

En la parte izquierda se ve un registro (log) de las mutaciones que han ocurrido hasta el momento, y a la izquierda se ve el estado actual del Store o estado de nuestra app.

隆Perfecto! Hemos obtenido el token y lo hemos guardado. Est谩 disponible desde cualquier parte de la aplicaci贸n. Ahora podr谩s usarlo cuando lo necesites.

Aportes 25

Preguntas 6

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Reg铆strate o inicia sesi贸n para participar.

Hola.
Me sale el siguiente error. No se que podr谩 ser.

Hasta ahora todo bien, lo que si es que me gustar铆a que se explicara m谩s a profundidad lo de los modulos de Vuex ya que ni en el curso b谩sico ni el profesional ni el avanzado con firebase lo explicaron.

A煤n as铆, aqu铆 dejo lo que entiendo de las rutas con namespace:

El namespace es para que puedas llamar a los actions usando una ruta entera y no solo a la funci贸n, es 煤til porque as铆 cuando veas que en el c贸digo se llama a tal acci贸n sabr谩s a qu茅 m贸dulo pertenece, si no usas namespace es como tener un arsenal de actions dispnibles tal como los tendr铆as en Vuex y todas desordenadas

A煤n as铆 me gustar铆a que me explicaran bien la sintaxis de import * as oauth from 鈥楡/api/oauth鈥 驴Cu谩l ser铆a la diferencia si simplemente pongo import oauth from 鈥楡/api/oauth鈥?

me genera el token pero en consola me aparece:

[vuex] unknown local mutation type: SET_ACCESS_TOKEN, global type: oauth/SET_ACCESS_TOKEN

Si alguien tiene problemas con Vuex y en la consola les sale sl siguiente error:

[vuex] unknown action type: oauth/getToken

Es porque, al menos para mi me funciona si escribo la parte de 鈥榦auth鈥 as铆 que solo escribe el nombre del metodo getToken y funcionar谩.

Saludos!

Una consulta, cada vez que se recarga la p谩gina se est谩 pidiendo el token, s茅 que store s贸lo guarda en memoria y s茅 que se podr铆a usar el localstorage para persistir el token hasta que caduque, mi pregunta es c贸mo combinar ambas cosas ya que me gusta mucho usar vuex. Saludos.

Es bueno crear una funci贸n dentro de cada m贸dulo del Store llamada initialState, esto es 煤til para reiniciar el estado del store, es especialmente 煤til cuando se tienen muchos campos en el state

const initialState = () => ({
  accessToken: null
})

Podemos tener algo como esto:

export default {
  namespaced: true,
  state: initialState(),
  mutations: {
    RESET (state) {
      state = initialState()
    }
  },
  actions: {}
}

Justo hace una semana estaba pensando en: 鈥渆star铆a bueno encontrar un curso donde modularicen el vuex para aprender a hacerlo鈥.
EXCELENTE! Gracias

Ten铆a algun tiempo sin reiniciar mi Ubuntu y no quer铆a funcionar. Reinicias y trabaja perfectamente.

Ta bueno el curso!

Excelente curso. Tengo una duda. Estoy intentando refresh el servidor con crtl + c para que no me de error de babel-lint cuando hago los cambios. Tuve que reiniciar el pc para poder ver la pagina online nuevamente y los cambios. No entiendo porque con crt+c no es suficiente para actualizar.

Ese lint鈥 un espacio, un tab, te marca error鈥 te obliga repararlo, menos mal que no es mi ajeiv, lo mando alv.

Buenas!
No se pierdan este v铆deo que est谩 genial la explicaci贸n:
https://vuex.vuejs.org/#what-is-vuex

Tengo un 鈥減roblema鈥 que realmente no se si sea eso. Al momento de revisar en Vue DevTools los commits hechos por Vuex, no veo reflejados los cambios en la consola.

C贸digo
modules\oauth.js

import * as oauth from '@/api/oauth'

export default {
  namespaced: true,
  state: {
    accessToken: null
  },
  mutations: {
    SET_ACCESS_TOKEN(state, payload) {
      state.accessToken = payload
    }
  },
  actions: {
    getToken({ commit }) {
      oauth
        .getToken()
        .then(res => {
          commit('SET_ACCESS_TOKEN', res.access_token)
        })
        .catch(err => {
          commit('SET_ACCESS_TOKEN', null)
          console.log(`Error OAuth: ${err}`)
        })
        .finally(() => {
          console.log('Done!')
        })
    }
  }
}

main.js

new Vue({
  router,
  store,
  created() {
    this.init()
  },
  methods: {
    init() {
      store.dispatch('oauth/getToken', null, { root: true })
    }
  },
  render: h => h(App)
}).$mount('#app')

Hola me sale este error cuando se hace el dispatch

{"error":"unauthorized","error_description":"An Authentication object was not found in the SecurityContext"}

Recomendaciones para evitar errores en esta secci贸n:
PROBAR EN POSTMAN el procedimiento citado en la secci贸n #6 para traer el token y descartar que el prosible fallo est茅 en dicha secci贸n.

Hola! Hay alguna forma de hacerlo como un backend for frontend? me preocupa que desde el cliente puedan llegarle a las credenciales (clientId y secretKey). Con las DevTools uno puede ver los par谩metos que se env铆an.

Existen varias formas de hacer esto. Vamos a aprender a llamar a una acci贸n (dispatch) de Vuex desde la instancia principal de Vue, que aunque no es la mejor forma de hacerlo, a efectos pr谩cticos es muy efectivo. 驴Cual seria la mejor manera de hacerlo? . Me interesa las buenas practicas 馃憖

no entiendo casi nada de tokens como ven soy mas front end que backen es algo muy nuevo para mi seria vacano con videos

store de modules/oauth.js :

import { getToken } from '@/api/oauth'
// mutations
export const SET_ACCESS_TOKEN = 'setAccessToken'
// actions
export const GET_TOKEN = 'getToken'

const state = {
  accessToken: null
}

const mutations = {
  [SET_ACCESS_TOKEN] (state, payload) {
    state.accessToken = payload
  }
}

const actions = {
  async [GET_TOKEN] ({ commit }) {
    try {
      const { data } = await getToken()
      console.log(data)
    } catch (e) {
      commit(SET_ACCESS_TOKEN, null)
      throw new Error('Error OAuth', e)
    } finally {
      console.info('Done!')
    }
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

el usode {commit} no entiendo , en pinia cual serai su equivalente o no hace falta

Hice una aplicaci贸n usando firebase y los datos de usuario los guard茅 en una variable del store de vuex. Cuando necesitaba cambiarla solo hac铆a store.state.currentUser=鈥渁lgo鈥 sin usar mutations y actions. Entiendo el concepto, pero qu茅 desventaja tiene si no las uso y solo modifico directamente el store de vuex? Aclaro que funciona sin problemas toda la aplicaci贸n.

NOTA IMPORTANTE
Para los que les sale este error:

[vuex] unknown local mutation type: SET_ACCESS_TOKEN, global type: oauth/SET_ACCESS_TOKEN

Deben cambiar en /store/modules/oauth.js la palabra mutation por mutations

Me aparece el siguiente error en consola, a pesar de que en postman s铆 me devuelve el valor del token, en la app me aparece vac铆o el objeto:

[Vue warn]: Error in created hook: 鈥淭ypeError: api_oauth__WEBPACK_IMPORTED_MODULE_1_.getToken is not a function鈥

(found in <Root>)
warn @ vue.runtime.esm.js?2b0e:619
logError @ vue.runtime.esm.js?2b0e:1884
globalHandleError @ vue.runtime.esm.js?2b0e:1879
handleError @ vue.runtime.esm.js?2b0e:1839
invokeWithErrorHandling @ vue.runtime.esm.js?2b0e:1862
callHook @ vue.runtime.esm.js?2b0e:4219
Vue.init @ vue.runtime.esm.js?2b0e:5008
Vue @ vue.runtime.esm.js?2b0e:5085
eval @ main.js?56d7:19
./src/main.js @ app.js:1160
webpack_require @ app.js:854
fn @ app.js:151
1 @ app.js:1269
webpack_require @ app.js:854
checkDeferredModules @ app.js:46
(an贸nimo) @ app.js:994
(an贸nimo) @ app.js:997
vue.runtime.esm.js?2b0e:1888 TypeError: api_oauth__WEBPACK_IMPORTED_MODULE_1
.getToken is not a function

Para los que est谩n usando Vue3, este es el dev tools que tienen que instalar:
https://chrome.google.com/webstore/detail/vuejs-devtools/ljjemllljcmogpfapbkkighbhhppjdbg
A煤n no hay soporte para vuex pero pueden agregar este logger al store para ver que es lo que est谩 pasando:

import { createStore, createLogger } from 'vuex'
.
.
.
export default createStore({
  state,
  getters,
  actions,
  mutations,
  plugins: process.env.NODE_ENV !== 'production'
    ? [createLogger()]
    : []
})

Hola.
A alguien le paso que le aparecio este error?:

[vuex] unknown local mutation type: SET_ACCESS_TOKEN, global type: oauth/SET_ACCESS_TOKEN

Porque no se como solucionarlo y no puedo continuar con el curso.
El error sale en la consola.
Gracias.

Lectura n煤mero siete: creo que mi ser a empezado a generar un fuerte odio hac铆a lint, espero que solo sea temporal.

PSDT: npm run lint ha sido mi salvador en este camino.