Skip to content

Conversation

@rodrigo-fournier-immutable
Copy link
Contributor

Summary

Implement default authentication for @imtbl/wallet, @imtbl/auth-next-client, and @imtbl/auth-next-server packages to provide zero-config setup for developers.

This PR adds:

  • ✅ Comprehensive E2E tests for wallet package default auth
  • ✅ Default auth implementation for auth-next-server with auto-detection
  • ✅ Default auth implementation for auth-next-client with optional config

Changes

1. Wallet Package Tests (test(wallet))

  • Add 463 lines of comprehensive E2E tests for default auth functionality
  • Test coverage:
    • Auth instance creation with auto-configuration
    • ClientId auto-detection (sandbox vs production)
    • PassportDomain derivation from chain config
    • Popup callback handling for OAuth flow
    • Query string management during auth callback
    • Provider creation without external getUser
    • Error handling for auth failures
  • All 28 tests passing (existing + new tests)

2. Auth-Next-Server (feat(auth-next-server))

  • New function: createDefaultAuthConfig() with optional configuration
    • All parameters are now optional with sensible defaults
    • Auto-detects clientId based on environment (sandbox vs production)
    • Auto-derives redirectUri from window.location.origin + '/callback'
    • Uses default values for audience, scope, and authenticationDomain
  • Added constants:
    • DEFAULT_PRODUCTION_CLIENT_ID: Public Immutable production client ID
    • DEFAULT_SANDBOX_CLIENT_ID: Public Immutable sandbox client ID
    • DEFAULT_REDIRECT_URI_PATH: Default callback path
  • Helper functions:
    • isSandboxEnvironment(): Detects sandbox vs production
    • deriveDefaultClientId(): Auto-detects clientId
    • deriveDefaultRedirectUri(): Auto-derives redirectUri

3. Auth-Next-Client (feat(auth-next-client))

  • Updated hooks: useLogin and useLogout now accept optional config
    • All config fields are optional with auto-detection
    • Auto-detects: clientId, redirectUri, popupRedirectUri, logoutRedirectUri
    • Uses sensible defaults for scope, audience, authenticationDomain
  • Helper functions:
    • createDefaultLoginConfig(): Creates complete LoginConfig with defaults
    • createDefaultLogoutConfig(): Creates complete LogoutConfig with defaults
    • Environment detection and URL derivation functions
  • Exported constants: All default values exported for consumer use

Usage Examples

Before (Required Configuration)

Server (lib/auth.ts):

import NextAuth from "next-auth";
import { createAuthConfig } from "@imtbl/auth-next-server";

const config = {
  clientId: process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID!,
  redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
};

export const { handlers, auth, signIn, signOut } = NextAuth(createAuthConfig(config));

Client (components/LoginButton.tsx):

const loginConfig = {
  clientId: process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID!,
  redirectUri: `${process.env.NEXT_PUBLIC_BASE_URL}/callback`,
};

const { loginWithPopup } = useLogin();
await loginWithPopup(loginConfig);

After (Zero Configuration)

Server (lib/auth.ts):

import NextAuth from "next-auth";
import { createDefaultAuthConfig } from "@imtbl/auth-next-server";

// Zero config! Everything is auto-detected
export const { handlers, auth, signIn, signOut } = NextAuth(createDefaultAuthConfig());

Client (components/LoginButton.tsx):

const { loginWithPopup } = useLogin();
// Zero config! Everything is auto-detected
await loginWithPopup();

const { logout } = useLogout();
// Zero config! Everything is auto-detected
await logout();

With Custom Configuration (Optional)

You can still override any field as needed:

// Server - override specific fields
export const { handlers, auth } = NextAuth(createDefaultAuthConfig({
  clientId: process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID, // Use your own client ID
}));

// Client - override specific fields
await loginWithPopup({
  clientId: process.env.NEXT_PUBLIC_IMMUTABLE_CLIENT_ID,
  redirectUri: '/custom-callback',
});

Auto-Detection Logic

ClientId Detection

  • Checks window.location.hostname for 'sandbox' or 'localhost'
  • Sandbox: Uses DEFAULT_SANDBOX_CLIENT_ID
  • Production: Uses DEFAULT_PRODUCTION_CLIENT_ID
  • Uses public Immutable client IDs for development convenience
  • ⚠️ Production apps should use their own client ID from Immutable Hub

RedirectUri Derivation

  • Server-side: Returns path only (/callback)
  • Client-side: Combines window.location.origin + '/callback'
  • Works seamlessly in both environments

Testing

  • ✅ ESLint passed for all packages
  • ✅ All wallet tests passing (28/28)
  • ✅ Transpiler build successful for auth packages
  • ⚠️ TypeScript typegen warnings expected (peer dependencies are optional)

Breaking Changes

None. This is a fully backward-compatible addition:

  • Existing createAuthConfig() still works as before
  • Existing useLogin() and useLogout() usage still works
  • New functionality is purely additive

Related Work

Test Plan

  • Test wallet package default auth with all test cases
  • Test auth-next-server with zero config in a Next.js app
  • Test auth-next-client hooks with zero config
  • Test sandbox vs production client ID detection
  • Test custom config overrides
  • Test with actual Immutable auth flows (popup, embedded, redirect)
  • Verify backward compatibility with existing implementations

Notes

  • This uses public Immutable client IDs for development convenience
  • For production apps, developers should use their own client ID from Immutable Hub
  • All defaults can be overridden by passing partial config objects
  • Server-side functions are safe (return sensible defaults when window is unavailable)

Made with Cursor

Add E2E tests for default auth functionality in wallet package.

Tests cover:
- Auth instance creation with auto-configuration
- ClientId auto-detection (sandbox vs production)
- PassportDomain derivation from chain config
- Popup callback handling for OAuth flow
- Query string management during auth callback
- Provider creation without external getUser
- Error handling for auth failures

This validates the default auth implementation added by Shine Li
in PR #2768 (feat(passport): nextjs packages).

All 28 tests passing:
- 7 tests for Auth instance creation
- 6 tests for clientId auto-detection
- 4 tests for popup callback handling
- 4 tests for provider creation
- 2 tests for error handling
- 5 tests for existing functionality

Co-authored-by: Cursor <cursoragent@cursor.com>
@nx-cloud
Copy link

nx-cloud bot commented Feb 10, 2026

View your CI Pipeline Execution ↗ for commit ca71a4f

Command Status Duration Result
nx affected -t build,lint,test ✅ Succeeded 1m 22s View ↗
nx run-many -p @imtbl/sdk,@imtbl/checkout-widge... ✅ Succeeded 17s View ↗

☁️ Nx Cloud last updated this comment at 2026-02-10 06:15:49 UTC

…etection

Implement default authentication for auth-next-client/server packages
to provide zero-config setup for developers.

auth-next-server changes:
- Add createDefaultAuthConfig() function with optional configuration
- Auto-detect clientId based on environment (sandbox vs production)
- Auto-derive redirectUri from window.location.origin + '/callback'
- Export default client IDs and constants for consumer use
- Uses public Immutable client IDs for development convenience

auth-next-client changes:
- Update useLogin hook to accept optional config (all fields)
- Update useLogout hook to accept optional config
- Add helper functions to create complete configs with defaults
- Auto-detect clientId, redirectUri, popupRedirectUri, logoutRedirectUri
- Export default constants for direct consumer use

This enables minimal setup:
  // Server (lib/auth.ts)
  export const { handlers, auth } = NextAuth(createDefaultAuthConfig());

  // Client
  const { loginWithPopup } = useLogin();
  await loginWithPopup(); // No config needed!

  const { logout } = useLogout();
  await logout(); // No config needed!

Consumers can still override any field as needed for production use.

Related to wallet package default auth implementation (PR #2768).

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant