Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lose user data in fetchUser CustomStrategy #884

Closed
diegodelajara opened this issue Nov 18, 2020 · 2 comments
Closed

Lose user data in fetchUser CustomStrategy #884

diegodelajara opened this issue Nov 18, 2020 · 2 comments

Comments

@diegodelajara
Copy link

diegodelajara commented Nov 18, 2020

Hi everyone!
I have my own custom strategy to get token, and all is good, but when a refresh page I lose user data and fetchUser does not works. It doesn´t send the params to API to get again the user data.
the workflow is next:
1- send params to token api and get token
2- send params to login API to get the user

//nuxt.config.js

customStrategy: {
        _scheme: '~/schemes/customScheme',
        endpoints: {
          login: {
            url: '/api/v1/token',
            method: 'post',
            propertyName: 'token',
            headers: {'x-channel-id': 1}
          },
          user: {
            url: '/api/v1/login',
            method: 'post',
            propertyName: false,
            headers: {'x-channel-id': 1}
          },
          logout: null
        }
      }

customScheme.js

import LocalScheme from '@nuxtjs/auth/lib/schemes/local'

export default class CustomScheme extends LocalScheme {

  _setToken (token) {
    if (this.options.globalToken) {
      // Set Authorization token for all axios requests
      this.$auth.ctx.app.$axios.setHeader(this.options.tokenName, token)
    }
  }
  
  _clearToken () {
    if (this.options.globalToken) {
      // Clear Authorization token for all axios requests
      this.$auth.ctx.app.$axios.setHeader(this.options.tokenName, false)
    }
  }
  
  mounted () {
    if (this.options.tokenRequired) {
      const token = this.$auth.syncToken(this.name)
      this._setToken(token)
    }
    return this.$auth.fetchUserOnce()

  }

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

    // Get token
    const result = await this.$auth.request({
      ...endpoint
    },
      this.options.endpoints.login
    )

    // Set token
    if (this.options.tokenRequired) {
      const token = this.options.tokenType
        ? this.options.tokenType + ' ' + result
        : result
        
      this.$auth.setToken(this.name, token)
      this._setToken(token)
    }

    // If result I get and set user
    if (result) {
      const user = await this.$auth.request({
        ...endpoint
      },
        this.options.endpoints.user
      )
      this.$auth.setUser(user);
    }
  }
  
  async fetchUser (endpoint) {
    // User endpoint is disabled.
    if (!this.options.endpoints.user) {
      this.$auth.setUser({})
      return
    }
    
    // Token is required but not available
    if (this.options.tokenRequired && !this.$auth.getToken(this.name)) {
      return
    }
    
    // Try to fetch user and then set
    try{
      const user = await this.$auth.requestWith(
        this.name,
        endpoint,
        this.options.endpoints.login
      )

      this.$auth.setUser(user)
    } catch (error){
      console.log(error)
    }
  }
}

When I set this.$auth.setUser(user) in login() method all is fine and app redirect me to /dashboard page and the user information (like role and email) is displayed on navBar but when I refresh page I lose user data. The app try to fetchUser but it give me a 400 error because user and password not sent.
Another thing I don´t understand is Why endpoint parameter is undefined in async fetchUser (endpoint) ??? . I think there is an issue in this part.

I hope u can help me
Regards

@TobiasJ
Copy link

TobiasJ commented Dec 4, 2020

#809 (comment)
should do the trick

Short version:
due to a breaking change or bug in the newer versions of @nuxt/axios / axios the auth module is not able to set the correct auth headers before dispatching the request to fetch the user-data. Thus we get a 401 (unauthenticated) on server-side.

@JoaoPedroAS51
Copy link
Collaborator

JoaoPedroAS51 commented Dec 18, 2020

Hi @diegodelajara! Sorry for the delay!

First, I would recommend using v5 instead of v4. See status and #893

Docs of v5 can be found here: local scheme and creating custom scheme

With that being said, I believe that your user is not being fetched because of typo in fetchUser

 async fetchUser (endpoint) {
    // User endpoint is disabled.
    if (!this.options.endpoints.user) {
      this.$auth.setUser({})
      return
    }
    
    // Token is required but not available
    if (this.options.tokenRequired && !this.$auth.getToken(this.name)) {
      return
    }
    
    // Try to fetch user and then set
    try{
      const user = await this.$auth.requestWith(
        this.name,
        endpoint,
        this.options.endpoints.login // <- here should be this.options.endpoints.user
      )

      this.$auth.setUser(user)
    } catch (error){
      console.log(error)
    }
  }

You can also simplify your login method to use fetchUser method.

// Your code now
if (result) {
  const user = await this.$auth.request({
    ...endpoint
  },
    this.options.endpoints.user
  )
  this.$auth.setUser(user);
}

// Simplified
if (result) {
  await this.fetchUser()
}

Another thing I don´t understand is Why endpoint parameter is undefined in async fetchUser (endpoint)

The endpoint param is undefined by default. It's an optional param that can be used to configure the endpoint when calling the method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants