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

If you enter the URL of a page that requires authentication in your browser, you will not be returned to the request page after signing in. #165

Closed
ibluest opened this issue May 4, 2018 · 11 comments
Labels

Comments

@ibluest
Copy link

ibluest commented May 4, 2018

I have difficulty moving the page after logging in.

If you click the page link that requires authentication and the login page appears, save the path to the previous page in the redirect token and return to the previous page if you successfully log in. This works exactly.
However, if you enter a page URL that requires authentication in your browser, or if you refresh the login page, you will be taken to the home instead of the previous page. You'll also need to double-click the Sign In button.
Perhaps the redirect token does not seem to generate the path of the previous page.

This issue also appears to be the same on the demo page.
How can we solve this problem?

This question is available on Nuxt.js community (#c122)
@ghost ghost closed this as completed May 4, 2018
@ghost ghost added the cmty:question label May 4, 2018
@sschadwick
Copy link
Contributor

sschadwick commented May 7, 2018

I'm running into this problem as well, don't know why the issue was closed.

@breakingrobot breakingrobot reopened this May 8, 2018
@SnooHD
Copy link
Contributor

SnooHD commented May 12, 2018

So what happens is that the server sets the redirect url in the store, and then goes to the login page on the server.
Because of this, the server reloads on the login page and loses all previous data (including the store).
In other words; this will work perfectly fine in mode:spa. (because then the redirect is done on the client instead, and the store is preserved).

A way to fix this might be by sending a cookie with the auth state on the server, then when we reload, we can check if a cookie excists and reload the previous state.

@SnooHD
Copy link
Contributor

SnooHD commented May 13, 2018

For whoever wants to solve this;
I made a middleware based on the original version that will set the cookie.
Then i am using a custom login scheme where i am checking for this cookie in the login function on the client.

I am using this plugin to set the cookies: https://github.com/S64/vue-universal-cookies

Middleware:

import { routeOption, getMatchedComponents } from '@nuxtjs/auth/lib/core/utilities'
export default function (ctx) {
  // Disable middleware if options: { auth: false } is set on the route
  if (routeOption(ctx.route, 'auth', false)) {
    return
  }

  // Disable middleware if no route was matched to allow 404/error page
  const matches = []
  const Components = getMatchedComponents(ctx.route, matches)
  if (!Components.length) {
    return
  }

  const { login, callback } = ctx.app.$auth.options.redirect

  if (ctx.app.$auth.$state.loggedIn) {
    // -- Authorized --
    // Redirect to home page if inside login page (or login page disabled)
    if (!login || ctx.route.path === login.split('?')[0]) {
      ctx.app.$auth.redirect('home')
    }
  } else {
    // -- Guest --
    // Redirect to login page if not authorized and not inside callback page
    // (Those passing `callback` at runtime need to mark their callback component
    // with `auth: false` to avoid an unnecessary redirect from callback to login)
    if (!callback || ctx.route.path !== callback.split('?')[0]) {
       if(process.server){
        //we are redirecting to the login page from the server!
        //to make sure we afterwards can retrieve the page we came from, we set a cookie.
        app.$cookies.set('auth-redirect', route.path, {
          path: login
        })
      }
      ctx.app.$auth.redirect('login')
    }
  }
}

Login scheme:

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

  // Ditch any leftover local tokens before attempting to log in
  await this._logoutLocally()

  const result = await this.$auth.request(
    endpoint,
    this.options.endpoints.login
  )

  if (this.options.tokenRequired) {
    const token = this.options.tokenType
      ? this.options.tokenType + ' ' + result
      : result

    this.$auth.setToken(this.name, token)
    this._setToken(token)
  }

  //check if cookie excists containing a redirect url.
  const cookie = this.$auth.ctx.app.$cookies.get('auth-redirect')
  if(cookie){
    //set the redirect url to ctx.from if there is none
    if(!this.$auth.ctx.from){
       this.$auth.ctx.from = cookie
    }
    //its now safe to remove the cookie
    this.$auth.ctx.app.$cookies.remove('auth-redirect')
  }

  return this.fetchUser()
}

@belak
Copy link

belak commented May 14, 2018

The other option is to use a query param, similar to how other frameworks have done it in the past. This is my current solution:

middleware/isLoggedIn.js:

// These helpers were copied from https://github.com/nuxt-community/auth-module/blob/dev/lib/core/utilities.js
// because it was easier than figuring out how to import them properly.
import { encodeQuery, routeOption, getMatchedComponents } from '../utils/nuxtjs-auth';

// NOTE: This is mostly a copy of the middleware from @nuxtjs/auth, however
// because we're using ctx.redirect and not $auth.redirect, this circumvents a
// number of features that library has to prevent infinite redirects and only
// redirect to known safe pages, so be very careful.
export default function isLoggedIn(ctx) {
  // Disable middleware if options: { auth: false } is set on the route
  if (routeOption(ctx.route, 'auth', false)) {
    return;
  }

  // Disable middleware if no route was matched to allow 404/error page
  const matches = [];
  const Components = getMatchedComponents(ctx.route, matches);
  if (!Components.length) {
    return;
  }

  // If we're not logged in, redirect to /login with 
  if (!ctx.app.$auth.loggedIn) {
    ctx.redirect(`/login?${encodeQuery({ next: ctx.route.fullPath })}`);
  }
}

pages/login.vue:

<script>
import { isRelativeURL } from '../utils/nuxtjs-auth';

export default {
  auth: false,

  head: {
    title: 'Login',
  },

  data() {
    return {
      username: '',
      password: '',
      errors: {},
    };
  },

  mounted() {
    // NOTE: This is meant to work around an issue with @nuxtjs/auth where
    // redirecting doesn't work properly. This only fixes the issue client
    // side, but that's good enough for now.
    if (this.$auth.loggedIn) {
      this.redirect();
    }
  },

  methods: {
    redirect() {
      if (this.$route.query.next && isRelativeURL(this.$route.query.next)) {
        this.$router.push(this.$route.query.next);
      } else {
        this.$router.push('/');
      }
    },
    handleLogin() {
      this.errors = [];
      this.$auth.login({
        data: {
          username: this.username,
          password: this.password,
        },
      }).then(() => {
        this.redirect();
      }).catch((error) => {
        this.errors = [error.message];
      });
    },
  },
};
</script>

@mathieutu
Copy link
Contributor

Duplicate of #134

@zolotyx
Copy link

zolotyx commented Jul 27, 2018

Please, take a look at my workaround

@mathieutu
Copy link
Contributor

Please could you post it the the original (proper) issue?

@shawnlauzon
Copy link

I agree with @mathieutu, this is a duplicate of #134 and should be closed.

@TheAlexLichter
Copy link
Member

More in #134

@raquelriobo
Copy link

raquelriobo commented Jun 15, 2020

RETURNING TO THE REQUEST PAGE AFTER LOGIN

Build in a system for keeping track of what page was originally requested and redirect to it after a successful login can be done in 2 steps.

As @belak said:

The query param solution is better,

However, for me his solution didn’t work as I have problems when trying to import the helpers from the library. Nevertheless, there is a most simple solution:

  • Create an auth-guard middleware that saves the requested url and redirects to the login with such url saved in the query params.

    • Declare the middleware in the nuxt config and disable @nuxtjs/auth redirect option as it will be done in the new middleware.

      nuxt.config.js:

      router: {
      		middleware: ['auth-guard'],
      },
      auth: {
          vuex: { namespace: '_auth' },
          redirect: {
               login: false,
               logout: '/login',
               callback: false,
               home: false,
           },
           localStorage: false,
      },
      strategies: {
        local: {
          endpoints: {
            login: {
              url: '/auth/login',
              method: 'post',
              propertyName: 'access_token',
            },
            logout: {
              url: '/auth/logout',
              method: 'post',
            },
            user: {
              url: '/auth/me',
              method: 'get',
              propertyName: false,
            },
          },
        },
      }
    • When the route path is different than login save such path and redirect to it if the user is NOT logged in.

      middleware/auth-guard.js

      export default function({ $auth, route, redirect }) {
      if (route.path !== '/login') {
      	const REDIRECT_URL = '/login?redirect=' + route.path
      	if (!$auth.loggedIn) {
        		redirect(REDIRECT_URL)
      	}
       }
      }
  • Use the query params for redirect after a successful login to the saved path if exists.

pages/login.vue

  const handleSubmit = async () => {
      try {
        errorMsg.value = undefined
        await form.submit()
        let redirect_url = root.$route.query.redirect || '/dashboard'
        root.$router.push({
          path: redirect_url,
        })
      } catch (error) {
        errorMsg.value = t(`auth.login.error.${error.code}`)
      }
    }

@kalnode
Copy link

kalnode commented Sep 4, 2021

The snippet posted seems to be triggered on ALL routes.

Do we not want this to only apply to protected routes?

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

No branches or pull requests