fix(auth): default signInPath to /api/auth/signin (NextAuth v5)
Provider-specific paths like /api/auth/signin/keycloak are POST only
in NextAuth v5 — they're the form-submit endpoint with CSRF. A GET
redirect there bounces to /api/auth/error?error=Configuration with
"UnknownAction".
/api/auth/signin (no provider segment) is the GET-accessible page
that lists configured providers. Apps that want one-click Keycloak
should set signInPath to a custom page that calls signIn('keycloak').
Repros against next-auth 5.0.0-beta.31 on Next 16.1.1. Pre-existing
bug in createAuth + createAuthMiddleware + signInRedirect; surfaced
when first user-driven login was attempted against the live CRM.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,9 @@ export type { SessionUser } from "./types";
|
|||||||
*/
|
*/
|
||||||
export function signInRedirect(callbackUrl?: string): void {
|
export function signInRedirect(callbackUrl?: string): void {
|
||||||
if (typeof window === "undefined") return;
|
if (typeof window === "undefined") return;
|
||||||
const target = "/api/auth/signin/keycloak";
|
// Match the server-side default. /api/auth/signin/<provider> is POST
|
||||||
|
// only in NextAuth v5 — a GET navigation there returns UnknownAction.
|
||||||
|
const target = "/api/auth/signin";
|
||||||
const url = new URL(target, window.location.origin);
|
const url = new URL(target, window.location.origin);
|
||||||
url.searchParams.set("callbackUrl", callbackUrl ?? window.location.pathname);
|
url.searchParams.set("callbackUrl", callbackUrl ?? window.location.pathname);
|
||||||
window.location.href = url.toString();
|
window.location.href = url.toString();
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ export interface AuthMiddlewareOptions {
|
|||||||
*/
|
*/
|
||||||
export function createAuthMiddleware(opts: AuthMiddlewareOptions = {}) {
|
export function createAuthMiddleware(opts: AuthMiddlewareOptions = {}) {
|
||||||
const publicRoutes = opts.publicRoutes ?? [];
|
const publicRoutes = opts.publicRoutes ?? [];
|
||||||
const signInPath = opts.signInPath ?? "/api/auth/signin/keycloak";
|
// See createAuth for why /api/auth/signin (not /api/auth/signin/keycloak):
|
||||||
|
// provider-specific paths are POST-only in NextAuth v5.
|
||||||
|
const signInPath = opts.signInPath ?? "/api/auth/signin";
|
||||||
|
|
||||||
return function middleware(req: NextRequestLike) {
|
return function middleware(req: NextRequestLike) {
|
||||||
const { pathname } = req.nextUrl;
|
const { pathname } = req.nextUrl;
|
||||||
|
|||||||
@@ -63,7 +63,13 @@ export interface AuthBundle {
|
|||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function createAuth(opts: CreateAuthOptions): AuthBundle {
|
export function createAuth(opts: CreateAuthOptions): AuthBundle {
|
||||||
const signInPath = opts.signInPath ?? "/api/auth/signin/keycloak";
|
// NextAuth v5: provider-specific paths like /api/auth/signin/keycloak
|
||||||
|
// are POST-only (CSRF-protected form submit). A GET redirect there
|
||||||
|
// bounces to /api/auth/error?error=Configuration ("UnknownAction").
|
||||||
|
// /api/auth/signin (no provider) is the GET-accessible page that
|
||||||
|
// lists configured providers. Apps wanting one-click Keycloak can
|
||||||
|
// override signInPath with a custom page that calls signIn('keycloak').
|
||||||
|
const signInPath = opts.signInPath ?? "/api/auth/signin";
|
||||||
const defaultTenantId =
|
const defaultTenantId =
|
||||||
opts.defaultTenantId ?? "00000000-0000-0000-0000-000000000000";
|
opts.defaultTenantId ?? "00000000-0000-0000-0000-000000000000";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user