Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Redirected to login after refreshing any protected page #478

Closed
atymic opened this issue Nov 4, 2019 · 34 comments
Closed

Redirected to login after refreshing any protected page #478

atymic opened this issue Nov 4, 2019 · 34 comments
Labels

Comments

@atymic
Copy link

atymic commented Nov 4, 2019

Version

4

Reproduction link

http://todo.com

Steps to reproduce

Visit a protected route by clicking a nuxt-link, and it loads correctly.
Then refresh the page

What is expected ?

Protected page loads

What is actually happening?

Redirect to login

Additional comments?

Hi!

I'm a bit confused as to why this is happening. I'm using a pretty basic set up (local scheme, universal storage).

As soon as I refresh the page, I'm redirected (302 from nuxt) to the login page. I did a bit of debugging and this seems to be because loggedIn isn't set in the cookie state.

All of the other cookies are there, but i'm still redirected :(

I'll do some more digging and try find some more info & a repro

This bug report is available on Nuxt community (#c439)
@ghost ghost added the cmty:bug-report label Nov 4, 2019
@atymic
Copy link
Author

atymic commented Nov 4, 2019

My current hackyish solution is to manually redirect back to the correct page from inside the login page:

 mounted () {
      if (this.$auth.loggedIn) {

        if (this.$auth.$storage.getUniversal('redirect')) {
          this.$router.replace(this.$auth.$storage.getUniversal('redirect'))
          this.$auth.$storage.removeUniversal('redirect')
          return;
        }

        this.$router.replace('/')
        return
      }

@truesteps
Copy link

I'm having the same issue, I tried checkout out older versions of my app to see if it would work but they unfortunately didn't. I fiddled around with my own middlewares that I had in place, whether they were redirecting me badly, but it seems to be the auth ultimately.

As OP mentioned I am using the basic local scheme, I didn't do anything to the auth since the first time I implemented it and after half a year of development and working fine, without updating my node_modules, it just stopped working.

@therhenals
Copy link

The same happens to me when I deploy the project in zeit now with nuxt/now-builder

@pushkin5241
Copy link

I had such a problem, I added the ip address to the token and then checked it on the server in middleware, whether it is equal to the ip address from the request.
And the reason was that when I updated the page (nuxt was turned on in the SSR mode and axios sends a request to the server before issuing the page), then the address in the request will be the address of your server

@dan-danciu
Copy link

I had this problem also.
I solved it by micromanaging auth :)
This might not be what you need but take a look.
So this is what I have:

auth: {
    strategies: {
      local: {
        endpoints: {
          login: false,
          logout: false,
          user: false
        }
      }
    }
  },

When logging in I do it with axios and I manually set up auth. I do this mainly because I need my app to handle refresh tokens so you could just call the $auth.loginWith instead:

await this.$auth.setToken("local", "Bearer " + access_token);

Then I get the user with axios as well and then I also give it to auth:

this.$auth.setUser(user.data);

This also sets the loggedIn flag on auth so my middleware looks like this:

export default function({ $auth, redirect }) {
  if (!$auth.loggedIn) {
    return redirect("/login");
  }
}

In the log out functionality I just clear local storage and do:
this.$auth.logout();

So I handle everything manually and it works out well in the end.

@truesteps
Copy link

truesteps commented Feb 14, 2020

So I figured it out and there is nothing wrong with the package at all as it is.

The underlying issue for me, was the fact that nodejs refused to accept the response from our BE server, since it didn't have a fullchain certificate, only an intermediate one and the response from the server was deemed as unsecure so nodejs just threw the response away without reporting any errors. I figured this out while trying to implement axios proxy as a last resort to try to fix this and the proxy was giving me unable_to_verify_leaf_signature error.

Which just showed me towards the right way.

Something to note: It worked fine with apache but we switched stack to nginx midway through development...

// Edit:
If this helps at least one of you to get rid of all the awful hacks that are here, I made the world a better place!

@lukaVarga
Copy link

For me, the issue was with cookie settings. Basically, setting a secure: true doesn't work on localhost (I haven't tried on a staging environment yet). So setting this did the trick

auth: {
    .......
    cookie: {
      options: {
        secure: false,
      },
    },
}

Note: After changing this (locally) between true and false, try it out in incognito mode (or make sure you clear your cookies first). Otherwise you might not see any difference (especially when changing it from false to true).

@leonelsanchesdasilva
Copy link

leonelsanchesdasilva commented Mar 14, 2020

Had the same problem when publishing to Heroku (production).

First, it's good to provide a little bit of context:

Packages

  "dependencies": {
    "@fortawesome/fontawesome-free": "^5.10.2",
    "@nuxtjs/auth": "^4.8.5",
    "@nuxtjs/axios": "^5.9.5",
    "bootstrap": "^4.1.3",
    "bootstrap-vue": "^2.0.1",
    "chart.js": "^2.8.0",
    "fullcalendar": "^3.10.1",
    "google-charts": "^2.0.0",
    "jquery": "^3.4.1",
    "jquery-sparkline": "^2.4.0",
    "leaflet": "^1.5.1",
    "load-google-maps-api": "^2.0.1",
    "mapbox-gl": "^1.3.1",
    "noty": "^3.2.0-beta",
    "nuxt": "^2.11.0",
    "nuxt-i18n": "^6.6.0",
    "perfect-scrollbar": "^1.4.0",
    "sortablejs": "^1.10.0-rc3",
    "v-money": "^0.8.1",
    "vue": "^2.6.10",
    "vue-select": "^3.2.0",
    "vue-the-mask": "^0.11.1"
  },
  "devDependencies": {
    "@nuxtjs/eslint-config": "^1.0.1",
    "@nuxtjs/eslint-module": "^1.0.0",
    "@vue/eslint-config-prettier": "^5.0.0",
    "@vue/test-utils": "^1.0.0-beta.27",
    "babel-eslint": "^10.0.1",
    "babel-jest": "^24.1.0",
    "eslint": "^6.1.0",
    "eslint-plugin-nuxt": ">=0.4.2",
    "eslint-plugin-prettier": "^3.1.1",
    "eslint-plugin-vue": "^5.0.0",
    "jest": "^24.1.0",
    "lint-staged": "^8.2.1",
    "node-sass": "^4.12.0",
    "prettier": "^1.18.2",
    "sass-loader": "^7.1.0",
    "vue-jest": "^4.0.0-0"
  }

nuxt.config.js

export default {
  mode: 'universal',
  auth: {
    strategies: {
      local: {
        endpoints: {
          login: { url: '/auth', method: 'post', propertyName: 'token' },
          // login: false,
          // logout: { url: '/api/auth/logout', method: 'post' },
          logout: false,
          user: { url: '/auth/user', method: 'get', propertyName: 'user' }
          // user: false
        },
        tokenRequired: true,
        tokenType: 'bearer'
      }
    },
    redirect: {
      login: '/login',
      logout: '/login'
      // callback: '/',
      // home: '/'
    },
    cookie: {
      options: {
        secure: process.env.NODE_ENV && process.env.NODE_ENV === 'production'
      }
    }
  },
  env: {
    apiUrl: process.env.API_URL || 'http://localhost:5000'
  },
  ...
  router: {
    middleware: ['auth']
  }
}

Environment Variables

NPM_CONFIG_LOGLEVEL=error
NPM_CONFIG_PRODUCTION=true
NODE_ENV=production
NODE_MODULES_CACHE=true
NODE_VERBOSE=false
HOST=0.0.0.0
API_URL=https://api.myservice.com

Deployed successfully, but every single page reload not using a nuxt-link was showing the login page. @atymic 's hint made me write a small debug middleware like this:

/middleware/debug_auth.js

export default function ({ $auth }) {
    console.log($auth);
}

Then I've found something like this in the middle of logs:

UNABLE_TO_VERIFY_LEAF_SIGNATURE

So I figured that Axios was trying to call endpoints.user (my case, /auth/user) and having a problem with the certificate. Turns out I purchased this certificate last week, so it was very strange that my certificate wasn't being accepted by Axios.

Testing the API url with a SSL Checker like https://www.sslshopper.com/ssl-checker.html gave me a message like:

The certificate is not trusted in all web browsers. You may need to install an Intermediate/chain certificate to link it to a trusted root certificate. Learn more about this error [Link]. You can fix this by following Sectigo's Certificate Installation Instructions for your server platform (use these instructions for InstantSSL [Link]). Pay attention to the parts about Intermediate certificates.

Indeed, my certificate issuer sent me a .crt file and a bundle file (which has, in theory, my purchased certificate + the intermediate certificate), but Heroku was complaining about the key. I had to find the intermediate certificate pointed by the SSL Checker by name (my case, Issuer: Sectigo RSA Domain Validation Secure Server CA) and combine them using a text editor (the order matters: first my purchased certificate, then the intermediate certificate). With the new file, Heroku accepted the bundle file and the key, I ran the validation again and this time the message was

The hostname (api.myservice.com) is correctly listed in the certificate.

I see some people setting NODE_TLS_REJECT_UNAUTHORIZED=0 and getting the problem "solved", but this just makes Node bypass the certificate verification. Not a good idea.

Would be great if this library can throw something in the logs when the TLS check fails. It would save a lot of time from this community figuring out how to solve this particular problem.

@okaufmann
Copy link

okaufmann commented Apr 6, 2020

Thanks @leonelsanchesdasilva !

I had exactly the same problem. The API had to be called locally via HTTPS and since nuxt-auth cannot reload the user, it logs out and causes this behavior.

After adding NODE_TLS_REJECT_UNAUTHORIZED=0 to the .env file (@nuxt/dotenv needed) it worked again.

It also seems to make sense to enable axios debug logs. Add this to your nuxt.config.js

  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {
    debug: process.env.NODE_ENV && process.env.NODE_ENV === 'development',
    // See https://github.com/nuxt-community/axios-module#options
  },

Then you will get something like this:
image

@jasonlyu123
Copy link

jasonlyu123 commented Apr 11, 2020

Have the the same problem before. The auth module just catch all error in fetch user data request on server. This is not very dev friendly! Maybe a console error of this by default would make our life much more easier 👍.
It should log or throw every error other than a status code of 401. The annoy me every time when I just forget to start api server for debug because it catch all error and redirect to login even if auth api server is unreachable lol.

@brendanlong
Copy link
Contributor

I had this problem and none of the above stuff applied to me (network logs showed that the user lookup was working). I fixed it by removing cookie: false from my nuxt.config.js. It's unclear to me why the cookie storage is required for this, since I would have expected local storage to work too.

@brendanlong
Copy link
Contributor

Ah I see, cookie: false prevents server-side auth. The problem I'm running into is that the auth module doesn't work right in SPA mode.

@brendanlong
Copy link
Contributor

brendanlong commented Apr 12, 2020

Ah actually it does work in SPA mode. If I set mode: "spa" localStorage works correctly. I think the problem is that the middleware isn't getting called in universal mode, according to the docs:

In universal mode, middlewares will be called server-side once (on the first request to the Nuxt app or when page refreshes) and client-side when navigating to further routes. In SPA mode, middlewares will be called client-side on the first request and when navigating to further routes.

https://nuxtjs.org/guide/routing#middleware

Which explains the behavior I was getting with localstorage mode, where I'd be redirected to /login on refresh, but if I click any link, I'm suddenly logged in (since the middleware triggered).

I'm new to Nuxt (and Vue) so I'm not sure what we're supposed to do with a middleware which needs to run on both the client and server side on initial load (since the server doesn't necesarily have access to the auth token).

EDIT: Seems like this is by design and just how Nuxt middleware works nuxt/nuxt#2653 If you want to only use local storage and not cookies, you need to render in SPA mode.

It's possible there's some sort of plugin version of this auth module that would work in universal mode without cookies but I'm still too new at this to really understand the difference. My app is going to use SPA mode anyway so it doesn't really matter to me.

@IvanBernatovic
Copy link

This was happening to me on every environment but only on new browser session. By default, cookies are deleted on session end. You have to set maxAge property of the cookie object to avoid cookie deleting after browser is closed.

@hktr92
Copy link

hktr92 commented Apr 26, 2020

You have to set maxAge property of the cookie object to avoid cookie deleting after browser is closed.

which... doesn't work for me in universal mode. the cookies are set anyways without maxAge (the expires field doesn't affect it either).

what i've defined in code:
image

and what do I get:
image

for this project I'm working on, I treat it as a feature, as it has to do with sensitive stuff, so it is ok to authenticate on each request. but in dev mode, it's annoying to always authenticate myself after each page refresh. and for other projects, too.

@IvanBernatovic
Copy link

@hktr92 Based on your screenshot it seems that you're setting your cookie options wrong. Based on the docs, you should place most of your settings in auth.cookie.options object, not directly in cookie object.

@Spiegel1039
Copy link

set the login property under redirect to false in nuxt.config.js

@xeno010
Copy link

xeno010 commented May 6, 2020

I had the same problem with nuxt-auth and Laravel (Sanctum)
Laravel checks if the request is coming from the frontend using the referer header. But SSR does not send a referer.

Simple solution:

# nuxt.config.js
user: {
    url: '/api/v1/user',
    method: 'get',
    propertyName: 'data',
    withCredentials: true,
    data: {},
    headers: {
      'Referer': 'http://YOUR.FRONTEND.DOMAIN', // <- here
      'Accept': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json'
    }
}

Or override the EnsureFrontendRequestsAreStateful Middleware

<?php

namespace App\Http\Middleware;

use Illuminate\Support\Str;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful as BaseEnsureFrontendRequestsAreStatefulAlias;

class EnsureFrontendRequestsAreStateful extends BaseEnsureFrontendRequestsAreStatefulAlias
{

    public static function fromFrontend($request)
    {
        if(parent::fromFrontend($request)) {
            return true;
        }

        return Str::startsWith($request->headers->get('x-forwarded-host', ''), config('sanctum.stateful', []));
    }
}

@vivekkairi
Copy link

vivekkairi commented Jun 24, 2020

Workaround:

So I had base url set to '/api' and all secured pages were getting redirected through 302.

Changed baseUrl to complete site url with https and it worked.
axios: { baseURL: 'https://mdsaban/api' }

@anwarramadha
Copy link

finally i found that the problem was with auth middleware. Just change the built in nuxt auth middleware with your own as i did.
middleware/authentication.js

const authentication = async ({ store, redirect }) => {
  if (!store.$auth.loggedIn) {
    if (!store.$auth.$storage._state['_token.sso']) {
      return redirect('/login')
    }
    await store.$auth.fetchUser()
  }
}

export default authentication

then change nuxt auth redirect configuration in nuxt.config.js like this:

redirect: { login: false, logout: '/login', home: false, callback: '/dashboard' },

@smzapp
Copy link

smzapp commented Aug 21, 2020

finally i found that the problem was with auth middleware. Just change the built in nuxt auth middleware with your own as i did.

@anwarramadha
Is this working in you already? On my local, I have this result. After I login, it goes to dashboard but then after I refreshed, it goes back to login page. I tried to remove the middleware:auth to check the value of this.$auth.loggedIn and then I got this:

https://i.imgur.com/aqj264p.png

On JS console, it is true, but on nuxt SSR, it is false. I guess, this is the reason why middleware:auth doesn't work. I tried your solution but it is still the same. Have you found alternative solution for this?

@izundo-viennv
Copy link

It seems that no others working on this issue. I'm running into this issue. The middleware run on server so loggedIn will be false when refresh the protected page

@Atem18
Copy link

Atem18 commented Oct 11, 2020

@anwarramadha For me it's nearly works. If I refresh the /dashboard page, yes it works but if I refresh while on another page I get :

Error
connect ECONNREFUSED 127.0.0.1:80
net.js
Missing stack frames
Js
TCPConnectWrap.afterConnect [as oncomplete]@1141:16

@fabiom91
Copy link

So did anyone found a solution?
The issue is that Nuxtjs Auth is not working in the middleware:

When calling $auth.$state on a page (while authenticated), it works and return the user data while if you do it on the middleware where you defined your own authentication policy (but also the default middleware: auth), it can't find the logged user.

my custom middleware (Not Working!)

export default async function ({ $auth, redirect }) {
  const user = await $auth.loggedIn
  console.log(user)
  if (user) {
    // let the user see the page
  } else {
    // redirect to homepage
    redirect('/')
  }
}

@Atem18
Copy link

Atem18 commented Oct 20, 2020

@fabiom91 Yes I found a solution but I am not sure exactly what makes it works.
I am using Caddy in front of my backend and frontend in HTTPS and there are no middleware. And my app is called Nautilus FYI.

My nuxt.config.js:

export default {
  publicRuntimeConfig: {
    axios: {
      browserBaseURL: process.env.BROWSER_NAUTILUS_API
    }
  },
  privateRuntimeConfig: {
    axios: {
      baseURL: process.env.NAUTILUS_API
    }
  },
  /*
   ** Nuxt target
   ** See https://nuxtjs.org/api/configuration-target
   */
  target: 'server',
  pwa: {
    icon: {
      /* icon options */
      fileName: 'nautilus.png'
    }
  },
  /*
   ** Headers of the page
   ** See https://nuxtjs.org/api/configuration-head
   */
  head: {
    titleTemplate: '%s - ' + process.env.npm_package_name,
    title: process.env.npm_package_name || '',
    meta: [{
      charset: 'utf-8'
    },
    {
      name: 'viewport',
      content: 'width=device-width, initial-scale=1'
    },
    {
      hid: 'description',
      name: 'description',
      content: process.env.npm_package_description || ''
    }
    ],
    link: [{
      rel: 'icon',
      type: 'image/x-icon',
      href: '/favicon.ico'
    }]
  },
  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   ** https://nuxtjs.org/guide/plugins
   */
  plugins: [
    {
      src: '~/plugins/repository'
    },
    {
      src: '~/plugins/native-websocket.js',
      mode: 'client',
      ssr: false
    }
  ],
  /*
   ** Auto import components
   ** See https://nuxtjs.org/api/configuration-components
   */
  components: true,
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module',
    '@nuxtjs/vuetify'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    '@nuxtjs/auth',
    '@nuxtjs/pwa',
    // Doc: https://github.com/nuxt/content
    '@nuxt/content'
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {
    baseURL: 'http://localhost:8000',
    credentials: true,
    https: true
  },
  auth: {
    redirect: {
      logout: '/login'
    },
    strategies: {
      local: {
        endpoints: {
          login: { url: '/auth/login', method: 'post', propertyName: 'access_token' },
          logout: false,
          user: { url: '/users/me', method: 'get', propertyName: false }
        }
      }
    }
  },
  /*
   ** Content module configuration
   ** See https://content.nuxtjs.org/configuration
   */
  content: {},
  /*
   ** vuetify module configuration
   ** https://github.com/nuxt-community/vuetify-module
   */
  vuetify: {
    customVariables: ['~/assets/variables.scss'],
    theme: {
      themes: {
        light: {
          primary: '#e38c59',
          secondary: '#1789a9'
        },
        dark: {
          primary: '#e38c59',
          secondary: '#1789a9'
        }
      }
    }
  },
  /*
   ** Build configuration
   ** See https://nuxtjs.org/api/configuration-build/
   */
  build: {},
  server: {
    host: '0.0.0.0'
  },
  watchers: {
    webpack: {
      poll: 1000,
      ignored: /node_modules/
    }
  },
  router: {
    middleware: ['auth']
  }
}

In my login.vue I am asking for auth: guest:

<script>
export default {
  auth: 'guest'
}
</script>

My Caddyfile for reference:

BACKEND_DOMAIN {
    tls /etc/caddy/certs/_wildcard.NAUTILUS_DOMAIN.pem /etc/caddy/certs/_wildcard.NAUTILUS_DOMAIN-key.pem
    reverse_proxy NAUTILUS_API {
        header_down Location http:// https://
    }
}

FRONTEND_DOMAIN {
    tls /etc/caddy/certs/_wildcard.NAUTILUS_DOMAIN.pem /etc/caddy/certs/_wildcard.NAUTILUS_DOMAIN-key.pem
    reverse_proxy NAUTILUS_WEB {
        header_down Location http:// https://
    }
}

Please ask if you need more files to reproduce a working app on your side.

@fabiom91
Copy link

fabiom91 commented Oct 20, 2020

Thank you @Atem18
Unfortunately I don't have much experience with Caddyfile and your solution seems a bit too complex. However I solved it by using cookie-universal-nuxt in combination with nuxtjs/auth:

You can leave your axios version as it is, no need to downgrade for this solution

  1. npm install --save cookie-universal-nuxt
  2. add cookie-universal-nuxt in your nuxt.config.js file:
modules: [
    // other modules ...
    '@nuxtjs/auth',
    'cookie-universal-nuxt',
  ],
  1. create a custom auth middleware. I called mine auth-user in the middleware folder:
export default async function ({ app, redirect }) {
  // the following look directly for the cookie created by nuxtjs/auth
  // instead of using $auth.loggedIn
  const user = await app.$cookies.get('auth._token.local')
  if (user) {
    // let the user see the page
  } else {
    // redirect to homepage
    redirect('/')
  }
}
  1. then declare your middleware in the root page of your application that you want to be accessible only by authenticated users:
<script>
export default {
  middleware: ['auth-user'],
}
</script>

If this doesn't work, check the cookie name where your user credential are saved by opening the developer tools / inspector in the browser.

Also see here: https://stackoverflow.com/questions/64444811/nuxtjs-auth-module-not-working-in-the-middleware/64447805#64447805

@Atem18
Copy link

Atem18 commented Oct 20, 2020

@fabiom91 The solution is not complex at all, Caddy is a web server like Nginx but I suspect that Caddy stores cookies somewhere while Nginx does not. And a solution like yours should be implemented by default in the auth-module.

@zacwebb
Copy link

zacwebb commented Nov 27, 2020

Amazing thanks @fabiom91 - this is the only solution that managed to solve the issue for me

@momurad18
Copy link

I had the same problem with nuxt-auth and Laravel (Sanctum)
Laravel checks if the request is coming from the frontend using the referer header. But SSR does not send a referer.

Simple solution:

# nuxt.config.js
user: {
    url: '/api/v1/user',
    method: 'get',
    propertyName: 'data',
    withCredentials: true,
    data: {},
    headers: {
      'Referer': 'http://YOUR.FRONTEND.DOMAIN', // <- here
      'Accept': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json'
    }
}

Or override the EnsureFrontendRequestsAreStateful Middleware

<?php

namespace App\Http\Middleware;

use Illuminate\Support\Str;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful as BaseEnsureFrontendRequestsAreStatefulAlias;

class EnsureFrontendRequestsAreStateful extends BaseEnsureFrontendRequestsAreStatefulAlias
{

    public static function fromFrontend($request)
    {
        if(parent::fromFrontend($request)) {
            return true;
        }

        return Str::startsWith($request->headers->get('x-forwarded-host', ''), config('sanctum.stateful', []));
    }
}

the first option work with me override forntend method doesnt work
Thank you

@evd3v
Copy link

evd3v commented Dec 28, 2020

Had the same issue, in my case the problem was in the server network settings.

I have the API, URL with domain name https://api.com (for example). But the server was in the same local network, where the nuxt app was. And when I'd tried to make request as curl -X GET https://api.com - it throw me the error curl: (7) Failed to connect to https://api.com : Connection refused, but when I sent the same request from my local machine, or from another server - it was work well. And when requests were sent by SSR, it throw the same error, I think. So, in this moment authentification fails.

After, we fixed the local network settings and all works as expected. May be it helps somebody.

@pyaehein
Copy link

pyaehein commented Mar 4, 2021

Workaround:

So I had base url set to '/api' and all secured pages were getting redirected through 302.

Changed baseUrl to complete site url with https and it worked.
axios: { baseURL: 'https://mdsaban/api' }

It works for me.

@yoelpc4
Copy link

yoelpc4 commented Mar 4, 2021

Thanks @leonelsanchesdasilva !

I had exactly the same problem. The API had to be called locally via HTTPS and since nuxt-auth cannot reload the user, it logs out and causes this behavior.

After adding NODE_TLS_REJECT_UNAUTHORIZED=0 to the .env file (@nuxt/dotenv needed) it worked again.

It also seems to make sense to enable axios debug logs. Add this to your nuxt.config.js

  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {
    debug: process.env.NODE_ENV && process.env.NODE_ENV === 'development',
    // See https://github.com/nuxt-community/axios-module#options
  },

Then you will get something like this:
image

To anyone ever faced UNABLE_TO_VERIFY_LEAF_SIGNATURE issue, instead of set up NODE_TLS_REJECT_UNAUTHORIZED=0 you could passed secure: false on proxy configuration, like so:

// Reverse proxy configuration
  proxy: {
    '/laravel': {
      pathRewrite: {
        '^/laravel': '/',
      },
      secure: process.env.NODE_ENV === 'production',
      target: 'https://api.app.test',
    },
  },

It works like a charm.

For more information check this out Webpack Dev Server Proxy Docs

@ajingopi-bridge
Copy link

There could be many reasons, but for me it's different.

In my nuxt-config.js

ssr: true,
target: 'server',
publicRuntimeConfig: {
    axios: {
      baseURL: process.env.BASE_URL,
    },
}

and I was using below command in production
yarn generate && yarn start

I changed it to yarn build && yarn start

Now everything works perfectly. When using yarn generate, it is supposed to use for static rendering only and because of that request & response headers or some nuxt contexts are not available on server side. That is the reson why server is unable to authenticate the user.

@timdrake
Copy link

timdrake commented Jun 30, 2021

I was hoping the auth-next package would handle things more gracefully than its' predecessor, but this does not seem to be the case. However, I was able to get everything working well, and without throwing navigation guard errors. My primary objective was to redirect the user back to the guarded path (including parameters) after a successful login.

An overview of my routes, and the desired redirect behavior is as follows:

If the user IS NOT authenticated the following should occur:

/ => /login
/login (no redirect occurs)
/sign-up (no redirect occurs ; the user needs to be able to sign up if they do not have a user account)
/logout (no redirect occurs)
/home => /login
/guarded/path => /login
/another/guarded/path?with= parameters => /login?with= parameters (the ?with=parameters displaying on the login page looks silly, and can likely be removed using a custom auth plugin via $auth.onRedirect. I just have not done this, yet. I will update this comment if I do.)

If the user IS authenticated the following should occur:

/ => /home
/login => /home
/sign-up => /home
/logout (no redirect occurs)
/home (no redirect occurs)
/guarded/path (no redirect occurs)
/another/guarded/path?with= parameters (no redirect occurs)

My auth relevant nuxt.config.js is as follows:

auth: {
  redirect: {
    // do not allow auth to automatically redirect to home. we will do this with our custom auth-redirect middleware.
    home: false,
    login: '/login',
    logout: '/logout',
  },
  strategies: {
    local: {
      token: {
        property: 'jwt',
        global: true,
      },
      user: {
        property: false,
        autoFetch: false,
      },
      endpoints: {
        login: { url: '/auth/local', method: 'post' },
        logout: { url: '/auth/logout', method: 'post' },
        user: { url: '/users/me', method: 'get' },
      },
    },
  },
},

// enable auth globally. we want to guard everything by default, and override on a case-by-case basis.
router: {
  middleware: ['auth'],
},

My custom middleware/auth-redirect.js middleware is as follows:

export default function ({ $auth, redirect, route }) {
  // if the user is not authenticated, and we are not on the login or sign up page then redirect to the login page.
  if (!$auth.loggedIn && !['/login', '/sign-up'].includes(route.path)) {
    return redirect('/login')
  // if the user is authenticated, and we are not on the home page then redirect to the home page.
  } else if ($auth.loggedIn && route.path !== '/home') {
    return redirect('/home')
  }
}

My / auth relevant logic is as follows:

<script>
export default {
  auth: false,
  middleware: 'auth-redirect',
}
</script>

My /login auth relevant logic is as follows:

<script>
export default {
  beforeRouteEnter(from, to, next) {
    // attempt to store the route full path (including parameters) so that we may redirect to it after a successful login.
    next((vm) => vm.setRedirectUrl(to))
  },
  auth: false,
  middleware: 'auth-redirect',
  data() {
    return {
      redirectUrl: null,
    }
  },
  methods: {
    setRedirectUrl(toRoute) {
      // only store the route full path (including parameters) if the path of the route does not match one of the following. we do not want to redirect a successful login back to any of the following pages.
      if (!['/', '/login', '/logout', '/sign-up'].includes(toRoute.path)) {
        this.redirectUrl = toRoute.fullPath
      }
    },
    async signinUser(userInfo) {
      const userData = {
        /* credentials go here */
      }

      try {
        const response = await this.$auth.loginWith('local', { data: userData })

        await this.$auth.setUserToken(response.data.jwt)

        // if a redirect URL is set then redirect to the URL.
        if (this.redirectUrl) {
          this.$router.push(this.redirectUrl)
        // if a redirect URL is not set then redirect to the home page.
        } else {
          this.$router.push('/home')
        }
      } catch (e) {
        /* exception handling goes here */
      }
    },
  },
}
</script>

My /sign-up auth relevant logic is as follows:

<script>
export default {
  auth: false,
  middleware: 'auth-redirect',
}
</script>

My /logout auth relevant logic is as follows:

<script>
export default {
  auth: false,
  created() {
    if (this.$auth.loggedIn) {
      this.$auth.logout()
    }
  },
  mounted() {
    this.$router.app.refresh()
  },
}
</script>

Lastly, do not forget to initialize the Vuex store by at least creating an empty store/index.js file. Redirects as well as many facets of auth seem to have issues when the Vuex store is not enabled.

My /guarded/paths need no auth relevant logic as auth has been enabled globally in nuxt.config.js.

I hope this helps. 🙏🏻

@nuxt-community nuxt-community locked and limited conversation to collaborators Jan 20, 2022
@bmulholland bmulholland converted this issue into discussion #1518 Jan 20, 2022

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
Projects
None yet
Development

No branches or pull requests