Integration Guide
Learn how to integrate Aura Auth with JavaScript frameworks and build custom integrations.
Aura Auth is a framework-agnostic and modular authentication system designed for TypeScript applications. Its core is built on Web Standards, including the Request and Response interfaces, and supports OAuth 2.0 and OpenID Connect (OIDC).
Because Aura Auth uses standard HTTP requests and responses, it can be integrated with JavaScript runtimes and frameworks that support server-side request handling.
For reference implementations, see Aura Auth Apps.
This guide explains the architecture of Aura Auth integrations and how to create a dedicated integration package for a framework or library.
Architecture
Core Package
The @aura-stack/auth package provides the core createAuth function and authentication logic. It returns an AuthInstance with the following properties:
handlers: HTTP handlers for authentication endpoints.api: Server-side API functions, includingsignIn,signOut, andgetSession.jose: JWT and cryptographic utilities.
The core package handles authentication independently of any specific framework. Integrations connect this functionality to a framework's request lifecycle, routing system, and context APIs.
Integration Packages
Integration packages provide framework-specific adapters around the core authentication functionality. Depending on the framework, an integration may:
- Wrap the core
createAuthfunction with framework-specific configuration or utilities. - Provide handler adapters, such as
toHandler, to connect Aura Auth handlers to the framework's request lifecycle. - Expose middleware or plugins, such as
withAuth, to make session data available in the framework's context. - Export framework-specific types while preserving the core API's type information.
Not every integration requires all these utilities. The implementation should follow the framework's conventions and expose only the functionality that is useful for that framework.
Generic Types
The core createAuth function accepts generic type parameters for the identity and sign-up schema:
createAuth<Identity, SignUpSchema>(
config: AuthConfig<Identity, SignUpSchema>,
)IdentityextendsIdentitiesand defines the application's identity structure.SignUpSchemaextendsSchemaTypesand defines the sign-up validation schema. Supported schema libraries depend on the core package's current type definitions.
A dedicated integration should preserve these generic parameters when wrapping createAuth so applications retain type inference and type safety.
Creating a Dedicated Integration Package
For integrations that require framework-specific behavior or are intended for community distribution, use the existing integration packages as implementation references.
Scaffold the Integration
Use the create:integration command to scaffold a package from the integration template:
pnpm create:integration --name my-frameworkThe scaffold command is intended to:
- Copy the integration template into
packages/my-framework. - Create the initial package structure.
- Configure TypeScript and build tooling.
Sync Core Modules
From the new package directory, run the module synchronization script:
cd packages/my-framework
pnpm sync:modulesThe script synchronizes the shared modules required by the integration. These may include:
oauth: OAuth provider implementations.identity: Identity schema types and utilities.crypto: Cryptographic utilities.shared: Shared utilities.cookies: Cookie management utilities.
If the script manages package exports, verify that the required modules are exported and that the resulting package builds correctly.
Implement a Framework-Specific createAuth
Create a framework-specific createAuth wrapper that delegates authentication configuration and initialization to the core implementation.
The wrapper should:
- Preserve the core generic parameters, including
IdentityandSignUpSchema. - Pass the authentication configuration to the core
createAuthfunction. - Add framework-specific utilities where necessary.
- Return an instance that preserves the core
AuthInstanceAPI and exposes the integration's additional utilities.
The implementation will vary by framework. Keep the wrapper thin and avoid duplicating authentication logic that already belongs to the core package.
Define Instance Types
Define the return type of the framework-specific createAuth function. It should preserve the core instance's types and describe any additional framework-specific properties, such as:
- Handler adapter signatures.
- Middleware or plugin signatures.
- Framework-specific request or context types.
Export the integration's public types from an appropriate entry point. Re-export core types when they are part of the intended public API.
Implement a Handler Adapter
Implement a handler adapter that connects the framework's request lifecycle to Aura Auth's Web Standard Request and Response interfaces.
The adapter should:
- Accept the framework's request or context object.
- Obtain or construct a standard
Request. - Pass the request to the appropriate Aura Auth handler.
- Return the resulting
Responsein the format expected by the framework.
Prefer passing through native Request and Response objects when the framework supports them. If conversion is required, preserve relevant request data, headers, cookies, and response semantics.
Implement Middleware or a Plugin
If the framework supports middleware or plugins, consider providing a utility that exposes session information to route handlers or other parts of the application.
A typical implementation should:
- Accept an initialized auth instance.
- Retrieve session information through
api.getSession. - Attach the session to the framework's request context using its established middleware or plugin conventions.
- Define explicit behavior for missing sessions and errors.
Treat an unauthenticated request separately from an unexpected error where the framework's API permits it. Set the session to null only when that matches the intended contract, and avoid silently hiding failures that should be reported or logged.
Export the Public API
Create the package entry point and export the supported integration API. For example:
// packages/my-framework/src/index.ts
export { createAuth } from "./createAuth"
export type {
User,
Session,
AuthConfig,
AuthInstance,
} from "@aura-stack/auth/types"Adjust the imports and exported types to match the actual package structure and the public types available in the core package. Prefer stable public entry points over internal module paths.
Add an Example Application
Add an example application under apps/ to demonstrate installation, configuration, and use of the integration.
For example:
apps/
└── my-framework/
├── src/
│ ├── lib/
│ │ ├── handler.ts
│ │ └── with-auth.ts
│ └── index.ts
├── package.json
└── tsconfig.jsonAdapt the structure to the framework's conventions. The example should demonstrate how to configure Aura Auth, register its handlers, and access session information where applicable.
Return Object Requirements
A framework-specific createAuth wrapper should preserve the core instance's public API.
At a minimum, this means retaining the core properties required by the integration, such as:
handlers: Authentication HTTP handlers.api: Server-side authentication and session functions.jose: JWT and cryptographic utilities, if exposed by the core instance.session: Session management utilities, if exposed by the core instance.
The exact properties should match the AuthInstance type exported by the version of @aura-stack/auth being integrated. Framework-specific utilities should extend the core API rather than replace or unintentionally narrow it.
Best Practices
- Preserve generic types. Carry
IdentityandSignUpSchemathrough the wrapper and its return type to maintain type inference. - Keep the integration thin. Delegate authentication logic to the core package and focus on framework-specific request handling and context integration.
- Re-export public types deliberately. Expose the core types consumers need without depending on unstable internal modules.
- Document framework-specific behavior. Use JSDoc and integration documentation to explain added utilities, expected inputs, and error handling.
- Provide a working example. Include an example application that demonstrates the integration's main use cases.
- Test the adapter and middleware. Cover request and response conversion, session retrieval, unauthenticated requests, and error handling.
- Keep synchronized modules up to date. Run
pnpm sync:modulesafter core changes when the integration relies on synchronized modules, then verify the generated code, exports, and build. - Verify runtime compatibility. Test against the runtimes and framework versions the integration claims to support.