auth-module: auth stuck at the callback URL — not storing Auth0 token [SPA mode]

EDIT All the testing links are not working anymore. Given the feedback and the PR made it seems the issue is solved so I took offline the demos I made for the various scenarios. I will check out the new PR too as soon as I can but given that the project maintainers already merged it to master I suppose it’s a go for production too.

Given the three tests I’ve done, I am making here a recap for clarity

  1. Mode SPAexample-auth0 repository https://github.com/nuxt-community/auth-module/issues/536#issue-568235358 Reproduction link: https://nuxt.federicod.dev/

Application stays stuck at the callback page, not storing the auth0 token, in the chance that this was an issue with the example-auth0 repo alone I’ve tested also the example build in the auth-module repo.

  1. Mode SPAauth-module repository https://github.com/nuxt-community/auth-module/issues/536#issuecomment-589557690 Reproduction link: https://auth-test.federicod.dev/

Same as above, I now think that the issue resides indeed in the auth-module itself.

  1. Mode SSR (universal) — auth-module repository https://github.com/nuxt-community/auth-module/issues/536#issuecomment-589600857 Reproduction link: https://auth-test-ssr.federicod.dev/

After trying to build the SSR version of the example\demo application, and serving it with nuxt start I have confirmed that the auth-module either:

  • doesn’t work at all in SPA mode;
  • the build command with the SPA configuration breaks something

Mode SPA — example-auth0 repository

Version

v4.8.5

Reproduction link

https://nuxt.federicod.dev/

Steps to reproduce

  1. git clone https://github.com/nuxt/example-auth0.git;
  2. set Auth0 domain and client_id into nuxt.config.js (I am not using the .env file as it seems to me that it doesn’t get embedded in the SPA after running npm run build)
  3. set mode: spa
  4. nuxt build
  5. deploy the dist folder
  6. access the website and try to login with demo@demo.com; Demo1@23
  7. after the callback URL is opened, it stays stuck there

On a more complicated platform I am developing, some API calls that are made on the callback URL to populate a Vuex store all yields unauthorized error, meaning that the token doesn’t get stored at all.

When running example-auth0 and the application I am developing in development mode with npm run dev, everything works fine. So I suppose that something goes wrong only after running the build command.

What is expected ?

I expect the callback URL to be opened and the token received stored.

What is actually happening?

The SPA stays stuck at the callback URL and no token is stored.

Additional comments?

Webserver: Caddy Configuration:

nuxt.federicod.dev {
        root /root/dev/example-auth0/dist
}

No errors are shown in the console.

<div align="right">This bug report is available on Nuxt community (#c500)</div>

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 8
  • Comments: 26 (4 by maintainers)

Most upvoted comments

After a whole day researching I stumbled upon these issues https://github.com/nuxt-community/auth-module/issues/299 and https://github.com/nuxt/nuxt.js/issues/5267.

The whole situation is still somewhat unclear to me, however I’ve tried to deploy the application in another way again Mode SSR (spa) — auth-module repository and the authentication flow worked as expected.

As referenced in the above mentioned issues it seems that static SPA mode is not supported at all by the auth-module (more specifically by its dynamic behaviour, so other libraries could be affected). What it is not explain at all in the documentation is that there are two possible ways to serve an SPA application:

  • either with the mode: 'spa' nuxt build and nuxt start
  • or the mode: 'spa' nuxt build and directly serving the dist folder as the document root with the webserver in use

In either case, nuxt build examples\demo creates two relevant folders:

  • the /dist folder in the project root;
  • the /example/demo/.nuxt;
.
|-- dist
|   |-- _nuxt
|   |   `-- img
|   |-- callback
|   |-- login
|   |-- public
|   `-- secure
|-- examples
|   |-- api
|   |-- demo
|   |   |-- .nuxt
|   |   |-- assets
|   |   |-- components
|   |   |-- layouts
|   |   |-- pages
|   |   `-- store

From the documentation on SPA one would assume that deploying only the /dist folder is necessary, instead to have the authentication flow working properly it is needed to run nuxt start examples/demo which serves the files from /example/demo/.nuxt.

I am hella lot confused on the deployment process involved with Nuxt. I beg someone to explain what’s happening here.

I had trouble where callback url was configured for an oauth strategy but didn’t match $auth.options.redirect.callback so the middleware wasn’t extracting tokens from url fragment.

Hope this helps someone else.

Its not working for me either, netlify + auth0 mode spa, on local it’s working, deployed generated version not

I got similar issue fixed by changing token url

token: process.env.API_URL + '/auth/token'

hope it helps someone.

complete auth config


auth: {
   localStorage: false,
   cookie: {
     prefix: 'tsterp-auth.',
     options: {
       path: '/',
     },
   },
   redirect: {
     login: '/login',
     logout: '/login',
     callback: '/login',
     home: '/',
   },
   resetOnError: true,
   strategies: {
     local: {
       token: {
         property: 'token',
         required: true,
         type: 'Bearer',
       },
       user: {
         property: '',
       },
       endpoints: {
         login: { url: '/v1/auth/login', method: 'post' },
         logout: false,
         user: { url: '/v1/employees/me', method: 'get' },
       },
     },
     jira: {
       scheme: 'oauth2',
       endpoints: {
         authorization: 'https://auth.atlassian.com/authorize',
         token: process.env.API_URL + '/v1/auth/jira-login',
         userInfo: '/v1/employees/me',
         logout: false,
       },
       audience: 'api.atlassian.com',
       token: {
         property: 'token',
         type: 'Bearer',
         required: true,
       },
       responseType: 'code',
       grantType: 'authorization_code',
       redirectUri: process.env.JIRA_REDIRECT_URI,
       clientId: process.env.JIRA_CLIENT_ID,
       scope: [
         'read:me',
         'read:jira-work',
         'write:jira-work',
         'offline_access',
       ],
       codeChallengeMethod: '',
       responseMode: '',
       acrValues: '',
     },
   },
   plugins: ['~/plugins/auth.js'],
 },

Hi Fellow users

I have submitted a PR with a potential fix https://github.com/nuxt-community/auth-module/pull/586 (it fixed my login flow which has same issue), can some of you please try the fix and confirm if it fixes your issue too (or not).

Thanks Rajat Jindal

This is my solution to host on Zeit/Now and login using github:

now.json

{
  "builds": [
    { "src": "package.json", "use": "@now/static-build" },
    { "src": "/functions/*.js", "use": "@now/node" }
  ],
  "routes": [
    { "src": "/_auth/oauth/github/authorize", "methods": ["POST"], "dest": "/functions/authorize.js" }
  ],
  "env": {
    "GITHUB_CLIENT_ID": "YOUR CLIENT ID",
    "GITHUB_CLIENT_SECRET": "YOUR CLIENT SECRET"
  },
  "build": {
    "env": {
      "GITHUB_CLIENT_ID": "YOUR CLIENT ID",
      "GITHUB_CLIENT_SECRET": "YOUR CLIENT SECRET"
    }
  }
}

functions/authorize.js

const axios = require('axios');

require('dotenv').config();

module.exports = (req, res) => {
  const {
    code,
    redirect_uri: redirectUri,
    response_type: responseType
  } = req.body;

  axios
    .request({
      method: 'post',
      url: 'https://github.com/login/oauth/access_token',
      data: {
        client_id: process.env.GITHUB_CLIENT_ID,
        client_secret: process.env.GITHUB_CLIENT_SECRET,
        redirectUri,
        responseType,
        code
      },
      headers: {
        Accept: 'application/json'
      }
    })
    .then((response) => {
      res.status(200).send(response.data);
    })
    .catch((error) => {
      res.status(403).send(error);
    });
};

It’s just a serverless function who overrides /_auth/oauth/github/authorize and perform github authorization.

The Nuxt community has a strong focus on SSR and sometimes the likes of us that need just a SPA can feel a little left behind…

Mode SPA — auth-module repository

To ensure it wasn’t an issue only on example-auth0 end I’ve also tried the following with the auth-module repo:

Reproduction link https://auth-test.federicod.dev/

Steps to reproduce

  1. git clone https://github.com/nuxt-community/auth-module.git
  2. change domain and client_id in examples/demo/nuxt.config.js with my own Auth0 tenant
  3. Run nuxt build examples\demo --spa
  4. Deploy generated dist folder
  5. access the website and try to login with demo@demo.com; Demo1@23
  6. after the callback URL is opened, it stays stuck there

Same as above, when running auth-module development mode with nuxt, everything works fine. So I suppose that something goes wrong only after running the build command.

No errors are shown in console.

Thanks to r3dqu33n! I use Google OAuth2 provider in @nuxtjs/auth-next for authentication. Google makes callback to “/login” and the static site made with “nuxt generate” just does not have the page for it generated. I was already studying how to copy the module’s code for callback into my own page login.vue when I came across r3dqu33n’s code.

I authorized the callback url, no issues from google. But the auth module is completely non reactive when i arrive at the callback url with the tokens in the url. I have now added the following to my callback url page and it works.

  mounted(){
    var oauth_state = this.$route.hash.match(/state=([^&]*)/) && this.$route.hash.match(/state=([^&]*)/)[1]
    var access_token = this.$route.hash.match(/&access_token=([^&]*)/) && this.$route.hash.match(/&access_token=([^&]*)/)[1]
    var strategy = this.$route.hash.match(/google/) && this.$route.hash.match(/google/)[0]
    var local_state = this.$auth.$storage.getUniversal(strategy+'.state')
    if(access_token && oauth_state == local_state ){
      this.$auth.$storage.removeUniversal(strategy+'.state')
      this.$auth.loginWith('convert_google', {
        data:{
                "token": access_token
      }
      })
    }
  }

image But thats as manual as it can get. Certainly this is something the auth module should take care of. at least