Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions packages/plugins/plugin-auth/src/auth-manager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,30 @@ describe('AuthManager', () => {
});
});

describe('onAPIError.errorURL (objectui#2458 item 1)', () => {
it('points browser-flow errors at the console login page so ?error= is surfaced', async () => {
let capturedConfig: any;
(betterAuth as any).mockImplementation((config: any) => {
capturedConfig = config;
return { handler: vi.fn(), api: {} };
});

const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const manager = new AuthManager({
secret: 'test-secret-at-least-32-chars-long',
baseUrl: 'http://localhost:3000',
});
await manager.getAuthInstance();
warnSpy.mockRestore();

// Default error redirect (`${baseURL}/error` → `/?error=…`) loses the
// query on the root→console bounce; the login page renders it instead.
expect(capturedConfig.onAPIError).toEqual({
errorURL: 'http://localhost:3000/_console/login',
});
});
});

describe('emailAndPassword passthrough', () => {
it('should default emailAndPassword to enabled: true', async () => {
let capturedConfig: any;
Expand Down
11 changes: 11 additions & 0 deletions packages/plugins/plugin-auth/src/auth-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,17 @@ export class AuthManager {
}),
},

// Where better-auth redirects a browser flow that fails server-side —
// most importantly an OAuth callback error (expired/replayed `state`,
// IdP error). The default is `${baseURL}/error`, which bounces to
// `/?error=<code>`; the root→console redirect then DROPS the query, so
// the user lands on a silent login form right after a successful IdP
// sign-in (objectui#2458 item 1). Point it at the console login page,
// which renders `?error=` as an inline banner.
onAPIError: {
errorURL: this.getConsolePageUrl('/login'),
},

// Trusted origins for CSRF protection (supports wildcards like "https://*.example.com")
// Auto-includes origins from OS_CORS_ORIGIN env var so CORS and CSRF stay in sync.
...(() => {
Expand Down