Remember me
Implementing a "remember me" feature would greatly enhance the user experience by eliminating the need for users to log in every time they visit. This feature automatically logs users in after their session expires. It works by generating a cryptographically secure token and saving it as a cookie in the user's browser.
Creating the remember me tokens table
The remember me tokens will be stored in a new table called remember_me_tokens
, which we need to create:
node ace make:migration remember_me_tokens
Once created, we will modify the migration as below:
import { BaseSchema } from '@adonisjs/lucid/schema'
export default class extends BaseSchema {
protected tableName = 'remember_me_tokens'
async up() {
this.schema.createTable(this.tableName, (table) => {
table.increments()
table
.integer('tokenable_id')
.notNullable()
.unsigned()
.references('id')
.inTable('users')
.onDelete('CASCADE')
table.string('hash').notNullable().unique()
table.timestamp('created_at').notNullable()
table.timestamp('updated_at').notNullable()
table.timestamp('expires_at').notNullable()
})
}
async down() {
this.schema.dropTable(this.tableName)
}
}
The remember_me_tokens
table will consist of six columns. The key columns are:
tokenable_id
: This column stores the ID of the user associated with the remember me token.hash
: This column contains the hash of the token.expires_at
: This column indicates when the token will expire, based on the setting defined asrememberMeTokensAge
.
In the down
method of the migration, we will simply drop the table.
Finally, we need to run the migration:
node ace migration:run
We should now have a remember_me_tokens
table in the database.
Enabling remember me tokens
To use the "Remember Me" feature, we first need to enable it in config/auth.ts
. We do this by setting useRememberMeTokens
to true
, which indicates that we want to enable remember me tokens. After that, we need to specify the duration for which these tokens will remain valid.
const authConfig = defineConfig({
default: 'web',
guards: {
web: sessionGuard({
useRememberMeTokens: true,
rememberMeTokensAge: '2 years',
provider: sessionUserProvider({
model: () => import('#models/user'),
}),
}),
},
})
Next, we must configure the tokens provider, which will be responsible for reading and writing the tokens. This can be accomplished by defining a static property on the User
model:
import { DbRememberMeTokensProvider } from '@adonisjs/auth/session' // [!code]
export default class User extends compose(BaseModel, AuthFinder) {
...
static rememberMeTokens = DbRememberMeTokensProvider.forModel(User) // [!code]
}
Adding the remember me checkbox
We don’t need to remember every user who logs in, only those who choose to be remembered. To achieve this, we will add a checkbox that users can tick to indicate they want to be remembered. This checkbox will be placed after the password field:
...
<form>
...
<div class="flex items-center gap-x-3">
<input id="remember" name="remember" type="checkbox" class="text-neutral-800 bg-neutral-50 border-neutral-300 rounded focus:border-neutral-300 focus:ring-neutral-800 disabled:cursor-not-allowed disabled:opacity-75">
<label for="remember" class="text-sm">Remember me</label>
</div>
...
</form>
..

Remembering users
Once we have everything set up, we can implement the functionality to remember users during login. Let’s modify the store
method in the AuthController
:
async store({ request, auth, session, response }: HttpContext) {
try {
const { email, password, remember } = request.only(['email', 'password', 'remember'])
const user = await User.verifyCredentials(email, password)
await auth.use('web').login(user, !!remember)
session.flash({
notification: {
type: 'success',
message: 'Welcome back!',
},
})
return response.redirect().toRoute('home')
} catch (error) {
session.flash({
notification: {
type: 'error',
message: 'Invalid credentials.',
},
})
return response.redirect().back()
}
}
In addition to the email and password, we also obtain the "remember" value from the form data. The login
method accepts an optional second argument, which is used to create a "remember me" token. This token allows users to be automatically logged in when their session expires. Therefore, we pass the "remember" value as the second argument to the method. This second argument must be a boolean, so we need to cast the value using !!
to ensure it is a boolean. If the user checks the "remember me" box, the value of "remember" will be true
; otherwise, it will be false
.
Whenever the user’s session expires, AdonisJS will use the "remember me" cookie to verify the token's validity and automatically recreate the logged-in session for the user.
