Support extending session length via "Remember Me" checkbox #1582
Replies: 15 comments 1 reply
-
Has there been any progress on this feature, or a way to get similar behavior? |
Beta Was this translation helpful? Give feedback.
-
You're welcome to implement it @rancou ;) |
Beta Was this translation helpful? Give feedback.
-
Hey guys! I can work on this feature ;) |
Beta Was this translation helpful? Give feedback.
-
@JoaoPedroAS51 Any news?) |
Beta Was this translation helpful? Give feedback.
-
Actually setCookie method accepts options object auth-module/src/core/storage.ts Line 231 in 3f0073b |
Beta Was this translation helpful? Give feedback.
-
@gerardolopezduenas not super familiar with this stuff, how would/should I make nuxt-auth-module setCookie with this option? |
Beta Was this translation helpful? Give feedback.
-
you can do something like this: this.$auth.$storage.setCookie('cookieName', 'cookieValue', { expires: 5 //this should be days } |
Beta Was this translation helpful? Give feedback.
-
thanks for the example, really appreciate it @gerardolopezduenas |
Beta Was this translation helpful? Give feedback.
-
Today i made this feature and this is my trick. (Using new codes in my below comment) |
Beta Was this translation helpful? Give feedback.
-
@dukinfotech Why don't you post it as code? |
Beta Was this translation helpful? Give feedback.
-
For anyone who like my approach way. By default, cookies expire date will be reset when refresh the window (Press F5). So, you need set them again in layout component. And this is my new codes.
File remember-me.js (folder mixins)
And finally, import remember-me mixin to default layout (and others if you are using multi-layout). |
Beta Was this translation helpful? Give feedback.
-
@dukinfotech Expiration / Max-age of cookies was changed but still comes back to default value (session). |
Beta Was this translation helpful? Give feedback.
-
I'm surprised that this is not documented. Instead of manually setting each individual auth cookie expiration, like in the @dukinfotech's example, you can also modify the default nuxt auth cookie Here is a full example: Lets say that this is your auth setup in auth: {
cookie: {
prefix: 'auth.',
options: {
secure: process.env.NODE_ENV === 'production'
}
}
} Then in you login form component, you can set your own "remember me" cookie based on the user selection, eg: methods: {
login() {
// authenticate...
if (this.remember) { // has selected the "Remember me" checkbox
this.$auth.$storage.setCookie('remember_expires', 7, { expires: 7 });
} else {
this.$auth.$storage.removeCookie('remember_expires');
}
}
} An lastly, you have to update the nuxt-auth cookie expires option. This could be done in different ways - middleware, in you layout components, etc., but keep in mind that this code need to run on each navigation/page refresh, because nuxt auth will resets the cookies // create a new file middleware/remember.js and register it as a global middleware in your nuxt.config.js
// (more info on middlewares - https://nuxtjs.org/docs/directory-structure/middleware/)
export default function ({ $auth }) {
const rememberExpires = $auth.$storage.getCookie('remember_expires');
if (rememberExpires) {
$auth.options.cookie.options.expires = rememberExpires
} else {
$auth.options.cookie.options.expires = null // reset to "session"
}
} |
Beta Was this translation helpful? Give feedback.
-
You can also go the other way around. Set your expiration in const redirectTo = this.$auth.$storage.getUniversal('redirect'); // You might want to grab it before
if (!this.remember) {
this.$auth.$storage.options.cookie = false;
this.$auth.$storage.options.localStorage = false;
}
await this.$auth.loginWith(/* ... */);
this.$router.push(redirectTo || '/'); Tokens will still be stored in RAM (vuex store only), so if page is closed or reloaded user will be redirected to login page. |
Beta Was this translation helpful? Give feedback.
-
I've created a custom scheme based off of the refresh scheme to add a new myproject/schemes/customScheme.js (click to expand)import { RefreshScheme, Token, RequestHandler } from '~auth/runtime'
const DEFAULTS = {
name: 'local',
remember: {
default: true,
duration: 30,
},
endpoints: {
login: {
url: '/api/auth/login',
method: 'post'
},
logout: {
url: '/api/auth/logout',
method: 'post'
},
user: {
url: '/api/auth/user',
method: 'get'
}
},
token: {
property: 'token',
type: 'Bearer',
name: 'Authorization',
maxAge: 1800,
global: true,
required: true,
prefix: '_token.',
expirationPrefix: '_token_expiration.'
},
user: {
property: 'user',
autoFetch: true
},
clientId: false,
grantType: false,
scope: false
}
export default class CustomScheme extends RefreshScheme {
constructor(
$auth,
options,
...defaults
) {
super(
$auth,
options,
...defaults,
DEFAULTS
)
// Remove cookie if it is the same as default
if ($auth.$storage.getCookie('remember') === options.remember.default) {
$auth.$storage.removeCookie('remember')
}
// Get remember from cookie that differs from default or default and set cookie expiry
const remember = $auth.$storage.getCookie('remember') ?? options.remember.default
$auth.options.cookie.options.expires = remember ? options.remember.duration : null
// Initialize Token instance
this.token = new Token(this, this.$auth.$storage)
// Initialize Request Interceptor
this.requestHandler = new RequestHandler(this, this.$auth.ctx.$axios)
}
// Override `login` method of `local` scheme
async login(
endpoint,
{ reset = true, remember = this.options.remember.default } = {}
) {
if (!this.options.endpoints.login) {
return
}
// Ditch any leftover local tokens before attempting to log in
if (reset) {
this.$auth.reset({ resetInterceptor: false })
}
// Check if auth cookies should be remembered
this.$auth.options.cookie.options.expires = remember ? this.options.remember.duration : null
// Set cookie if remember is not the default value
if (this.options.remember.default !== remember) {
this.$auth.$storage.setCookie('remember', remember)
} else {
this.$auth.$storage.removeCookie('remember')
}
// Add client id to payload if defined
if (this.options.clientId) {
endpoint.data.client_id = this.options.clientId
}
// Add grant type to payload if defined
if (this.options.grantType) {
endpoint.data.grant_type = this.options.grantType
}
// Add scope to payload if defined
if (this.options.scope) {
endpoint.data.scope = this.options.scope
}
// Make login request
const response = await this.$auth.request(
endpoint,
this.options.endpoints.login
)
// Update tokens
this.updateTokens(response)
// Initialize request interceptor if not initialized
if (!this.requestHandler.interceptor) {
this.initializeRequestInterceptor()
}
// Fetch user if `autoFetch` is enabled
if (this.options.user.autoFetch) {
await this.fetchUser()
}
return response
}
reset({ resetInterceptor = true } = {}) {
this.$auth.$storage.removeCookie('remember') // Remove cookie
this.$auth.setUser(false)
this.token.reset()
if (resetInterceptor) {
this.requestHandler.reset()
}
}
} Use the scheme ( auth: {
// ...
strategies: {
local: {
- scheme: 'refresh',
+ scheme: '~/schemes/customScheme',
+ remember: {
+ default: true, // Default
+ duration: 30, // Duration in days / expire
+ },
// ...
}
} Now I can do this: <template>
<div>
<form @submit.prevent="onSubmit">
<div>username</div>
<div><input v-model="form.username" type="text" /></div>
<div>password</div>
<div><input v-model="form.password" type="text" /></div>
<div><input v-model="remember" type="checkbox" /> Remember me</div>
<input type="submit">
</form>
</div>
</template>
<script>
export default {
name: 'LoginComponent',
data() {
return {
remember: this.$auth.getStrategy().options.remember.default
form: {
username: '',
password: '',
}
}
},
methods: {
onSubmit() {
this.$auth.loginWith(
'local',
{ data: this.form },
{ remember: this.remember } // This
).then(() => { /* ... */ })
}
}
}
</script> With this, it will store the cookies for the configured amount of days or just session. This is based on the default or what's passed to I hope this helps someone who was facing the same issue as me. |
Beta Was this translation helpful? Give feedback.
-
What problem does this feature solve?
It's Normal for website login, to have a choice of "remember me", in that case user should not need to input credentials next time, until the cookies expired.
Today, the expires can be set in
nuxt.config.js->auth->cookie->options
.But it's very hard to programatically change it in Vue component, login page for example.
There is API of
this.$auth.$storage.setCookie(key, val, isJson)
, but only change cookies related value, and can not change globally the expires value, so it will not be valid eventually.There are another API:
this.$auth.$storage.setUniversal()
but the expires options can not be passed in currently.I'm not sure if this is a bug or I made some mistake, but it's essential to enable this feature.
What does the proposed changes look like?
Enable programatically change the cookie expires value globally, in Vue component
Beta Was this translation helpful? Give feedback.
All reactions