How to hide provider (credentials) from signIn page? #12525
Replies: 1 comment
-
I ran into the same problem. The correct solution would be to implement a customized /signin page that renders whatever provider you see fit but with the defaults its still possible using a bit complex setup. My approach is: NextJS with NextAuth customized GET handler
in // /server/auth/providers/appkit.ts
export function AppKit() {
return CredentialsProvider({
name: 'SIWE',
id: 'appkit',
credentials: {
message: {
label: 'Message',
type: 'text',
placeholder: '0x0',
},
signature: {
label: 'Signature',
type: 'text',
placeholder: '0x0',
},
},
async authorize(credentials: { message: string; signature: string }) {
....
// /server/auth/providers/credentials.ts
export function Credentials() {
return CredentialsProvider({
name: 'Credentials',
id: 'credentials',
credentials: {
username: { label: 'Username', type: 'text', placeholder: 'jsmith' },
password: { label: 'Password', type: 'password' },
},
async authorize(credentials: { username: string; password: string }) {
.... // /server/auth/active/config.ts
import { Credentials } from '@/server/auth/providers/credentials'
import { AppKit } from '@/server/auth/providers/appkit'
export const {
providers: [ Credentials, AppKit ],
events: {....} so far this is working as the docs suggest, you export NextAuth(config) and use them in import {authConfig} from '@/server/auth/active/config`
const nextAuth = NextAuth(authConfig);
const {
auth: uncachedAuth,
handlers,
signIn,
signOut,
} = nextAuth
const auth = cache(uncachedAuth);
export { auth, handlers, signIn, signOut }; now assuming the GET route-handler is used (handlers.GET) you'll get the two (or many) providers you configure in the ui. The question was how to remove one (or many) of them and according to the next-auth/auth core sources there is no such thing in the sources to reduce the providers. I'd like to pass a property like hidden in the provider but the renderPage just maps the array. So instead of fiddling with the internals, i create a ui-config with just the provider(s) that should be displayed on signin and override the GET handler: // /server/auth/ui/config.ts
import { Credentials } from '@/server/auth/providers/credentials'
export const authConfig = {
providers: [Credentials()]
} satisfies NextAuthConfig; this config should only satisfy next-auth so its as empty as possible and only lists the providers we want to display. in our import NextAuth from 'next-auth';
import { cache } from 'react';
import { authConfig as authConfigActive} from './active/config';
import { authConfig as authConfigUi } from './ui/config';
const nextAuthActive = NextAuth(authConfigActive);
const nextAuthUi = NextAuth(authConfigUi);
const {
auth: uncachedAuth,
handlers: authHandlers,
signIn,
signOut,
} = nextAuthActive
const auth = cache(uncachedAuth);
function handleUiGET(req: NextRequest, res: NextResponse) {
const requestUrl = new URL(req.url);
if (requestUrl.pathname === '/api/auth/signin') {
return nextAuthUi.handlers.GET(req, res);
}
return nextAuthActive.handlers.GET(req, res);
}
const handlers = {
POST: authHandlers.POST,
GET: handleUiGET,
};
export { auth, handlers, signIn, signOut }; This causes the /api/auth/signin request to render the GET handler that was created by the NextAuth(authConfigUi) but all the POST requests have the extra provider(s) available. The GET requests to /api/auth/providers, /api/auth/crsf etc are also handled by the nextAuthActive.GET I found this solution because in /app/middleware.ts nextjs(15) started to misbehave as it tried to import alot of dependencies that were not fit for the middleware-environment. all i needed was a 'getSession' but the new auth deprecated that and wants us to use // /server/auth/middleware/config.ts
import { jwt } from '@/server/auth/jwt';
import { session } from '@/server/auth/session';
export const authConfig = {
providers: [],
events: {},
callbacks: {
jwt,
session,
},
session: {
strategy: 'jwt',
},
} satisfies NextAuthConfig;
// /server/auth/middleware/index.ts
import NextAuth from 'next-auth';
import { authConfig } from './config';
const { auth} = NextAuth(authConfig);
export { auth };
// /middleware.ts
import { auth } from '@/server/auth/middleware';
export default async function middleware(req: NextRequest) {
const isAuthenticated = await auth();
if (!isAuthenticated) {
const returnUrl = new URL(req.nextUrl.pathname, process.env.NEXTAUTH_URL);
return NextResponse.redirect(
new URL(
'/api/auth/signin?callbackUrl=' + encodeURIComponent(returnUrl),
req.nextUrl,
),
);
}
return NextResponse.next();
}
export const config = {
matcher: ['/protected','/path','/names'],
}; now before i circle back and implement a custom page (where the user can select if they want to use credential signin/signup or siwe using the styling of the page) i wanted to share that findings with anyone who still wants to hide providers, a thing i already had to implement in next-auth ~v2 along time ago. very useful for m2m logins that the oidc-users should not see and the final warning that doing this might not be a stable solution in the future and keep in mind the warnings of the next-auth docs: 🔥 The functionality provided for credentials based authentication is intentionally limited to discourage use of passwords due to the inherent security risks associated with them and the additional complexity associated with supporting usernames and passwords. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Is there an easy way to hide the credentials provider on the automatic sign-in page?
I'm using the credentials provider for SIWE login, but I don’t want it to be visible on the sign-in page.
I’ve found some complex examples of how to achieve this using a custom login page, but I’m hoping there’s a simpler way to customize the pre-built sign-in page to hide it.
Thanks in advance for any advice!
Beta Was this translation helpful? Give feedback.
All reactions