Custom sign-in Page
Provider: authjs
To create a custom sign-in page you will need to:
- Create the custom sign-in page: Creating the actual page your user will enter their credentials on OR select their oauth provider (e.g., google, azure, ...)
- Configure the
authjs
-backend-auth-handler to redirect to the custom sign-in page: If a sign-in is triggered or a session check fails, theauthjs
-backend-auth-handler has to forward you to your custom sign-in page, instead of the theauthjs
-backend-auth-handler builtin sign-in page - Optional: Disable the
nuxt-auth
global protection middleware for the custom page if you have it enabled
Create the Custom sign-in Page
To create your custom sign-in page you can use signIn
to directly start a provider-flow once the user selected it, e.g., by clicking on a button on your custom sign-in page. Here is a very simple sign-in page that either directly starts a github-oauth sign-in flow or directly signs in the user via the credentials flow:
<!-- file: ~/pages/login.vue --><template> <div> <p>Sign-In Options:</p> <button @click="signIn('github')">Github</button> <!-- NOTE: Here we hard-coded username and password, on your own page this should probably be connected to two inputs for username + password --> <button @click="signIn('credentials', { username: 'test', password: 'hunter2' })">Username and Password</button> </div></template><script setup lang="ts">definePageMeta({ auth: { unauthenticatedOnly: true, navigateAuthenticatedTo: '/', }})const { signIn } = useAuth()</script>
Note:
- In the above example
username
andpassword
are hard-coded. In your own custom page, these two fields should probably come from inputs on your page. - We disable the global
nuxt-auth
middleware for this page by using the guest modedefinePageMeta({ auth: { unauthenticatedOnly: true, ... } })
, this is only necessary if you have setglobalAppMiddleware: true
in thenuxt-auth
module configuration
If you want to create a custom sign-in page that dynamically offers sign-in options based on your configured providers, you can call getProviders()
first and then iterate over the supported providers to generate your sign-in page.
[email protected]
. If you are on a previous version, use auth: false
instead. This has the downside of not automatically redirecting authenticated users away from the login page.Configure authjs
to redirect to the Custom sign-in Page
Redirects to the sign-in page happen automatically, e.g., when a getSession()
call fails to get a session or when signIn()
is called. By default this redirect sends the user to /api/auth/signin
. To use a custom sign-in page we will have to configure authjs
to send the user to the custom sign-in page instead.
We can apply this configuration in the NuxtAuthHandler
:
// file: ~/server/api/auth/[...].tsimport { NuxtAuthHandler } from '#auth'export default NuxtAuthHandler({ pages: { // Change the default behavior to use `/login` as the path for the sign-in page signIn: '/login' }, providers: [ // ... your provider configuration ]})
We can also configure the default-location for other pages in the pages
configuration, see the NextAuth.js pages docs for more.
Disable the global page protection middleware
As already outlined in the first step, you will need to add:
definePageMeta({ auth: { unauthenticatedOnly: true, navigateAuthenticatedTo: '/', }})
to your login page if you have enabled the global page protection middleware. This is the guest mode and allows unauthenticated users to access the login-page, while authenticated users will be redirected to /
. Not disabling the global middleware would result in an endless loop of redirects. You can change navigateAuthenticatedTo
to any route you like, e.g., /profile
to show authenticated users their profile instead.
If you have not set globalAppMiddleware
or have set it to false
this step does not apply to your application.
[email protected]
. If you are on a previous version, use auth: false
instead. This has the downside of not automatically redirecting authenticated users away from the login page.Optional: Custom Error handling
You can handle sign-in errors yourself by calling signIn
with redirect: false
and inspecting its result for errors. For example:
const { signIn } = useAuth()const mySignInHandler = async ({ username, password }: { username: string, password: string }) => { const { error, url } = await signIn('credentials', { username, password, redirect: false }) if (error) { // Do your custom error handling here alert('You have made a terrible mistake while entering your credentials') } else { // No error, continue with the sign in, e.g., by following the returned redirect: return navigateTo(url, { external: true }) }}
Then call the mySignInHandler({ username, password })
on login instead of the default signIn(...)
method. You can find all possible errors here. This file also contains the default error-messages that nuxt-auth
would show to the user if you would not handle the error manually using redirect: false
.
Provider: local
The only way to use the local provider does not come with a pre-made login page, so you will have to build one yourself. To do so:
- Create the page, e.g.,
pages/login.vue
- Call the
signIn
method with the username and password your user has to enter on this page - Disable the page protection, if you have the global middleware enabled
- Configure
nuxt-auth
to know the place of your login page
A full example login page could look like this:
<!-- file: ~/pages/my-cool-login.vue --><template> <div> <p>Sign-In:</p> <!-- NOTE: Here we hard-coded username and password, on your own page this should probably be connected to two inputs for username + password --> <button @click="signIn('credentials', { username: 'test', password: 'hunter2' })">Username and Password</button> </div></template><script setup lang="ts">definePageMeta({ auth: { unauthenticatedOnly: true, navigateAuthenticatedTo: '/', }})const { signIn } = useAuth()</script>
Then the full nuxt.config.ts
for this would look like this:
export default defineNuxtConfig({ modules: ['@sidebase/nuxt-auth'], auth: { provider: { type: 'local', pages: { login: '/my-cool-login' }, }, globalAppMiddleware: { isEnabled: true } }})
Note:
- if your global app middleware is disabled, you have to add
auth: true
to thedefinePageMeta
-code above to correctly enable the guest-mode - the default location set for the
login
page is/login