nuxt-community / auth-module

Zero-boilerplate authentication support for Nuxt 2
https://auth.nuxtjs.org
MIT License
1.93k stars 924 forks source link

Authentication does not occur after callback on statically generated nuxt site #299

Closed devalexwhite closed 5 years ago

devalexwhite commented 5 years ago

Version

v4.5.1

Reproduction link

https://github.com/nuxt-community/auth-module

Steps to reproduce

Set a valid github key/secret in the nuxt config for the demo example. Use nuxt generate to produce a static build. Run http-server ./ in the dist folder. Try authenticate with github by going to /login and clicking the github button.

What is expected ?

The user should be authenticated after github redirects to the callback

What is actually happening?

Github redirects to /callback, but the user is not authenticated. The strategy in Vuex is reset to "local".

Additional comments?

This only effects static sites, I have not run into this issue when running the application normally. I have reproduced this in a private repo deployed to netlify as well.

This bug report is available on Nuxt community (#c277)
dominikmontada commented 5 years ago

Having the same issue. Any update on this?

devalexwhite commented 5 years ago

I had some thoughts on this, but haven't had a chance to verify. I wonder if this is failing because the Github endpoint for creating the OAuth access token doesn't support CORs. I'd imagine this only fails with static sites because in universal mode the server-side part of Nuxt is handling the token callback.

If this is the issue, the only solution would be to override the token_endpoint defined for the Github Provider to your own hosted handler (like a Lambda function that just makes the AJAX call and returns the OAuth token).

dominikmontada commented 5 years ago

I have investigated it a little bit. I'm not using GitHub, but Social, so not sure if this applies to GitHub as well, but I guess it should.

First of all, what strikes me as odd is that I have alternating results when trying to log in repeatedly and I can reproduce it 100% of the time. The first login attempt fails with a CORS problem on trying to access the /userinfo endpoint. It sends a correct OPTIONS request, but then ignores that and sends a normal request, which is then blocked because of missing CORS headers. This attempt stalls on the login page itself, before any kind of log in or redirect is performed.

When I then try to log in again without reloading the page, I'm being forwarded as usual to my IdP, can login, and the callback is performed. However, as described in the original post, the authentication then stalls on the callback. Nothing about any CORS error whatsoever.

These two patterns keep alternating no matter how many times I try, and reset once I reload the page.

dominikmontada commented 5 years ago

I've dug a little deeper and am pretty sure that it has nothing to do with CORS. First of all, my problem with the alternating pattern was simply caused by an old cookie when I ran the app in non-static mode. In incognito mode it does not occur. It's still a very strange behavior and definitely not correct, but anyway.

As for CORS: to make sure that it has nothing to do with it, I set up a local Docker environment with Keycloak, Nuxt, and a Nginx reverse proxy to serve the static files and proxy requests to Keycloak. I also set it up to add CORS headers. This solved the problem of the /userinfo request being rejected by CORS, however the log in request still stalls on the callback, just like before.

Unless I screwed something up with setting all of that up, it should have no relation to CORS. I feel like that some necessary JS is simply not executed, or that the store, which holds the auth state, is not working in static mode. However I'm only guessing here...

dominikmontada commented 5 years ago

I finally got it working on my side. In nuxt.config.js I had to switch the mode from Universal to SPA. After that I re-ran generate and it started working. Simple as that.

I must say I'm pretty confused as to why that is working because I thought that the mode should make no difference when generating static pages, but there it is.

roelmagdaleno commented 5 years ago

@dominikmontada Thank you! My $auth.$state.loggedIn value always return false after refresh the page when the user already logged in. So I did what you mentioned, changed to "universal" to "spa", then generate again, and finally got it working! Thanks :)

But now there's the doubt why is this happening on universal?

samanthamichele7 commented 5 years ago

Ran into this also — tried various methods to persist state on page refresh figuring that was the problem, but the only thing that worked for me as well to get the authentication middleware to properly work when logged in was changing from "universal" to "spa."

montoulieu commented 5 years ago

I'm unfortunately getting this issue with a new nuxt install and auth module for Google oauth.

Works great when running dev, but build and generate loop me back to login on both my local machine and netlify.

I already had my nuxt.config.js set to 'spa' instead of 'universal' which has me wondering what could be wrong here. 🤔

Any help would be greatly appreciated!

manniL commented 5 years ago

Using nuxt generate + auth module for https://blog.lichter.io/ and haven't seen such an issue. Mode was/is universal

jwheatp commented 5 years ago

Hi, I'm having the same issue :

I have this both on my own code and when using the /examples/demo folder.

Using spa mode does not solve the issue.

After searching into the code, I found this : https://github.com/nuxt-community/auth-module/blob/dev/lib/schemes/oauth2.js#L131-L134 So actually it seems it's willingly blocked in the code, no ?


If someone has this working, is it possible to publish it on a repo ? 🙏 Thanks

jwheatp commented 5 years ago

Ok so I got it working by using the module with version 4.7.0 (2 months ago).

npm install @nuxtjs/auth@4.7.0

A short term solution, waiting to understand more why it cannot be used anymore with static mode. See this line https://github.com/nuxt-community/auth-module/blob/dev/lib/schemes/oauth2.js#L131-L134

HughesWang commented 5 years ago

Hi, I'm having the same issue :

  • When I use npm run generate with modes universal OR spa : Auth0 redirect to /callback, but then no redirection to my home and no authentification (user is still null in the store).
  • When I use npm run dev, everything works.

I have this both on my own code and when using the /examples/demo folder.

Using spa mode does not solve the issue.

After searching into the code, I found this : https://github.com/nuxt-community/auth-module/blob/dev/lib/schemes/oauth2.js#L131-L134 So actually it seems it's willingly blocked in the code, no ?

If someone has this working, is it possible to publish it on a repo ? 🙏 Thanks

I got the same problem. When oauth0 redirect back to callback path, auth module won't fetch user, but npm run dev works.

version

v4.8.1

nuxt.config.js

mode spa

jakul commented 5 years ago

@Atinux Can you help here? You introduced the code that causes this in https://github.com/nuxt-community/auth-module/pull/381 https://github.com/nuxt-community/auth-module/blob/ea08d39b849b882ea32da7a9db9c338bef210db5/lib/schemes/oauth2.js#L131-L134

jakul commented 5 years ago

I've created a PR/branch which fixes this for me, and a PR in https://github.com/nuxt-community/auth-module/issues/452.

While we're waiting for that to get merged, you can use it in your sites with

$ npm install https://github.com/jakul/auth-module.git#fix/allow-callbacks-to-static-sites
DjustinK commented 4 years ago

It's not working at my side (npm run generate): "@nuxtjs/auth": "^4.8.4" "@types/nuxtjs__auth": "^4.8.1",

Im using the auth0 provider, after the callback i check if the user is logged in. this.$auth.loggedIn

This always returns false, im then getting redirect back to auth0 to login (which i am). This results in a never ending loop.

rasgo-cc commented 4 years ago

Also having the same issue, and I think I found the code to blame. /user/auth is my oauth2 callback

image

The trailing slash shoud be removed (or added to the redirect callback option?)

So the callback handler will fail for sure: https://github.com/nuxt-community/auth-module/blob/dev/lib/schemes/oauth2.js#L128

Will test a bit more and will try to make a PR.

A quick workaround without a PR and new release needed is to add a trailing slash to the callback endpoint.

There's also another bug and unrelated to this it seems. When the website is statically generated, the callback endpoint doesn't change the strategy automatically (ie, it keeps the local strategy). A workaround for this is to set it explicitely in the mouted function for example and then fetchUser to retrieve the user.

montoulieu commented 4 years ago

I see this issue is closed, but something is clearly not working properly.

  auth: {
    strategies: {
      github: {
        client_id: process.env.GITHUB_CLIENT_ID,
        client_secret: process.env.GITHUB_CLIENT_SECRET
      },
    }
  },

I'm building a new app on Netlify and trying to use a simple Github auth config and it has the same redirect loop issue I referenced here when being built in both spa and universal mode. It works perfectly on npm run dev but it is holding up my ability to launch this app live.

rasgo-cc commented 4 years ago

@montoulieu check my comment above. You might be able to fix it by making sure you add a trailing slash to your endpoint. Without that, it worked with yarn dev but not with yarn generate for me and that was the cause.

montoulieu commented 4 years ago

Thanks for the advice @rasgo-cc, unfortunately I'm still getting the same redirect loop behavior that takes me back to my login page.

image

The auth state also has a user of null with false for logged in. Pretty frustrating.

image
johanvanwambeke commented 4 years ago

I have the same problem and I dont understand how to implement your solution @rasgo-cc I am trying google auth so the only code I have is. Google:clientid

atinux commented 4 years ago

Actually GitHub auth is not supported yet on static generation since it need a serverMiddleware to generate the access token based on a secret key.

montoulieu commented 4 years ago

Any way we can get this out of a closed status until that's working?

maxiride commented 4 years ago

I stumbled upon the same issue (being stuck at the callback page). After reading everything I'm still a hella lot confused on the flow and decisions made to block the authentication flow.

What should be done if one wants to deploy an SPA with Auth?

johanvanwambeke commented 4 years ago

@Maxiride
I have this now as a redirect. And it works I guess it's the extra / The moment I added it, it just redirected ... without it. It stays on the page. redirect: { login: '/login', logout: '/', home: '/', callback: '/login/' },

maxiride commented 4 years ago

I'll give it a try. Is there also any difference in deploying with nuxt build --spa vs nuxt generate --spa?

mohamnag commented 4 years ago

I'm experiencing same problem after deploying a generated SPA on GitLab Pages. It tends to redirect all URLs to one with trailing / so after callback, I don't get redirected to home page. If this is al hanging on one trailing slash, this is clearly a bug and don't see why this should be closed!!

maxiride commented 4 years ago

@mohamnag Unfortunately after browsing a lot of similar issues I am getting the idea that this module isn't exactly production ready. Even the fixes implemented in the PR mentioned above fixed it for some and didn't for others.

mohamnag commented 4 years ago

handling authentication is in nature pretty complex specially if you are going to handle lots of providers. OAuth tries to unify but still leaves lots of space for diversity. But honestly, a trailing slash should not be among long lasting problems. I'm not confidence enough in Vue related things but this should be a simple check to fix.

vedovelli commented 4 years ago

My solution was to move my app from Netlify to Heroku. I changed the mode to universal and now although out of my favorite hosting company, I benefit from SSR. =) And the auth module is working like a charm.

altryne commented 4 years ago

Can confirm that had the same issue, callback redirect worked like a charm in dev, but when uploaded to Netlify, it didn't redirect. Adding trailing slashes (which Netlify adds by default) solved and callback redirect is now working.

There has got to be a fix for this, it's a ridiculous thing to try and hunt down, took me 2 hours of googling to get to this thread!

eramosr16 commented 3 years ago

Hey, I'm experiencing this very same issue with static site generation:

 ssr: false,
 target: 'static',
 "nuxt": "^2.14.6",
 "@nuxt/content": "^1.9.0",
 "@nuxtjs/auth-next": "^5.0.0-1610115973.9fdaa66",

I tried the trailing slash and didn't work either.

Jordanlelay commented 3 years ago

Hello there, experiencing the exact same issue. No way to get a Google Auth working in static mode

"nuxt": "^2.14.6"
"@nuxtjs/auth-next": "5.0.0-1608568767.2fe2217",
bmulholland commented 3 years ago

Since we don't have your authentication setup, it's almost impossible for us to track this down. We need your help. Please either post a repro (e.g. on codesandbox), or stick a breakpoint in the execution and debug the root cause.

prajintst commented 3 years ago

I got similar issue fixed by changing token url

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

hope it helps someone.

thankyou.

yoshutch commented 3 years ago

I had a similar issue caused by the trailing / on my redirect uri. Static S3 sites don't play well with a SPA that has routing to a page (i.e. a redirect uri of https://mycoolsite.com/auth won't work but a https://mycoolsite.com/auth/ will) so we set the redirect uri to include the trailing slash in the OAuth server's config.

To make the nuxt auth module work I had to define both the redirect callback option and the redirectUri in the nuxt.config.ts:

auth: {
    redirect: {
      callback: '/auth/' // need this for the auth module to know what path to execute the auth code callback
    },
    strategies: {
      oauth2: {
        scheme: 'oauth2',
        // ...
        redirectUri: 'https://mycoolsite.com/auth/', // need this so that we can define the redirect URI with a trailing slash since auth module removes it by default and static s3 sites need it
      }
    }

When I tried to put just redirect: { callback: '/auth/' } the auth module would remove the trailing slash before sending it to the auth endpoint as the redirectUri query param, which wasn't working. When I added the redirectUri property to the oauth strategy and removed the 'callback' property it failed again because the auth module was looking for the default callback/redirectUri (/login) and not the explicit one I defined in the strategy.

Hence I had to define both the full redirectUri and the redirect.callback path (not sure if the redirect.callback needs the trailing slash to work or not).

I hope this helps someone.

OndraRehounek commented 1 year ago

My oauth2 flow with ssr: false and target: static was solved by the extendRoutes config as mentioned in this PR (without installing the PR version)

https://github.com/nuxt-community/auth-module/pull/1308

chapus commented 9 months ago

It's never too late, I was able to solve it but my case is with SSR: true, my problem is similar except that it happened in some Samsung browsers where logging with Google worked always the first time. But when I entered and left several times it stopped working.

Debugging i saw auth write cookies with the Bearer token but inmediatly set all auth to false.

What I did was disable autoFetch in Google's config.

       Google: {
         clientId: process.env.CLIENT_ID_GOOGLE,
         codeChallengeMethod: '',
         callback: process.env.BASE_URL + '/google/redirect',
         responseType: 'code',
         endpoints: {
           token: process.env.BASE_URL + '/auth/user/google', 
           userInfo: process.env.BASE_URL + '/auth/me', 
         },
         user: {
           url: process.env.BASE_URL + '/auth/me',
           method: 'get',
           autoFetch: false, // <--------------------- FALSE fixed my issue
           property: 'user',
         },
         token: {
           property: 'token',
           type: 'Bearer',
           maxAge: 1800,
         },
       },

in my backend I returned the user and token.