API reference
Check out our getting started guides:
See the Migration Guide for breaking changes and upgrade instructions.
Configuration
The utility functions of the package all extend the same interface for static configuration options. This enables the use of a centralized configuration object that can be reused throughout the project.
The package provides a configuration factory, enabling auto-completion and type-checking of the configuration object.
createAuthConfig
Create a config object reusable throughout the project, and set compatible options with environment variables.
Configuration
Required options with an environment variable alternatives must be provided either via environment variables or directly in the config object.
- Kraken
- Edge Config
- Encryption
- App Routes
- API Routes
- Customization
- Validation
- i18n
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
krakenConfig.authEndpoint | Kraken auth endpoint | string | KRAKEN_AUTH_ENDPOINT | ⚠️ Required to enable Kraken OAuth |
krakenConfig.graphqlAuthEndpoint | GraphQL endpoint for auth operations | string | KRAKEN_GRAPHQL_AUTH_ENDPOINT | ❌ Defaults to krakenConfig.graphqlEndpoint |
krakenConfig.graphqlEndpoint | Target GraphQL endpoint | string | KRAKEN_GRAPHQL_ENDPOINT | ✅ |
krakenConfig.oauthClientId | Kraken OAuth client ID | string | KRAKEN_OAUTH_CLIENT_ID | ⚠️ Required to enable Kraken OAuth |
krakenConfig.organizationSecretKey | Kraken organization secret key | string | KRAKEN_ORGANIZATION_KEY | ⚠️ Required to enable organization-scoped auth |
krakenConfig.xClientIpSecretKey | Secret key to sign the user IP address | string | KRAKEN_X_CLIENT_IP_SECRET_KEY | ✅ |
Every request to the Kraken API includes the x-kraken-client-ip-authorization
header, which is set with the base 64 encoded value of
krakenConfig.xClientIpSecretKey, and the x-kraken-client-ip header which is
set with the user IP address.
These headers are used by Kraken to attribute requests made from a limited number of IP addresses, e.g. server-side requests, to the actual user IP address, preventing erroneous rate-limiting. More information can be found on this Kraken announcement.
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
edgeConfig.authToken | Vercel Edge Config write access token | string | VERCEL_AUTH_TOKEN | ⚠️ Required to enable organization-scoped auth |
edgeConfig.envVar | Vercel Edge Config environment variable | string | EDGE_CONFIG | ⚠️ Required to enable organization-scoped auth |
edgeConfig.teamId | Vercel team ID | string | VERCEL_TEAM_ID | ⚠️ Required to enable organization-scoped auth |
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
encryption.key | Encryption secret key | string | AUTH_ENCRYPTION_KEY | ⚠️ Required to enable organization-scoped auth |
encryption.iv | Encryption initialization vector | string | AUTH_ENCRYPTION_IV | ⚠️ Required to enable organization-scoped auth |
| Option | Description | Type | Required |
|---|---|---|---|
appRoutes.anon.allowList | Pathnames accessible without authentication. Supports glob patterns via picomatch. | string[] | ❌ |
appRoutes.anon.customErrorResponse | Custom error response override | (options: { errorCode: [ErrorCode](#errorcode); url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.anon.customSuccessResponse | Custom success response override | (options: { url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.anon.getAnonParams | Extract pre-signed key from anon route URL | (options: { url: NextUrl }) => { preSignedKey: string | null | undefined } | undefined | ⚠️ Required to enable anon auth |
appRoutes.anon.pathname | Pathnames of routes accessible using anon authentication | string | string[] | ⚠️ Required to enable anon auth |
appRoutes.dashboard.allowList | Pathnames accessible without authentication. Supports glob patterns via picomatch. | string[] | ❌ |
appRoutes.masquerade.customErrorResponse | Custom error response override | (options: { errorCode: [ErrorCode](#errorcode); url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.masquerade.customSuccessResponse | Custom success response override | (options: { url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.masquerade.getMasqueradeParams | Extract user ID and masquerade token from masquerade route URL | (options: { url: NextUrl }) => { masqueradeToken: string | null | undefined; userId: string | null | undefined } | undefined | ⚠️ Required to enable masquerade auth |
appRoutes.masquerade.pathname | Masquerade pathname | string | ⚠️ Required to enable masquerade auth |
appRoutes.dashboard.customErrorResponse | Custom error response override | (options: { errorCode: [ErrorCode](#errorcode); url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.dashboard.customSuccessResponse | Custom success response override | (options: { url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.dashboard.pathname | Dashboard pathname | string | ✅ |
appRoutes.login.pathname | Login pathname | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
apiRoutes.graphql | GraphQL API endpoints | Record<string, string> | ⚠️ Required to enable Client Functions |
apiRoutes.krakenOAuth | Kraken OAuth API endpoint | string | ⚠️ Required to enable Kraken OAuth |
apiRoutes.login | Login API endpoint | string | ⚠️ Required to enable Client Functions |
apiRoutes.logout | Logout API endpoint | string | ⚠️ Required to enable Client Functions |
apiRoutes.session | Session API endpoint | string | ⚠️ Required to enable Client Functions |
| Option | Description | Type | Required |
|---|---|---|---|
customization.getCookieOptions | Customize cookie options | (cookieName: [CookieName](#cookiename)) => SerializeOptions | undefined | ❌ |
customization.setCustomHeaders | Customize request headers | (headers: Headers, authScope: [AuthScope](#authscope)) => void | Promise<void> | ❌ |
| Option | Description | Type | Required |
|---|---|---|---|
validation.preventGraphQLMutations | Prevent GraphQL mutations | (graphQLEndpoint: string) => boolean | ❌ Defaults to preventProductionGraphQLMutationsDuringDevelopment |
validation.validateGraphQLEndpointUrl | Validate Kraken GraphQL endpoint URL | boolean | ❌ |
The validation.preventGraphQLMutations option defaults to
preventProductionGraphQLMutationsDuringDevelopment, which:
- Prevents accidental execution of GraphQL mutations on production endpoints during development
- Applies when the endpoint URL includes
.kraken.techor.energyANDNODE_ENVis set todevelopment - Can be customized by providing your own validation function
- Can be disabled by setting
validation.preventGraphQLMutationsto a function that always returnsfalse
| Option | Description | Type | Required |
|---|---|---|---|
i18n.localeCookie | Name of the cookie storing user's locale preference | string | ❌ |
i18n.getLocalizedPathname | Callback to resolve localized pathnames | (options: GetLocalizedPathnameOptions) => string | Promise<string> | ✅ |
Check out the full i18n guide to learn more.
Make sure your secrets are kept secure and available server-side only:
- Do not hardcode them in your codebase.
- Do not use environment variables starting with
NEXT_PUBLIC_.
Usage
Somewhere in your project, export the config object returned by
createAuthConfig.
import { createAuthConfig } from "@krakentech/blueprint-auth/server";
export const authConfig = createAuthConfig({ ... });
Middleware
createAuthMiddleware
The middleware is responsible for protecting routes requiring authentication. It redirects unauthenticated users to the login page, and refreshes expired access tokens when necessary. It also handles masquerade and anonymous authentication.
We expose this function separately to avoid bundling code that is unsupported in Edge Runtime. Learn More.
Configuration
- Kraken
- App Routes
- Customization
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
krakenConfig.authEndpoint | Kraken auth endpoint | string | KRAKEN_AUTH_ENDPOINT | ⚠️ Required to enable Kraken OAuth |
krakenConfig.graphqlAuthEndpoint | GraphQL endpoint for auth operations | string | KRAKEN_GRAPHQL_AUTH_ENDPOINT | ❌ Defaults to krakenConfig.graphqlEndpoint |
krakenConfig.graphqlEndpoint | Target GraphQL endpoint | string | KRAKEN_GRAPHQL_ENDPOINT | ✅ |
krakenConfig.oauthClientId | Kraken OAuth client ID | string | KRAKEN_OAUTH_CLIENT_ID | ⚠️ Required to enable Kraken OAuth |
krakenConfig.xClientIpSecretKey | Secret key to sign the user IP address | string | KRAKEN_X_CLIENT_IP_SECRET_KEY | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
appRoutes.anon.allowList | Pathnames accessible without authentication. Supports glob patterns via picomatch. | string[] | ❌ |
appRoutes.anon.customErrorResponse | Custom error response override | (options: { errorCode: [ErrorCode](#errorcode); url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.anon.customSuccessResponse | Custom success response override | (options: { url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.anon.getAnonParams | Extract pre-signed key from anon route URL | (options: { url: NextUrl }) => { preSignedKey: string | null | undefined } | undefined | ⚠️ Required to enable anon auth |
appRoutes.anon.pathname | Pathnames of routes accessible using anon authentication | string | string[] | ⚠️ Required to enable anon auth |
appRoutes.dashboard.allowList | Pathnames accessible without authentication. Supports glob patterns via picomatch. | string[] | ❌ |
appRoutes.dashboard.customErrorResponse | Custom error response override | (options: { errorCode: [ErrorCode](#errorcode); url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.dashboard.customSuccessResponse | Custom success response override | (options: { url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.dashboard.pathname | Dashboard pathname | string | ✅ |
appRoutes.login.pathname | Login pathname | string | ✅ |
appRoutes.masquerade.customErrorResponse | Custom error response override | (options: { errorCode: [ErrorCode](#errorcode); url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.masquerade.customSuccessResponse | Custom success response override | (options: { url: NextUrl }, helpers: { redirect, rewrite }) => NextResponse | undefined | ❌ |
appRoutes.masquerade.getMasqueradeParams | Extract user ID and masquerade token from masquerade route URL | (options: { url: NextUrl }) => { masqueradeToken: string | null | undefined; userId: string | null | undefined } | undefined | ⚠️ Required to enable masquerade auth |
appRoutes.masquerade.pathname | Masquerade pathname | string | ⚠️ Required to enable masquerade auth |
| Option | Description | Type | Required |
|---|---|---|---|
customization.getCookieOptions | Customize cookie options | (cookieName: [CookieName](#cookiename)) => SerializeOptions | undefined | ❌ |
customization.setCustomHeaders | Customize request headers | (headers: Headers, authScope: [AuthScope](#authscope)) => HeadersInit | ❌ |
i18n.localeCookie | Name of the cookie storing user's locale preference | string | ❌ |
i18n.getLocalizedPathname | Callback to resolve localized pathnames | (options: GetLocalizedPathnameOptions) => string | Promise<string> | ❌ |
Usage
- Simple usage
- Composing middlewares
If your Next.js middleware only handles authentication, the function returned by
createAuthMiddleware can be exported directly as
middleware:
import { createAuthMiddleware } from "@krakentech/blueprint-auth/middleware";
import { authConfig } from "@/lib/auth/config";
export const middleware = createAuthMiddleware(authConfig);
export const config = {
matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
};
The auth middleware can be composed with other middlewares. Depending on which middleware needs to run first, you can either call the auth middleware first and pass its response to the next middleware, or vice-versa.
import type { NextRequest } from "next/server";
import { createAuthMiddleware } from "@krakentech/blueprint-auth/middleware";
import { setFeatureFlagCookies } from "@krakentech/blueprint-utils/feature-flags";
import { authConfig } from "@/lib/auth/config";
const authMiddleware = createAuthMiddleware(authConfig);
export async function middleware(request: NextRequest) {
const res = await authMiddleware(request);
return setFeatureFlagCookie({ res });
}
export const config = {
matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
};
The auth middleware accepts an optional response parameter, which can be useful in case it needs to run after another middleware.
import type { NextRequest } from "next/server";
import { createAuthMiddleware } from "@krakentech/blueprint-auth/middleware";
import createIntlMiddleware from "next-intl/middleware";
import { authConfig } from "@/lib/auth/config";
import { routing } from "@/i18n/routing";
const intlMiddleware = createIntlMiddleware(routing);
const authMiddleware = createAuthMiddleware(authConfig);
export async function middleware(request: NextRequest) {
const response = await intlMiddleware(request);
if (!response.ok) return response;
return authMiddleware(request, response);
}
export const config = {
matcher: ["/((?!api|_next|_vercel|.*\\..*).*)"],
};
If a middleware returns a redirect or a rewrite response, you probably want to
skip other middlewares. You can check the Location header to detect redirects
and rewrites.
Server Functions
The package exports Server Functions, which can be used in Next.js server-side execution contexts.
These functions can either be used directly, passing all required configuration and context parameters on each call, or via factories.
Server functions typically accept two separate parameter objects:
- Static Configuration: Application settings that rarely change (endpoints,
secrets, routes). Pass your
authConfigobject directly. - Runtime Parameters: Dynamic values for each call (context, user input, etc.)
// direct import: static configuration and runtime parameters required
await login(authConfig, { context, input: { email, password } });
// factory pattern: config pre-filled, only runtimes parameters required
await login({ context, input: { email, password } });
When using factory functions, the config is pre-filled automatically.
Execution environment
Not all functions work in all environments. Use the table below to check compatibility.
| Function | SSG | SSR | API Handler | Route Handler | Server Component | Server Action | Middleware |
|---|---|---|---|---|---|---|---|
createAuthCookieUtils | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
generateKrakenOAuthURI | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
getOrganizationScopedGraphQLClient | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
getRequestPathname | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
getSession | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
getUserScopedGraphQLClient | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
login | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ |
logout | ❌ | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ |
prefetchSession | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
The context object
All Server Functions expect a context object, which shape varies depending on
the execution context.
- SSG
- SSR
- API Handler
- Server Component
- Route Handler
- Middleware
type StaticPropsContext = Partial<GetStaticPropsContext> | null;
import type { GetStaticPropsContext } from "next";
export async function getStaticPaths() {
const context = null; // or {}
...
}
export async function getStaticProps(context: GetStaticPropsContext) {
...
}
type ServerSidePropsContext = Pick<GetServerSidePropsContext, "req" | "res">;
import type { GetServerSidePropsContext } from "next";
export async function getServerSideProps(context: GetServerSidePropsContext) {
...
}
type ApiRouteHandlerContext = { req: NextApiRequest; res: NextApiResponse };
import type { NextApiRequest, NextApiResponse } from "next";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const context = { req, res };
...
}
Use the createAppRouterAuth helper to get
pre-configured Server Functions with the context object already set.
type ServerComponentContext = {
cookies(): Promise<ReadonlyRequestCookies>;
headers(): Promise<ReadonlyHeaders>;
};
import { cookies, headers } from "next/headers";
const context = { cookies, headers };
In Server Components, cookies() and headers() are read-only. Write
operations on cookies are only allowed in Server Actions, they throw an error in
Server Components. Runtime behavior differs depending on the execution
environment, even though types are identical.
type RouteHandlerContext = { req: NextRequest };
export async function POST(req: NextRequest) {
const context = { req };
...
}
type MiddlewareContext = { req: NextRequest; res: NextResponse };
export async function middleware(req: NextRequest) {
// if you have a `NextResponse` object from a previous operation:
const context = { req, res };
// if you don't have a `NextResponse` object, create one with `NextResponse.next()`:
const context = { req, res: NextResponse.next() };
...
}
At the TypeScript level, Server Actions and Server Components share the same
context type since they use the same Next.js APIs (cookies() and headers()).
However, we distinguish them with separate type names:
ServerComponentContext- For React Server Components (RSC)ServerActionContext- For Server Actions
This distinction helps clarify where each function can be used, even though the underlying type is identical.
Server Function Factories
Server Functions can be used in three different ways, depending on your particular needs.
| Method | Description | Recommendation | Needs configuration | Needs context |
|---|---|---|---|---|
| Direct import | Import Server Functions directly from the package | One-off usage or advanced use cases | ✅ | ✅ |
| Server-Side Factory | Create Server Functions with configuration pre-filled | Pages Router | ❌ | ✅ |
| App Router Factory | Create Server Functions with configuration and context pre-filled | App Router | ❌ | ❌ |
- Direct import
- Server Side Factory
- App Router Factory
Directly imported Server Functions expect: configuration object, context
object, and other runtime parameters.
import {
createAuthCookieUtils,
generateKrakenOAuthURI,
getOrganizationScopedGraphQLClient,
getRequestPathname,
getSession,
getUserScopedGraphQLClient,
login,
logout,
prefetchSession,
} from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
const {
getActiveAuthMethod,
getAuthCookie,
getAuthCookies,
getAuthTokenOverride,
getCookieMapItem,
getRefreshToken,
removeAllCookies,
removeAuthCookies,
removeAuthTokenCookies,
setAuthCookie,
} = createAuthCookieUtils(authConfig, { context });
await generateKrakenOAuthURI(authConfig, { context });
await getRequestPathname({ context });
await getSession({ context });
await login(authConfig, { context, input: { email, password } });
await logout({ context });
await prefetchSession({ context, queryClient });
getOrganizationScopedGraphQLClient(authConfig, { context });
getUserScopedGraphQLClient(authConfig, { context });
Server Functions returned by
createServerSideAuth do not need the
configuration object, only the context object and other runtime parameters are
required.
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const {
createAuthCookieUtils,
generateKrakenOAuthURI,
getOrganizationScopedGraphQLClient,
getRequestPathname,
getSession,
getUserScopedGraphQLClient,
login,
logout,
prefetchSession,
} = createServerSideAuth(authConfig);
const {
getActiveAuthMethod,
getAuthCookie,
getAuthCookies,
getAuthTokenOverride,
getCookieMapItem,
getRefreshToken,
removeAllCookies,
removeAuthCookies,
removeAuthTokenCookies,
setAuthCookie,
} = createAuthCookieUtils({ context });
await generateKrakenOAuthURI({ context });
await getRequestPathname({ context });
await getSession({ context });
await login({ context, input: { email, password } });
await logout({ context });
await prefetchSession({ context, queryClient });
getOrganizationScopedGraphQLClient({ context });
getUserScopedGraphQLClient({ context });
Server Functions returned by createAppRouterAuth
do not need the configuration or context objects, only runtime parameters are
required.
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const {
// cookie utils
getActiveAuthMethod,
getAuthCookie,
getAuthCookies,
getAuthTokenOverride,
getCookieMapItem,
getRefreshToken,
removeAllCookies,
removeAuthCookies,
removeAuthTokenCookies,
setAuthCookie,
// graphql clients
getOrganizationScopedGraphQLClient,
getUserScopedGraphQLClient,
// server functions
getRequestPathname,
getSession,
prefetchSession,
// server actions
generateKrakenOAuthURI,
login,
logout,
} = createAppRouterAuth(authConfig, { cookies, headers });
await generateKrakenOAuthURI();
await getRequestPathname();
await getSession();
await login({ input: { email, password } });
await logout();
await prefetchSession({ queryClient });
getOrganizationScopedGraphQLClient();
getUserScopedGraphQLClient();
All Server Functions rely on
Dynamic APIs,
i.e. cookies
and headers. Be
aware that calling any of the Server Functions in Server Components opts the
Route Segment out of
Static Rendering,
and into
Dynamic Rendering.
- Client components
- React's cache utility
- Blocking calls
With the "use server" directive in lib/auth/server.ts (shown above), you can
call these Server Actions from Client Components marked with "use client":
"use client";
import { logout } from "@/lib/auth/server";
export function LogoutButton() {
return <button onClick={() => logout()}>Logout</button>;
}
Some functions returned by createAppRouterAuth
are wrapped with React's cache
utility to dedupe repeated calls with identical parameters during the lifetime
of a request.
| Function | Cached |
|---|---|
generateKrakenOAuthURI | ✅ |
getActiveAuthMethod | ✅ |
getAuthCookie | ✅ |
getAuthCookies | ✅ |
getAuthTokenOverride | ✅ |
getCookieMapItem | ✅ |
getOrganizationScopedGraphQLClient | ✅ |
getRefreshToken | ✅ |
getRequestPathname | ✅ |
getSession | ✅ |
getUserScopedGraphQLClient | ✅ |
login | ❌ |
logout | ❌ |
prefetchSession | ✅ |
removeAllCookies | ❌ |
removeAuthCookies | ❌ |
removeAuthTokenCookies | ❌ |
setAuthCookie | ❌ |
Note that the request method of the
AuthenticatedGraphQLClient returned by
getUserScopedGraphQLClient (or
getOrganizationScopedGraphQLClient) is
not wrapped with cache, and will execute a network request on each call. Make
sure to wrap functions calling the request method with cache if you want to
dedupe them.
"use server";
import { cache } from "react";
import { getUserScopedGraphQLClient } from "@/lib/auth/server";
import { graphql } from "@/lib/graphql";
const UserQuery = graphql(`
query User {
viewer {
dateOfBirth
email
familyName
fullName
givenName
mobile
preferredName
title
}
}
`);
export const getUser = cache(async () => {
const graphQLClient = getUserScopedGraphQLClient();
const { user } = await graphQLClient.request(UserQuery);
return user;
});
However, getUserScopedGraphQLClient (or
getOrganizationScopedGraphQLClient) are
deduped. During the lifetime of the request all calls to these functions return
the same AuthenticatedGraphQLClient instance.
This ensures expired tokens are refreshed only once per request, and queries can
be paused until the token is refreshed.
Calls to asynchronous function in Server Components block the rendering process
and may harm the performances of your application. Make sure Server Functions
are called in components wrapped in
Suspense boundary to display a
fallback while the asynchronous operation is in progress and stream the content
once the function resolves.
import { DropdownMenu } from "@radix-ui/themes";
import { Link } from "next/link";
import { Avatar } from "@/components/Avatar";
import { LogoutButton } from "@/components/LogoutButton";
import { getSession } from "@/lib/auth/server";
import { getUser } from "@/queries/getUser";
export async function UserMenu() {
const { isAuthenticated } = await getSession();
if (!isAuthenticated) {
return (
<Button asChild>
<Link href="/login">Log in</Link>
</Button>
);
}
const { givenName, preferredName } = await getUser();
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<Avatar name={preferredName || givenName} />
</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item asChild>
<Link href="/dashboard/settings">Settings</Link>
</DropdownMenu.Item>
<DropdownMenu.Item asChild>
<LogoutButton />
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
);
}
import { Logo } from "@/components/Logo";
import { NavigationMenu } from "@/components/NavigationMenu";
import { UserMenu } from "@/components/UserMenu";
function Header() {
return (
<header>
<NavigationMenu />
<Logo />
<Suspense fallback={<Skeleton />}>
<UserMenu />
</Suspense>
</header>
);
}
generateKrakenOAuthURI
Set the code verifier cookie, and generate a unique URI to initiate the Kraken OAuth flow.
Configuration
| Option | Description | Type | Required |
|---|---|---|---|
krakenConfig.authEndpoint | Kraken auth endpoint | string | ✅ |
krakenConfig.oauthClientId | Kraken OAuth client ID | string | ✅ |
Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
context | Request context | ServerSidePropsContext | ApiRouteHandlerContext | RouteHandlerContext | ServerActionContext | MiddlewareContext | ✅ |
Output
| Type | Description |
|---|---|
string | The generated Kraken OAuth URI |
Usage
- Direct import
- Server-Side Factory
- App-Router Factory
import { generateKrakenOAuthURI } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
const krakenOAuthURI = await generateKrakenOAuthURI(authConfig, { context });
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const { generateKrakenOAuthURI } = createServerSideAuth(authConfig);
import { generateKrakenOAuthURI } from "@/lib/auth/server";
const krakenOAuthURI = await generateKrakenOAuthURI({ context });
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const { generateKrakenOAuthURI } = createAppRouterAuth(authConfig, {
cookies,
headers,
});
import { generateKrakenOAuthURI } from "@/lib/auth/server";
const krakenOAuthURI = await generateKrakenOAuthURI();
getSession
Read session data from cookies.
Configuration
This function does not require static configuration.
Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
context | Request context | ServerSidePropsContext | ApiRouteHandlerContext | RouteHandlerContext | ServerComponentContext | ServerActionContext | MiddlewareContext | ✅ |
Output
Returns a SessionState object:
| Field | Description | Type |
|---|---|---|
authMethod | The active authentication method based on cookie priority | AuthMethod | null |
isAuthenticated | User has an auth token cookie | boolean |
sub | The value of the sub cookie if set | string | null |
Usage
- Direct import
- Server-Side Factory
- App-Router Factory
const { authMethod, isAuthenticated, sub } = await getSession({ context });
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const { getSession } = createServerSideAuth(authConfig);
import { getSession } from "@/lib/auth/server";
const { authMethod, isAuthenticated, sub } = await getSession({ context });
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const { getSession } = createAppRouterAuth(authConfig, {
cookies,
headers,
});
import { getSession } from "@/lib/auth/server";
const { authMethod, isAuthenticated, sub } = await getSession();
login
Authenticate a user using email and password, and triggers redirect on successful authentication.
Configuration
- Kraken
- App Routes
- Customization
- i18n
| Option | Description | Type | Required |
|---|---|---|---|
krakenConfig.graphqlAuthEndpoint | GraphQL endpoint for auth operations | string | ✅ |
krakenConfig.xClientIpSecretKey | Secret key to sign the user IP address | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
appRoutes.dashboard.pathname | Dashboard pathname | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
customization.getCookieOptions | Customize cookie options | (cookieName: [CookieName](#cookiename)) => SerializeOptions | undefined | ❌ |
customization.setCustomHeaders | Customize request headers | (headers: Headers, authScope: [AuthScope](#authscope)) => HeadersInit | ❌ |
| Option | Description | Type | Required |
|---|---|---|---|
i18n.localeCookie | Name of the cookie storing user's locale preference | string | ❌ |
i18n.getLocalizedPathname | Callback to resolve localized pathnames | (options: GetLocalizedPathnameOptions) => string | Promise<string> | ❌ |
Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
context | Request context | ApiRouteHandlerContext | RouteHandlerContext | ServerActionContext | ✅ |
input | Login credentials | { email: string; password: string } | ✅ |
nextPage | Redirect pathname | string | null | ❌ |
enableRedirect | Enable redirect | boolean | ❌ Only available in API Handlers and Route Handlers |
searchParams | The URL search params | SearchParams | Promise<SearchParams> | ❌ Only available in Server Actions |
Output
The return type of this function varies depending on the execution context.
- API Handler
- Route Handler
- Server Action
| Type | Condition |
|---|---|
Promise<undefined> | Always |
| Type | Condition |
|---|---|
Promise<NextResponse> | Always |
| Type | Condition |
|---|---|
Promise<never> | Default - throws redirect |
Promise<undefined> | When nextPage is null |
Usage
- Direct import
- Server-Side Factory
- App-Router Factory
import { login } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
await login(authConfig, {
context,
input: { email: "test@example.com", password: "****" },
nextPage: "/dashboard/settings",
searchParams, // available as props in Next.js App Router page components
});
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const { login } = createServerSideAuth(authConfig);
import { login } from "@/lib/auth/server";
await login({
context,
input: { email: "test@example.com", password: "****" },
nextPage: "/dashboard/settings",
searchParams, // available as props in Next.js App Router page components
});
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const { login } = createAppRouterAuth(authConfig, { cookies, headers });
import { login } from "@/lib/auth/server";
await login({
input: { email: "test@example.com", password: "****" },
nextPage: "/dashboard/settings",
searchParams, // available as props in Next.js App Router page components
});
If the nextPage options is not set, the nextPage URL search parameter is
used, appRoutes.dashboard.pathname is used as a fallback. To disable
redirection, set the nextPage option to null.
Redirection is disabled by default in API Handlers and Route Handlers. To
enable redirects, set the enableRedirect option to true.
Learn more
When an fetch request responds a 303 See Other status code, the Pages Router
does not trigger a client-side navigation. Instead, the browser handles it and
triggers a navigation, losing state in the process.
To accomodate for this limitation of the Pages Router, by default the redirect URL is stored in the response body as a JSON object, and redirection is left to the caller.
However, this behavior does not fit all use cases. For instance, a redirect
response is desirable when the API endpoint is used as the action attribute of
the HTML <form> element. To enable redirects, set the enableRedirect option.
The use of the login function in a Server Action is recommended in
the App Router. Check out our
Building Forms tutorial to learn
more.
In case authentication fails, the login Server Function does not
redirect to the current URL with the error code as the error URL search
parameter.
Learn more
Since Next.js 15, calling redirect in a Server Action results in a
303 See Other status response. The App Router handles this error code with a
client-side navigation, preserving the state of layout components. However,
redirecting to the same page triggers a full page reload,
losing client-side page state in the process.
Handling errors client-side prevents the progressive enhancements enabled by
Server Actions. If you're using the App Router, consider storing form errors and
validation errors as action state using React's
useActionState hook. Check
out the Next.js documentation to
learn more.
logout
Remove auth cookies, and redirects the user to the home page.
Configuration
- App Routes
- i18n
| Option | Description | Type | Required |
|---|---|---|---|
appRoutes.home.pathname | Home pathname | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
i18n.localeCookie | Name of the cookie storing user's locale preference | string | ❌ |
i18n.getLocalizedPathname | Callback to resolve localized pathnames | (options: GetLocalizedPathnameOptions) => string | Promise<string> | ❌ |
Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
context | Request context | ServerSidePropsContext | ApiRouteHandlerContext | RouteHandlerContext | ServerActionContext | ✅ |
nextPage | Redirect pathname | string | null | ❌ |
enableRedirect | Enable redirect | boolean | ❌ Only available in API Handlers and Route Handlers |
Output
The return type of this function varies depending on the execution context.
- API Handler
- Route Handler
- Server Action
| Type | Condition |
|---|---|
Promise<undefined> | Always |
| Type | Condition |
|---|---|
Promise<NextResponse> | Always |
| Type | Condition |
|---|---|
Promise<never> | Default - throws redirect |
Promise<undefined> | When nextPage is null |
Usage
- Direct import
- Server-Side Factory
- App-Router Factory
import { logout } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
await logout(authConfig, { context, nextPage: "/goodbye" });
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const { logout } = createServerSideAuth(authConfig);
import { logout } from "@/lib/auth/server";
await logout({ context, nextPage: "/goodbye" });
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const { logout } = createAppRouterAuth(authConfig, { cookies, headers });
import { logout } from "@/lib/auth/server";
await logout({ nextPage: "/goodbye" });
If the nextPage option is not set, appRoutes.home.pathname is used as the
default redirect. To disable redirection, set the nextPage option to null.
Redirection is disabled by default in API Handlers and Route Handlers. To
enable redirects, set the enableRedirect option to true.
Learn more
When an fetch request responds a 303 See Other status code, the Pages Router
does not trigger a client-side navigation. Instead, the browser handles it and
triggers a navigation, losing state in the process.
To accomodate for this limitation of the Pages Router, by default the redirect URL is stored in the response body as a JSON object, and redirection is left to the caller.
However, this behavior does not fit all use cases. For instance, a redirect
response is desirable when the API endpoint is used as the action attribute of
the HTML <form> element. To enable redirects, set the enableRedirect option.
Check out our
Building Forms tutorial to learn
more.
prefetchSession
Reads session data from the cookie, and stores the result into the QueryClient
instance cache.
prefetchSession must be used in combination with the
HydrationBoundary component from @tanstack/react-query. To set it up with
the Pages Router, check out the
Server Rendering and Hydration guide.
To learn more about the App Router setup, check out the
Advanced Server Rendering guide.
Configuration
This function does not require static configuration.
Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
context | Request context | ServerComponentContext | ServerSidePropsContext | StaticPropsContext | ✅ |
queryClient | @tanstack/react-query client instance | QueryClient | ✅ |
Output
| Type | Description |
|---|---|
Promise<void> | No return value |
Usage
- Direct import
- Server-Side Factory
- App-Router Factory
import { prefetchSession } from "@krakentech/blueprint-auth/server";
import { QueryClient } from "@tanstack/react-query";
const queryClient = new QueryClient();
await prefetchSession({ context, queryClient });
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const { prefetchSession } = createServerSideAuth(authConfig);
import { QueryClient } from "@tanstack/react-query";
import { prefetchSession } from "@/lib/auth/server";
const queryClient = new QueryClient();
await prefetchSession({ context, queryClient });
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const { prefetchSession } = createAppRouterAuth(authConfig, {
cookies,
headers,
});
import { QueryClient } from "@tanstack/react-query";
import { prefetchSession } from "@/lib/auth/server";
const queryClient = new QueryClient();
await prefetchSession({ queryClient });
getRequestPathname
Get the pathname from the current request.
Configuration
This function does not require static configuration.
Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
context | Request context | ServerSidePropsContext | ApiRouteHandlerContext | RouteHandlerContext | ServerComponentContext | ServerActionContext | MiddlewareContext | ✅ |
Output
| Type | Description |
|---|---|
Promise<string> | The current request pathname |
Usage
- Direct import
- Server-Side Factory
- App-Router Factory
import { getRequestPathname } from "@krakentech/blueprint-auth/server";
const pathname = await getRequestPathname({ context });
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const { getRequestPathname } = createServerSideAuth(authConfig);
import { getRequestPathname } from "@/lib/auth/server";
const pathname = await getRequestPathname({ context });
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const { getRequestPathname } = createAppRouterAuth(authConfig, {
cookies,
headers,
});
import { getRequestPathname } from "@/lib/auth/server";
const pathname = await getRequestPathname();
getUserScopedGraphQLClient
Create a GraphQL client using user-scoped authentication.
Configuration
- Kraken
- Customization
- Validation
| Option | Description | Type | Required |
|---|---|---|---|
krakenConfig.graphqlAuthEndpoint | GraphQL endpoint for auth operations | string | ✅ |
krakenConfig.graphqlEndpoint | Target GraphQL endpoint | string | ✅ |
krakenConfig.xClientIpOverride | Override for the user IP header (for tests) | string | ❌ |
krakenConfig.xClientIpSecretKey | Secret key to sign the user IP address | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
customization.getCookieOptions | Customize cookie options | (cookieName: [CookieName](#cookiename)) => SerializeOptions | undefined | ❌ |
customization.setCustomHeaders | Customize request headers | (headers: Headers, authScope: [AuthScope](#authscope)) => HeadersInit | ❌ |
| Option | Description | Type | Required |
|---|---|---|---|
validation.preventGraphQLMutations | Prevent GraphQL mutations | (graphQLEndpoint: string) => boolean | ❌ |
Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
context | Request context | StaticPropsContext | ServerSidePropsContext | ApiRouteHandlerContext | RouteHandlerContext | ServerComponentContext | ServerActionContext | MiddlewareContext | ✅ |
errorPolicy | How the client handles GraphQL errors | "none" | "ignore" | "all" | ❌ |
Output
| Type | Description |
|---|---|
AuthenticatedGraphQLClient | An authenticated GraphQL client for making requests |
Usage
- Direct import
- Server-Side Factory
- App-Router Factory
import { getUserScopedGraphQLClient } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
const graphQLClient = getUserScopedGraphQLClient(authConfig, { context });
const viewer = await graphQLClient.request(ViewerQuery);
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const { getUserScopedGraphQLClient } = createServerSideAuth(authConfig);
import { getUserScopedGraphQLClient } from "@/lib/auth/server";
const graphQLClient = getUserScopedGraphQLClient({ context });
const viewer = await graphQLClient.request(ViewerQuery);
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const { getUserScopedGraphQLClient } = createAppRouterAuth(authConfig, {
cookies,
headers,
});
import { getUserScopedGraphQLClient } from "@/lib/auth/server";
const graphQLClient = getUserScopedGraphQLClient();
const viewer = await graphQLClient.request(ViewerQuery);
The returned client is an instance of
AuthenticatedGraphQLClient. See the
Classes section for complete documentation on the
request method, error handling, retry behavior, and advanced features.
getOrganizationScopedGraphQLClient
Create a GraphQL client using organization-scoped authentication.
Configuration
- Kraken
- Edge Config
- Encryption
- Customization
- Validation
| Option | Description | Type | Required |
|---|---|---|---|
krakenConfig.graphqlAuthEndpoint | GraphQL endpoint for auth operations | string | ✅ |
krakenConfig.graphqlEndpoint | Target GraphQL endpoint | string | ✅ |
krakenConfig.organizationSecretKey | Kraken organization secret key | string | ✅ |
krakenConfig.xClientIpOverride | Override for the user IP header (for tests) | string | ❌ |
krakenConfig.xClientIpSecretKey | Secret key to sign the user IP address | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
edgeConfig.authToken | Vercel Edge Config read access token | string | ✅ |
edgeConfig.envVar | Vercel Edge Config environment variable | string | ✅ |
edgeConfig.teamId | Vercel team ID | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
encryption.iv | Encryption initialization vector | string | ✅ |
encryption.key | Encryption secret key | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
customization.getCookieOptions | Customize cookie options | (cookieName: [CookieName](#cookiename)) => SerializeOptions | undefined | ❌ |
customization.setCustomHeaders | Customize request headers | (headers: Headers, authScope: [AuthScope](#authscope)) => HeadersInit | ❌ |
| Option | Description | Type | Required |
|---|---|---|---|
validation.preventGraphQLMutations | Prevent GraphQL mutations | (graphQLEndpoint: string) => boolean | ❌ |
Parameters
| Parameter | Description | Type | Required |
|---|---|---|---|
context | Request context | StaticPropsContext | ServerSidePropsContext | ApiRouteHandlerContext | RouteHandlerContext | ServerComponentContext | ServerActionContext | MiddlewareContext | ✅ |
errorPolicy | How the client handles GraphQL errors: "none", "ignore", or "all". See Error policy. | "none" | "ignore" | "all" | ❌ |
Output
| Type | Description |
|---|---|
AuthenticatedGraphQLClient | An authenticated GraphQL client for making requests |
Usage
- Direct import
- Server-Side Factory
- App-Router Factory
import { getOrganizationScopedGraphQLClient } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
const graphQLClient = getOrganizationScopedGraphQLClient(authConfig, {
context,
});
const thirdPartyViewer = await graphQLClient.request(ThirdPartyViewerQuery);
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const { getOrganizationScopedGraphQLClient } =
createServerSideAuth(authConfig);
import { getOrganizationScopedGraphQLClient } from "@/lib/auth/server";
const graphQLClient = getOrganizationScopedGraphQLClient({ context });
const thirdPartyViewer = await graphQLClient.request(ThirdPartyViewerQuery);
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const { getOrganizationScopedGraphQLClient } = createAppRouterAuth(
authConfig,
{ cookies, headers },
);
import { getOrganizationScopedGraphQLClient } from "@/lib/auth/server";
const graphQLClient = getOrganizationScopedGraphQLClient();
const thirdPartyViewer = await graphQLClient.request(ThirdPartyViewerQuery);
The returned client is an instance of
AuthenticatedGraphQLClient. See the
Classes section for complete documentation on the
request method, error handling, retry behavior, and advanced features.
createAuthCookieUtils
Create helpers to manage authentication cookies.
Configuration
| Option | Description | Type | Required |
|---|---|---|---|
customization.getCookieOptions | Customize cookie options | (cookieName: [CookieName](#cookiename)) => SerializeOptions | undefined | ❌ |
Output
Returns an object with the following fields:
| Field | Description | Type |
|---|---|---|
getActiveAuthMethod | Determine active authentication method based on cookie priority | (cookies: [CookieMap](#cookiemap)) => AuthMethod | null |
getAuthCookie | Get auth cookie | (name: [CookieName](#cookiename)) => Promise<string | undefined> |
getAuthCookies | Get auth cookie map | () => Promise<[CookieMap](#cookiemap)> |
getAuthTokenOverride | Get auth token override from request header | () => Promise<{ token: string, type: "override" } | null> |
getCookieMapItem | Get cookie from cookie map | <Name extends [CookieName](#cookiename)>({ cookies, name }: { cookies: [CookieMap](#cookiemap), name: Name }) => { type: Name, value: string } | null |
getRefreshToken | Get refresh token from cookie | () => Promise<string | undefined> |
removeAllCookies | Remove all auth cookies | () => Promise<void> |
removeAuthCookies | Remove auth cookies | (cookies: [CookieName](#cookiename)[]) => Promise<void> |
removeAuthTokenCookies | Remove auth token cookies, i.e. accessToken, masqueradeToken, MWAuthToken, scopedToken | () => Promise<void> |
setAuthCookie | Set auth cookie | ({ name, value, expires }: { name: [CookieName](#cookiename), value: string, expires: Date | undefined }) => Promise<void> |
See CookieName and CookieMap in the Types
section for type definitions.
Usage
- Direct import
- Server-Side Factory
- App-Router Factory
import { createAuthCookieUtils } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
const {
getActiveAuthMethod,
getAuthCookie,
getAuthCookies,
getAuthTokenOverride,
getCookieMapItem,
getRefreshToken,
removeAllCookies,
removeAuthCookies,
removeAuthTokenCookies,
setAuthCookie,
} = createAuthCookieUtils(authConfig, { context });
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { authConfig } from "./config";
export const { createAuthCookieUtils } = createServerSideAuth(authConfig);
import { createAuthCookieUtils } from "@/lib/auth/server";
const {
getActiveAuthMethod,
getAuthCookie,
getAuthCookies,
getAuthTokenOverride,
getCookieMapItem,
getRefreshToken,
removeAllCookies,
removeAuthCookies,
removeAuthTokenCookies,
setAuthCookie,
} = createAuthCookieUtils({ context });
The App Router factory does not return
createAuthCookieUtils, instead it returns the
utility functions directly.
"use server";
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { authConfig } from "./config";
export const {
getActiveAuthMethod,
getAuthCookie,
getAuthCookies,
getAuthTokenOverride,
getCookieMapItem,
getRefreshToken,
removeAllCookies,
removeAuthCookies,
removeAuthTokenCookies,
setAuthCookie,
} = createAppRouterAuth(authConfig, { cookies, headers });
import {
getActiveAuthMethod,
getAuthCookie,
getAuthCookies,
getAuthTokenOverride,
getCookieMapItem,
getRefreshToken,
removeAllCookies,
removeAuthCookies,
removeAuthTokenCookies,
setAuthCookie,
} from "@/lib/auth/server";
Cookies are read-only inside Server Components, calling removeAllCookies,
removeAuthCookies, removeAuthTokenCookies, or setAuthCookie throws an
error. These functions can safely be used in Server Actions however.
API Handlers
The packages exports factory functions to create API handlers. The handlers can be used with the Pages Router as API Handlers, or with the App Router as Route Handlers.
API handlers the Cache-Control header with
no-cache, no-store, max-age=0, must-revalidate", effectively disabling the
cache ensure each request results in a fresh response.
createLoginHandler
The login handler authenticates the user using email and password, sets auth cookies, and provides a redirect URL in the response.
Configuration
- Kraken
- App Routes
- Customization
- i18n
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
krakenConfig.graphqlAuthEndpoint | GraphQL endpoint for auth operations | string | KRAKEN_GRAPHQL_AUTH_ENDPOINT | ✅ |
krakenConfig.xClientIpSecretKey | Secret key to sign the user IP address | string | KRAKEN_X_CLIENT_IP_SECRET_KEY | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
appRoutes.dashboard.pathname | Dashboard pathname | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
customization.getCookieOptions | Customize cookie options | (cookieName: [CookieName](#cookiename)) => SerializeOptions | undefined | ❌ |
customization.setCustomHeaders | Customize request headers | (headers: Headers, authScope: [AuthScope](#authscope)) => HeadersInit | ❌ |
| Option | Description | Type | Required |
|---|---|---|---|
i18n.localeCookie | Name of the cookie storing user's locale preference | string | ❌ |
i18n.getLocalizedPathname | Callback to resolve localized pathnames | (options: GetLocalizedPathnameOptions) => string | Promise<string> | ❌ |
Output
| Type | Description |
|---|---|
(req: NextApiRequest, res: NextApiResponse) => Promise<void> | Handler function for Pages Router |
(req: NextRequest) => Promise<NextResponse<unknown | AuthErrorResponse>> | Handler function for App Router |
Usage
- Pages Router
- App Router
import { createLoginHandler } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
export default createLoginHandler(authConfig);
You may not need a Route Handler for login with the App Router, check out the
login Server Function.
import { createLoginHandler } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
export const POST = createLoginHandler(authConfig);
Request
The login handler expects a POST request with a JSON body containing the
following fields:
| Field | Description | Type | Required |
|---|---|---|---|
email | User email | string | ✅ |
nextPage | Redirect pathname | string | null | ❌ |
password | User password | string | ✅ |
Response
The success response body is a JSON object with the following fields:
| Field | Description | Type |
|---|---|---|
data.redirectUrl | The URL to redirect the user to after login. | string | null |
The error response body is a JSON object with the following fields:
| Field | Description | Type |
|---|---|---|
error.errorCode | Error code | ErrorCode |
error.message | Error message | string |
error.source | Source of the error | "blueprint-auth" |
Status Codes
| Status Code | Condition |
|---|---|
| 200 OK | Successful login with redirect URL in response body (when enableRedirect is false) |
| 307 Temporary Redirect | Successful login, redirect to dashboard or nextPage (when enableRedirect is true) |
| 400 Bad Request | Invalid request body, invalid email format, missing required fields (email/password), authentication failed, or any validation error |
| 405 Method Not Allowed | Request method is not POST |
createLogoutHandler
The logout handler removes auth cookies and provides a redirect URL in the response.
Configuration
- i18n
| Option | Description | Type | Required |
|---|---|---|---|
i18n.localeCookie | Name of the cookie storing user's locale preference | string | ❌ |
i18n.getLocalizedPathname | Callback to resolve localized pathnames | (options: GetLocalizedPathnameOptions) => string | Promise<string> | ❌ |
Output
| Type | Description |
|---|---|
(req: NextApiRequest, res: NextApiResponse) => Promise<void> | Handler function for Pages Router |
(req: NextRequest) => Promise<NextResponse<unknown | AuthErrorResponse>> | Handler function for App Router |
Usage
- Pages Router
- App Router
import { createLogoutHandler } from "@krakentech/blueprint-auth/server";
export default createLogoutHandler();
You may not need a Route Handler for logout with the App Router, check out the
logout Server Function.
import { createLogoutHandler } from "@krakentech/blueprint-auth/server";
export const POST = createLogoutHandler();
Request
The logout handler expects a POST request with a JSON body containing the
following fields:
| Field | Description | Type | Required |
|---|---|---|---|
nextPage | Redirect pathname | string | null | ❌ |
Response
The success response body is a JSON object with the following fields:
| Field | Description | Type |
|---|---|---|
data.redirectUrl | The URL to redirect the user to after login. | string | null |
The error response body is a JSON object with the following fields:
| Field | Description | Type |
|---|---|---|
error.errorCode | Error code | ErrorCode |
error.message | Error message | string |
error.source | Source of the error | "blueprint-auth" |
Status Codes
| Status Code | Condition |
|---|---|
| 200 OK | Successful logout with redirect URL in response body (when enableRedirect is false) |
| 307 Temporary Redirect | Successful logout, redirect to home or nextPage (when enableRedirect is true) |
| 400 Bad Request | Invalid request body (validation error) |
| 405 Method Not Allowed | Request method is not POST |
| 500 Internal Server Error | Unknown logout operation error |
createSessionHandler
The session handler reads auth cookies and provides the current session data.
Configuration
No configuration needed.
Output
| Type | Description |
|---|---|
(req: NextApiRequest, res: NextApiResponse) => Promise<void> | Handler function for Pages Router |
(req: NextRequest) => Promise<NextResponse<AuthSuccessResponse<SessionState> | AuthErrorResponse>> | Handler function for App Router |
Usage
- Pages Router
- App Router
import { createSessionHandler } from "@krakentech/blueprint-auth/server";
export default createSessionHandler();
You may not need a Route Handler to get session data with the App Router, check
out the getSession Server Function.
import { createSessionHandler } from "@krakentech/blueprint-auth/server";
export const GET = createSessionHandler();
Request
The session handler expects a GET request.
Response
The success response body is a JSON object with the following fields:
| Field | Description | Type |
|---|---|---|
data.isAuthenticated | User has an auth token cookie | boolean |
data.authMethod | Active auth method | AuthMethod |
data.sub | The value of the sub cookie if set | string | null |
The error response body is a JSON object with the following fields:
| Field | Description | Type |
|---|---|---|
error.errorCode | Error code | ErrorCode |
error.message | Error message | string |
error.source | Source of the error | "blueprint-auth" |
Status Codes
| Status Code | Condition |
|---|---|
| 200 OK | Successfully retrieved session state |
| 405 Method Not Allowed | Request method is not GET |
| 500 Internal Server Error | Failed to read session details (any error) |
createGraphQLHandler
The GraphQL handler proxies requests to the GraphQL endpoint specified by
krakenConfig.graphqlEndpoint after setting the Authorization header
depending on the incoming request cookies.
Configuration
- Kraken
- Customization
- Validation
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
krakenConfig.graphqlAuthEndpoint | GraphQL endpoint for auth operations | string | KRAKEN_GRAPHQL_AUTH_ENDPOINT | ✅ |
krakenConfig.graphqlEndpoint | Target GraphQL endpoint | string | KRAKEN_GRAPHQL_ENDPOINT | ✅ |
krakenConfig.xClientIpOverride | Override for the user IP header (for tests) | string | ❌ | |
krakenConfig.xClientIpSecretKey | Secret key to sign the user IP address | string | KRAKEN_X_CLIENT_IP_SECRET_KEY | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
customization.getCookieOptions | Customize cookie options | (cookieName: [CookieName](#cookiename)) => SerializeOptions | undefined | ❌ |
customization.setCustomHeaders | Customize request headers | (headers: Headers, authScope: [AuthScope](#authscope)) => HeadersInit | ❌ |
| Option | Description | Type | Required |
|---|---|---|---|
validation.preventGraphQLMutations | Prevent GraphQL mutations | (graphQLEndpoint: string) => boolean | ❌ |
validation.validateGraphQLEndpointUrl | Should validate Kraken GraphQL endpoint URL | boolean | ❌ |
Output
| Type | Description |
|---|---|
(req: NextApiRequest, res: NextApiResponse) => Promise<void> | Handler function for Pages Router |
(req: NextRequest) => Promise<NextResponse<unknown>> | Handler function for App Router |
Usage
- Pages Router
- App Router
import { createGraphQLHandler } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
export default createGraphQLHandler(authConfig);
You may not need a Route Handler for GraphQL operations with the App Router,
check out the getUserScopedGraphQLClient and
getOrganizationScopedGraphQLClient
Server Functions.
import { createGraphQLHandler } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
export const POST = createGraphQLHandler(authConfig);
Request
The GraphQL handler expects a POST request with a JSON body containing the
following fields:
| Field | Description | Type | Required |
|---|---|---|---|
query | GraphQL query/mutation | string | ✅ |
variables | Variables of the GraphQL query/mutation | object | ❌ |
Optional request header: the handler accepts the x-error-policy header to set the error policy for that request (e.g. when the client is created with useGraphQLClient({ errorPolicy: "…" })). Values are case-sensitive: "none", "ignore", "all".
Response
The success response body is a JSON object with the following fields:
| Field | Description | Type |
|---|---|---|
data | Response of GraphQL query/mutation | object the shape depends on the query/mutation |
The error response body is a JSON object with the following fields:
| Field | Description | Type |
|---|---|---|
data | Result of the query/mutation | object | null the shape depends on the query/mutation |
errors | GraphQL errors | KrakenError[] |
If the accessToken cookie expired, the GraphQL handler attempts to refresh it
using the refreshToken cookie.
The GraphQL handler passes errors returned by the GraphQL API endpoint through.
In case an error occurs inside of the GraphQL handler, the error is converted to
match the KrakenError interface, and includes the following fields:
| Field | Description | Type |
|---|---|---|
message | Error message | string |
extensions.errorCode | Error code | string |
extensions.errorDescription | Error description | string |
Status Codes
| Status Code | Condition |
|---|---|
| 200 OK | Successful GraphQL request or GraphQL request with errors (errors returned in response body) |
| 400 Bad Request | Invalid request body, missing query field, or invalid query/variables |
| 401 Unauthorized | Kraken API returns UNAUTHORIZED error code |
| 405 Method Not Allowed | Request method is not POST |
| 500 Internal Server Error | Unknown GraphQL operation error |
createKrakenOAuthHandler
The Kraken OAuth handler authenticates the user using the Kraken OAuth flow. It
is meant to be used in combination with
generateKrakenOAuthURI. It fetches auth tokens from
Kraken, sets auth cookies, and redirects the user to the dashboard page on
success. In case authentication fails, the user is redirected to the login page
with the error code as the error URL search parameter.
Configuration
- Kraken
- App Routes
- API Routes
- Customization
- i18n
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
krakenConfig.authEndpoint | Kraken auth endpoint | string | KRAKEN_AUTH_ENDPOINT | ✅ |
krakenConfig.oauthClientId | Kraken OAuth client ID | string | KRAKEN_OAUTH_CLIENT_ID | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
appRoutes.dashboard.pathname | Dashboard pathname | string | ✅ |
appRoutes.login.pathname | Login pathname | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
apiRoutes.krakenOAuth | Kraken OAuth API endpoint | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
customization.getCookieOptions | Customize cookie options | (cookieName: [CookieName](#cookiename)) => SerializeOptions | undefined | ❌ |
| Option | Description | Type | Required |
|---|---|---|---|
i18n.localeCookie | Name of the cookie storing user's locale preference | string | ❌ |
i18n.getLocalizedPathname | Callback to resolve localized pathnames | (options: GetLocalizedPathnameOptions) => string | Promise<string> | ❌ |
Output
| Type | Description |
|---|---|
(req: NextApiRequest, res: NextApiResponse) => Promise<void> | Handler function for Pages Router |
(req: NextRequest) => Promise<NextResponse<unknown | AuthErrorResponse>> | Handler function for App Router |
Usage
- Pages Router
- App Router
import { createKrakenOAuthHandler } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
export default createKrakenOAuthHandler(authConfig);
import { createKrakenOAuthHandler } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
export const GET = createKrakenOAuthHandler(authConfig);
Request
The Kraken OAuth handler expects a GET request with the following URL search
parameters:
| URL search parameter | Description | Type | Required |
|---|---|---|---|
code | Kraken OAuth code | string | ✅ |
The Kraken OAuth handler requires a
Proof Key for Code Exchange (PKCE) stored as the
pkce-verifier cookie on the incoming request. This cookie is set by the
handler of the URL returned by generateKrakenOAuthURI.
Response
The Kraken OAuth handler responds with a redirect response. The Location
header is set to the dashboard page on success, and to the login page with error
code on failure.
Status Codes
| Status Code | Condition |
|---|---|
| 307 Temporary Redirect (to Dashboard) | Successful OAuth authentication |
| 307 Temporary Redirect (to Login) | error query parameter present in callback, missing or invalid code query parameter, missing code_verifier cookie, OAuth token exchange failed, invalid token validation (iss/aud/sub), or any authentication error |
| 405 Method Not Allowed | Request method is not GET |
createUpdateOrgTokenHandler
The organization token update handler is meant to be used as a Vercel cron job. It fetches a new organization token and stores the value in the Edge Config store.
Configuration
- Kraken
- Edge Config
- Encryption
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
krakenConfig.graphqlAuthEndpoint | GraphQL endpoint for auth operations | string | KRAKEN_GRAPHQL_AUTH_ENDPOINT | ✅ |
krakenConfig.organizationSecretKey | Kraken organization secret key | string | KRAKEN_ORGANIZATION_KEY | ✅ |
krakenConfig.xClientIpSecretKey | Secret key to sign the user IP address | string | KRAKEN_X_CLIENT_IP_SECRET_KEY | ✅ |
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
edgeConfig.authToken | Vercel Edge Config read access token | string | VERCEL_AUTH_TOKEN | ✅ |
edgeConfig.envVar | Vercel Edge Config environment variable | string | EDGE_CONFIG | ✅ |
edgeConfig.teamId | Vercel team ID | string | VERCEL_TEAM_ID | ✅ |
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
encryption.iv | Encryption initialization vector | string | AUTH_ENCRYPTION_IV | ✅ |
encryption.key | Encryption secret key | string | AUTH_ENCRYPTION_KEY | ✅ |
The organization token update handler requires the CRON_SECRET environment
variable to be set. This ensures the handler can only be called as a cron job.
Vercel automatically sets the CRON_SECRET environment variable as the
Authorization header in cron jobs. The handler responds with a
401 Unauthorized status response in case the header and the environment
variable do not match.
Check out the Vercel documentation to learn more.
Output
| Type | Description |
|---|---|
(req: NextApiRequest, res: NextApiResponse) => Promise<void> | Handler function for Pages Router |
(req: NextRequest) => Promise<NextResponse<unknown>> | Handler function for App Router |
Usage
- Pages Router
- App Router
import { createUpdateOrgTokenHandler } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
export default createUpdateOrgTokenHandler(authConfig);
import { createUpdateOrgTokenHandler } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
export const GET = createUpdateOrgTokenHandler(authConfig);
To setup the cron job, create a vercel.json at the root of your project with
the following content:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"crons": [
{
"path": "/api/auth/update-org-token",
"schedule": "*/55 * * * *"
}
]
}
The organization token lifetime is usually set to 1 hour. The example above run
the cron job every 55 minutes, but you can customize the schedule field to
better fit your needs. Check out Vercel's
cron expressions guide.
Request
The update organization token handler expects a GET request with the
Authorization header set to Bearer {CRON_SECRET}.
Response
The handler returns an empty response body.
Status Codes
| Status Code | Condition |
|---|---|
| 200 OK | Successfully updated organization token |
| 401 Unauthorized | Missing Authorization header or header doesn't match CRON_SECRET |
| 405 Method Not Allowed | Request method is not GET |
| 500 Internal Server Error | Error updating organization token, Edge config write failure, or any unknown error |
Client Functions
If you are using the Next.js App Router, you most likely do not need any of these helpers, use Server Functions instead.
createClientSideAuth
Creates AuthProvider and the hooks depending on it, i.e.
useAuth, useGraphQLClient,
useKrakenAuthErrorHandler,
useLogin, useLogout, and
useSession.
Configuration
- App Routes
- API Routes
- i18n
| Option | Description | Type | Required |
|---|---|---|---|
appRoutes.dashboard.pathname | Dashboard pathname | string | ✅ |
appRoutes.login.pathname | Login pathname | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
apiRoutes.graphql | GraphQL API endpoints | Record<string, string> | ✅ |
apiRoutes.login | Login API endpoint | string | ✅ |
apiRoutes.logout | Logout API endpoint | string | ✅ |
apiRoutes.session | Session API endpoint | string | ✅ |
| Option | Description | Type | Required |
|---|---|---|---|
i18n.localeCookie | Name of the cookie storing user's locale preference | string | ❌ |
i18n.getLocalizedPathname | Callback to resolve localized pathnames | (options: GetLocalizedPathnameOptions) => string | Promise<string> | ❌ |
Parameters
| Param | Description | Type | Required |
|---|---|---|---|
defaultTarget | Default GraphQL API endpoint | keyof typeof apiRoutes.graphql | ✅ |
router | Specifies which Next.js router the application uses. | "app-router" | "pages-router" | ✅ |
If your application uses multiple GraphQL endpoints relying on Kraken
authentication, you can define them in the apiRoutes.graphql object.
{
apiRoutes: {
graphql: {
kraken: "/api/graphql/kraken",
custom: "/api/graphql/custom",
}
}
}
The createClientSideAuth factory expects an options object as its second
argument with two properties:
defaultTarget: The default GraphQL endpoint used byuseGraphQLClient. The value must be a key of theapiRoutes.graphqlobject.router: The Next.js router being used. Must be either"pages-router"or"app-router".
Usage
- Pages Router
- App Router
Export the functions returned by createClientSideAuth.
import { createClientSideAuth } from "@krakentech/blueprint-auth/client";
import { authConfig } from "./config";
export const {
AuthProvider,
useAuth,
useGraphQLClient,
useKrakenAuthErrorHandler,
useLogin,
useLogout,
useSession,
} = createClientSideAuth(authConfig, {
defaultTarget: "kraken",
router: "pages-router",
});
Export the functions returned by createClientSideAuth.
"use client";
import { createClientSideAuth } from "@krakentech/blueprint-auth/client";
import { authConfig } from "./config";
export const {
AuthProvider,
useAuth,
useGraphQLClient,
useKrakenAuthErrorHandler,
useLogin,
useLogout,
useSession,
} = createClientSideAuth(authConfig, {
defaultTarget: "kraken",
router: "app-router",
});
The "use client" directive is required to hint Next.js that the module exports
a client component, i.e. AuthProvider.
AuthProvider
Provides configuration to auth hooks.
Configuration
| Option | Description | Type | Required |
|---|---|---|---|
onLoginSuccess | Successful login callback | (defaultRedirect: () => void) => void | Promise<void> | ❌ |
onLoginError | Login error callback | (errorCode: [ErrorCode](#errorcode), defaultRedirect: () => void) => void | Promise<void> | ❌ |
onLogoutSuccess | Successful logout callback | (defaultRedirect: () => void) => void | Promise<void> | ❌ |
onLogoutError | Logout error callback | (errorCode: [ErrorCode](#errorcode), defaultRedirect: () => void) => void | Promise<void> | ❌ |
Usage
- Pages Router
- App Router
In your Next.js _app.tsx file, wrap the page component with
AuthProvider, and optionally define custom handlers.
import { useRouter } from "next/router";
import { useToast } from "@/hooks/useToast";
import { authConfig } from "@/lib/auth/config";
import { AuthProvider } from "@/lib/auth/client";
export default function App({ Component, pageProps }) {
const router = useRouter();
const toast = useToast("auth");
return (
<AuthProvider
// extend default behavior
onLoginSuccess={(defaultRedirect) => {
defaultRedirect();
toast("login.success", { type: "success" });
}}
// override default behavior
onLoginError={(errorCode) => {
toast("login.error", { errorCode, type: "error" });
}}
// optionally extend default behavior
onLogoutSuccess={(defaultRedirect) => {
toast("logout.success", { type: "success" });
if (router.pathname.startsWith("/dashboard")) {
defaultRedirect();
}
}}
>
<Component {...pageProps} />
</AuthProvider>
);
}
Create a Providers Client Component including all your global providers, and
render it in your root layout.tsx.
"use client";
import {
QueryClientProvider,
QueryClient,
isServer,
} from "@tanstack/react-query";
import { usePathname } from "next/navigation";
import { AuthProvider } from "@/lib/auth/client";
import { useToast } from "@/hooks/useToast";
let browserQueryClient: QueryClient | undefined = undefined;
function getQueryClient() {
if (isServer) {
return new QueryClient();
} else {
if (!browserQueryClient) browserQueryClient = new QueryClient();
return browserQueryClient;
}
}
export function Providers({ children }: PropsWithChildren) {
const toast = useToast("auth");
const pathname = usePathname();
const queryClient = getQueryClient();
return (
<QueryClientProvider client={queryClient}>
<AuthProvider
// extend default behavior
onLoginSuccess={(defaultRedirect) => {
toast("login.success", { type: "success" });
defaultRedirect();
}}
// override default behavior
onLoginError={(errorCode) => {
toast("login.error", { errorCode, type: "error" });
}}
// optionally extend default behavior
onLogoutSuccess={(defaultRedirect) => {
toast("logout.success", { type: "success" });
if (pathname?.startsWith("/dashboard")) {
defaultRedirect();
}
}}
>
{children}
</AuthProvider>
</QueryClientProvider>
);
}
import { Providers } from "./providers";
export default function RootLayout({ children }: LayoutProps<"/">) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
useAuth
This hook is used internally by other auth hooks to access the
AuthProviderContext state.
This hook is exposed for convenience in advanced use cases, e.g. custom auth hooks. In most cases you should not use it directly.
Configuration
No configuration needed.
Output
| Field | Description | Type | Required |
|---|---|---|---|
apiRoutes.graphql | GraphQL API endpoints | Record<string, string> | ✅ |
apiRoutes.login | Login API endpoint | string | ✅ |
apiRoutes.logout | Logout API endpoint | string | ✅ |
apiRoutes.session | Session API endpoint | string | ✅ |
appRoutes.dashboard.pathname | Dashboard pathname | string | ✅ |
appRoutes.login.pathname | Login pathname | string | ✅ |
defaultTarget | Default GraphQL endpoint | string | ✅ |
handlers.onLoginSuccess | Successful login callback | (defaultRedirect: () => void) => void | Promise<void> | ❌ |
handlers.onLoginError | Login error callback | (errorCode: AuthErrorCode, defaultRedirect: () => void) => void | Promise<void> | ❌ |
handlers.onLogoutSuccess | Successful logout callback | (defaultRedirect: () => void) => void | Promise<void> | ❌ |
handlers.onLogoutError | Logout error callback | (errorCode: AuthErrorCode, defaultRedirect: () => void) => void | Promise<void> | ❌ |
Requirements
| Requirement | Notes |
|---|---|
| Context provider | Use inside AuthProvider. |
| Client-side auth | The component must be wrapped with a client-side auth setup using createClientSideAuth. |
Usage
import { useAuth } from "@/lib/auth/client";
function useCustomLogin() {
const { apiRoutes, appRoutes, defaultTarget, handlers } = useAuth();
...
}
useGraphQLClient
Get a preconfigured GraphQL client to perform authenticated requests to the Kraken GraphQL API endpoint, or GraphQL API endpoint relying on Kraken for authentication.
Requirements
| Requirement | Notes |
|---|---|
| API endpoint | Create the GraphQL API endpoint at apiRoutes.graphql using createGraphQLHandler. |
| Context provider | Use inside AuthProvider. |
Configuration
| Parameter | Description | Type | Required |
|---|---|---|---|
target | Target GraphQL endpoint (must be a key of the apiRoutes.graphql object provided to createClientSideAuth) | string | ❌ Defaults to the default target |
errorPolicy | How the client handles GraphQL errors: "none" (default), "ignore", or "all". See Error policy. | "none" | "ignore" | "all" | ❌ Defaults to "none" |
Output
| Field | Description | Type | Required |
|---|---|---|---|
graphQLClient | GraphQL client instance | GraphQLClient | ✅ |
Usage
import { useQuery } from "@tanstack/react-query";
import { AccountQuery } from "@/graphql/AccountQuery";
import { useGraphQLClient } from "@/lib/auth/client";
export function useAccount(variables: { accountNumber: string }) {
// using the default target and error policy (no args needed)
const { graphQLClient } = useGraphQLClient();
// using a different target:
const { graphQLClient } = useGraphQLClient({ target: "custom" });
// with a custom error policy:
const { graphQLClient } = useGraphQLClient({ errorPolicy: "ignore" });
return useQuery({
queryKey: ["account", variables.accountNumber],
queryFn: () => graphQLClient.request(AccountQuery, variables),
});
}
The returned client is a GraphQLClient instance from the
graphql-request library. It
provides a request method with the same signature as
AuthenticatedGraphQLClient, plus additional
methods like batchRequests.
useKrakenAuthErrorHandler
The hook provides an error handler to be used with data fetching libraries. If
the error is auth-related the handler redirects the user to the login page with
error and nextPage search parameters.
Requirements
| Requirement | Notes |
|---|---|
| Context provider | Use inside AuthProvider. |
Configuration
| Option | Description | Type | Required |
|---|---|---|---|
onError | Error callback | (error: unknown, defaultRedirect: () => void) => void | Promise<void> | ❌ |
redirectType | Redirect type | "push" | "replace" | ❌ Defaults to "push" |
Providing onError overrides the default redirect behavior of the
useKrakenAuthErrorHandler hook. In case you need
to extend the default behavior, the onError callback is called with the
defaultRedirect function.
Output
| Field | Description | Type | Required |
|---|---|---|---|
handleKrakenErrors | Error handler | (error: unknown) => void | Promise<void> | ✅ |
When i18n is configured, this hook redirects to localized login pages based on the user's locale.
Usage
import { useQuery } from "@tanstack/react-query";
import { AccountQuery } from "@/graphql/AccountQuery";
import { useGraphQLClient, useKrakenAuthErrorHandler } from "@/lib/auth/client";
export function useAccount(variables: { accountNumber: string }) {
const { graphQLClient } = useGraphQLClient();
const { handleKrakenErrors } = useKrakenAuthErrorHandler();
return useQuery({
queryKey: ["account", variables.accountNumber],
queryFn: () => graphQLClient.request(AccountQuery, variables),
onError: handleKrakenErrors,
});
}
useLogin
The useLogin hook can be used to authenticate the user, and
handles redirection for both success and failure cases.
Learn more about the useLogin hook redirect behavior
Default success redirect
- Redirect to the
nextPageoption if set. - Redirect to the
nextPageURL search parameter if set. - Redirect to the
appRoutes.dashboard.pathnameotherwise.
Default failure redirect
Set the error URL search parameter in the current URL.
Customizing redirects
To customize the redirects, you can provide the onLoginSuccess and
onLoginError callbacks to AuthProvider, or pass additional
onSuccess and onError callbacks to login.mutate or login.mutateAsync.
If the handlers.onLoginSuccess callback set on the
AuthProvider does not call the defaultRedirect function,
the nextPage option and the nextPage URL search parameter have no effect.
Requirements
| Requirement | Notes |
|---|---|
| API endpoint | Create the login API endpoint at apiRoutes.login using createLoginHandler. |
| Context provider | Use inside AuthProvider. |
| React Query | Use inside of <QueryClientProvider>, see the Pages Router or the App Router example. |
Login API Handler
The useLogin hook expects the login API handler created with
createLoginHandler to be available on the
apiRoutes.login endpoint.
QueryClientProvider
The useLogin hook uses React Query's useMutation under the
hood. It must be used inside of <QueryClientProvider>. Check out React Query's
Pages Router example.
or
App Router example.
Configuration
| Option | Description | Type | Required |
|---|---|---|---|
nextPage | Redirect pathname | string | null | ❌ |
Output
Returns a UseMutationResult object, see React Query's
useMutation hook documentation.
Usage
import { useLogin } from "@/lib/auth/client";
export function LoginForm(props: LoginFormProps) {
const login = useLogin();
function handleSubmit() {
// trigger the login mutation
login.mutate({ email: "example@email.com", password: "****" });
}
async function handleSubmit() {
// alternatively, you can use the async version
await login.mutateAsync({ email: "example@email.com", password: "****" });
}
}
The error code can be read from the error URL search parameter. The
UseMutationResult object returned by the useLogin hook also
includes the error response accessible as login.error. The error code can be
extracted from the error response using the getErrorCode
utility function.
The useLogin hook can be used to create a login form that works
even before the page is fully hydrated, or if JavaScript is disabled. Check out
our Building Forms guide to learn
more.
useLogout
The useLogout hook can be used to log out the user, and handles
redirection for both success and failure cases.
Learn more about the useLogout hook redirect behavior
Default success redirect
- Redirect to the
nextPageoption if set. - Redirect to the
/otherwise.
Default failure redirect
Set the error URL search parameter in the current URL.
Customizing redirects
To customize the redirects, you can provide the onLogoutSuccess and
onLogoutError callbacks to AuthProvider, or pass additional
onSuccess and onError callbacks to logout.mutate or logout.mutateAsync.
If the handlers.onLogoutSuccess callback set on the
AuthProvider does not call the defaultRedirect function,
the nextPage option has no effect.
Requirements
| Requirement | Notes |
|---|---|
| API endpoint | Create the logout API endpoint at apiRoutes.logout using createLogoutHandler. |
| Context provider | Use inside AuthProvider. |
| React Query | Use inside of <QueryClientProvider>, see the Pages Router or the App Router example. |
Logout API Handler
The useLogout hook expects the logout API handler created with
createLogoutHandler to be available on the
apiRoutes.logout endpoint.
QueryClientProvider
The useLogout hook uses React Query's useMutation under the hood. It must be
used inside of <QueryClientProvider>. Check out React Query's
Pages Router example.
or
App Router example.
Configuration
| Option | Description | Type | Required |
|---|---|---|---|
nextPage | Redirect pathname | string | null | ❌ |
Output
| Type | Description |
|---|---|
UseMutationResult | React Query mutation result, see useMutation docs |
Usage
import { useLogout } from "@/lib/auth/client";
export function LogoutButton() {
const logout = useLogout();
function handleClick() {
// trigger the logout mutation
logout.mutate();
}
async function handleClick() {
// alternatively, you can use the async version
await logout.mutateAsync();
}
return (
<button type="button" onClick={handleClick}>
Logout
</button>
);
}
The error code can be read from the error URL search parameter. The
UseMutationResult object returned by the useLogout hook also
includes the error response accessible as logout.error. The error code can be
extracted from the error response using the getErrorCode
utility function.
The useLogout hook can be used to create a logout button that
works even before the page is hydrated, or if JavaScript is disabled. Check out
our Building Forms tutorial to
learn more.
useSession
The useSession hook can be used to access information about the
current user session.
Requirements
| Requirement | Notes |
|---|---|
| API endpoint | Create the session API endpoint at apiRoutes.session using createSessionHandler. |
| Context provider | Use inside AuthProvider. |
| React Query | Use inside of <QueryClientProvider>, see the Pages Router or the App Router example. |
Configuration
No configuration needed.
Output
Returns a DefinedUseQueryResult<SessionState, unknown> object.
The SessionState data includes:
| Field | Description | Type |
|---|---|---|
authMethod | The active authentication method based on cookie priority | AuthMethod | null |
isAuthenticated | User has an auth token cookie | boolean |
sub | The value of the sub cookie if set | string | null |
const { data: session } = useSession();
if (session.isAuthenticated) {
return <LogoutButton />
} else {
return <LoginButton />
}
if (session.authMethod === "masquerade") {
return <MasqueradeBanner />
}
if (session.authMethod === "scoped") {
return <PaymentDetailsCard />
} else {
return <PaymentDetailsForm />
}
redirectToNextPage
The redirectToNextPage function redirects the user to
the relative URL found in the nextPage URL search parameter.
If nextPage is empty or contains an absolute URL, the fallback is used. If
nextPage is invalid and the fallback is not provided, the function has no
effect.
Requirements
| Requirement | Notes |
|---|---|
| Pages Router | This function relies expects a NextRouter instance, which can only be used with the Pages Router. |
Configuration
| Option | Description | Type | Required |
|---|---|---|---|
router | The NextRouter instance | NextRouter | ✅ |
fallback | The fallback URL in case nextPage is empty or invalid | string | ❌ |
redirectType | The type of navigation | push | replace | ❌ defaults to replace |
Usage
import { useRouter } from "next/router";
import { redirectToNextPage } from "@krakentech/blueprint-auth/client";
const Page = () => {
const router = useRouter();
useEffect(() => {
redirectToNextPage({
router,
fallback: "/dashboard",
});
}, []);
return <p>Redirecting...</p>;
};
Utils
convertIterableToRecord
Converts an Iterable (like an Iterator or generator) to a Record object.
function convertIterableToRecord<
T extends {
entries(): Iterable<readonly [string, string]>;
},
>(iterable: T): Record<string, string | string[]>;
Configuration
| Parameter | Description | Type | Required |
|---|---|---|---|
iterable | The iterable to convert | T extends { entries(): Iterable<readonly [string, string]>} | ✅ |
Output
| Type | Description |
|---|---|
Record<string, string | string[]> | A record object created from the iterable |
Usage
const iterable = Map([
["key1", "value1"],
["key2", "value2"],
]);
const record = convertIterableToRecord(iterable);
// { key1: "value1", key2: "value2" }
convertRecordToIterable
Converts a Record object back to an Iterable.
function convertRecordToIterable<
Entry,
Target extends { append(key: string, value: string): void },
>(record: Record<string, Entry>, target: Target): Target;
Configuration
| Parameter | Description | Type | Required |
|---|---|---|---|
record | The record to convert | Record<string, Entry> | ✅ |
target | The target iterable to append to | Target extends { append(key: string, value: string): void } | ✅ |
Output
| Type | Description |
|---|---|
Target | The target iterable with appended entries |
Usage
const record = { key1: "value1", key2: "value2" };
const iterable = convertRecordToIterable(record);
// Map(2) { "key1" => "value1", "key2" => "value2" }
getErrorCode
Get the error code from a client-side function or from a GraphQL operation.
Configuration
Expect an error of type unknown.
Output
| Type | Condition |
|---|---|
BlueprintAuthErrorCode | Blueprint auth error |
MappedKrakenErrorCode | Mapped Kraken error |
null | No error code found |
Usage
import { getUserScopedGraphQLClient } from "@krakentech/blueprint-auth/server";
import { reportGraphQLError } from "@/lib/error/reporting";
async function getAccount(variables: { accountNumber: string }) {
try {
const graphQLClient = getUserScopedGraphQLClient();
const { account } = await graphQLClient.request(AccountQuery, variables);
return account;
} catch (error) {
const errorCode = getErrorCode(error);
if (errorCode) {
return reportGraphQLError(error, { errorCode });
}
return reportUnexpectedError(error);
}
}
isBlueprintAuthErrorCode
Check if an error code is a valid
BlueprintAuthErrorCode.
Configuration
Expect an error code of type string.
Output
| Type | Description |
|---|---|
boolean | True if valid Blueprint auth error |
Usage
import { getTranslations } from "next-intl/server";
import { isBlueprintAuthErrorCode } from "@krakentech/blueprint-auth/utils";
import { isMappedKrakenErrorCode } from "@krakentech/blueprint-api/utils";
async function getErrorMessage(error: unknown) {
const t = await getTranslations("getErrorMessage");
const errorCode = getErrorCode(error);
if (errorCode) {
if (isBlueprintAuthErrorCode(errorCode)) {
return t(`blueprint-auth.${errorCode}`);
}
if (isMappedKrakenErrorCode(errorCode)) {
return t(`kraken.${errorCode}`);
}
}
return t("unknown");
}
setNextPageSearchParam
This function sets the nextPage URL search parameter. This is the URL search
parameter that we are setting in the authMiddleware function when we redirect
the user to the login page.
Configuration
| Option | Description | Type | Required |
|---|---|---|---|
nextPage | Redirect page pathname or URL | string | URL | NextUrl | ✅ |
url | The URL on which the nextPage URL search parameter should be set | URL | NextUrl | ✅ |
Output
Returns void.
Usage
import { setNextPageSearchParam } from "@krakentech/blueprint-auth/utils";
const url = new URL("https://example.com/login");
setNextPageSearchParam({
nextPage: "/profile/settings?tab=update-password",
url,
});
// url.href → https://example.com/login?nextPage=%2Fprofile%2Fsettings%3Ftab%3Dupdate-password
If the nextPage URL includes search parameters, they are included in the
encoded nextPage URL search parameter along with the URL pathname.
The setNextPageSearchParam automatically removes the nextPage and error
URL search parameters from the nextPage URL if they are set.
setKrakenAuthTokenOverrideHeader
Manually set the Kraken auth token override header.
Configuration
| Option | Description | Type | Required |
|---|---|---|---|
headers | Headers object | Headers | ✅ |
token | Override token value | string | ✅ |
Output
| Type | Description |
|---|---|
void | No return value |
Usage
"use server";
import { setKrakenAuthTokenOverrideHeader } from "@krakentech/blueprint-auth/utils";
import { headers } from "next/headers";
import { redirect } from "next/navigation";
import { getUserScopedGraphQLClient } from "@/lib/auth/server";
import { CheckoutQuoteInput, CheckoutQuote } from "@/mutations/checkout-quote";
import {
handleRequestError,
handleSubmissionError,
parseSubmission,
type FormState,
} from "@/utils/form-actions";
export async function checkoutAction(
token: string,
_formState: FormState,
formData: FormData,
) {
const submission = parseSubmission(formData, CheckoutQuoteInput);
if (!submission.success) {
return handleSubmissionError(submission);
}
const requestHeaders = new Headers(await headers());
setKrakenAuthTokenOverrideHeader(requestHeaders, token);
try {
const graphQLClient = getUserScopedGraphQLClient();
await graphQLClient.request(CheckoutQuote, submission.data, requestHeaders);
} catch (error) {
return handleRequestError(error, submission);
}
redirect("/subscribe/confirmation");
}
Classes
AuthenticatedGraphQLClient
The AuthenticatedGraphQLClient class provides a
GraphQL client with automatic authentication, token refresh, and intelligent
retry logic. It is returned by
getUserScopedGraphQLClient and
getOrganizationScopedGraphQLClient.
Error policy
The client supports an optional error policy that controls how GraphQL errors in responses are handled:
| Policy | Behavior |
|---|---|
"none" | (default) GraphQL errors cause the request to throw. |
"ignore" | GraphQL errors are ignored; response data is returned even when the response contains errors. |
"all" | Response includes both data and errors (rawRequest-style), so the caller can handle errors explicitly. |
You can set the error policy when creating the client (e.g. via getUserScopedGraphQLClient({ context, errorPolicy: "ignore" }) or getOrganizationScopedGraphQLClient({ errorPolicy: "ignore" })). You can also override it per request by passing the xErrorPolicyHeader in requestHeaders:
import { xErrorPolicyHeader } from "@krakentech/blueprint-auth";
const graphQLClient = getUserScopedGraphQLClient({ context, errorPolicy: "ignore" });
const result = await graphQLClient.request({
document: MyQuery,
requestHeaders: { [xErrorPolicyHeader]: "ignore" },
});
request<T, V>(document, variables?, headers?): Promise<T>
Execute a GraphQL query or mutation with automatic authentication.
Parameters
- Positional Arguments
- Object Configuration
Pass up to three separate arguments to the request method.
| Parameter | Type | Description | Required |
|---|---|---|---|
document | RequestDocument | TypedDocumentNode | GraphQL query/mutation document | ✅ |
variables | V | GraphQL variables | ❌ |
requestHeaders | HeadersInit | Request-level headers | ❌ |
const { account } = await graphQLClient.request(
AccountQuery,
{ accountNumber: "A-12345678" },
{ "x-custom-header": "my-value" },
);
Pass a single object with all options (supports additional features like AbortSignal).
| Parameter | Type | Description | Required |
|---|---|---|---|
document | RequestDocument | TypedDocumentNode | GraphQL query/mutation document | ✅ |
variables | V | GraphQL variables | ❌ |
requestHeaders | HeadersInit | Request-level headers | ❌ |
signal | AbortSignal | AbortSignal for request cancellation | ❌ |
const abortController = new AbortController();
const { account } = await graphQLClient.request({
document: AccountQuery,
variables: { accountNumber: "A-12345678" },
requestHeaders: { "x-custom-header": "my-value" },
signal: abortController.signal,
});
// later, if needed:
abortController.abort();
Output
| Type | Description |
|---|---|
Promise<T> | The GraphQL response data |
Throws
| Error Type | Condition |
|---|---|
AuthError (BlueprintAuthErrorCode.TokenAccessInvalid) | Token refresh fails after 3 retries (rare - automatic retry usually succeeds) |
AuthError (BlueprintAuthErrorCode.Forbidden) | Mutation attempted when preventGraphQLMutations is enabled |
| Kraken API errors | GraphQL operation failures (validation, permissions, etc.) |
Usage
- Basic Usage
- Custom Headers
- Request Cancellation
- Concurrent Requests
Execute GraphQL queries and mutations with automatic authentication:
import { getUserScopedGraphQLClient } from "@/lib/auth/server";
import { graphql } from "@/gql-tada";
const AccountQuery = graphql(`
query Account($accountNumber: String!) {
account(accountNumber: $accountNumber) {
number
balance
status
}
}
`);
export async function getServerSideProps(context) {
const graphQLClient = getUserScopedGraphQLClient({ context });
const { account } = await graphQLClient.request(AccountQuery, {
accountNumber: "A-12345678",
});
return {
props: { account },
};
}
Client-level headers (via config)
Set headers that apply to all requests made with any client instance:
import { createAuthConfig } from "@krakentech/blueprint-auth";
const authConfig = createAuthConfig({
// ... other config
customization: {
setCustomHeaders: (headers, authScope) => {
headers.set("x-client-version", "1.0.0");
headers.set("x-tracking-id", generateTrackingId());
},
},
});
All requests made with any client instance will include these headers.
Request-level headers (via request method)
Set headers for a specific request only:
const { account } = await graphQLClient.request(
AccountQuery,
{ accountNumber: "A-12345678" },
{ "x-request-id": requestId }, // Only for this specific request
);
Request-level headers override client-level headers. Use client-level headers for common values (authentication tokens, API versions) and request-level headers for per-request metadata (trace IDs, cache control).
Use the AbortController API to cancel in-flight requests:
import { graphql } from "@/gql-tada";
const LongRunningQuery = graphql(`
query LongRunning {
complexData {
# ... expensive query
}
}
`);
const abortController = new AbortController();
// start the request
const requestPromise = graphQLClient.request({
document: LongRunningQuery,
signal: abortController.signal,
});
// cancel after 5 seconds
setTimeout(() => {
abortController.abort();
}, 5000);
try {
const data = await requestPromise;
} catch (error) {
if (error.name === "AbortError") {
console.log("Request was cancelled");
}
}
The signal parameter is only available when using the object configuration
style. Use request({ document, signal }) instead of
request(document, variables, headers).
Multiple concurrent requests using the same client instance automatically share token refresh operations:
import { getUserScopedGraphQLClient } from "@/lib/auth/server";
import { graphql } from "@/gql-tada";
const UserQuery = graphql(`
query User {
viewer {
email
fullName
}
}
`);
const AccountQuery = graphql(`
query Account($accountNumber: String!) {
account(accountNumber: $accountNumber) {
number
balance
}
}
`);
export async function getServerSideProps(context) {
const graphQLClient = getUserScopedGraphQLClient({ context });
// these three requests run concurrently and share token refresh
const [user, account1, account2] = await Promise.all([
graphQLClient.request(UserQuery),
graphQLClient.request(AccountQuery, { accountNumber: "A-12345678" }),
graphQLClient.request(AccountQuery, { accountNumber: "A-87654321" }),
]);
// if the token expires, only one refresh operation occurs
// all three requests wait and resume with the new token
return {
props: { user, account1, account2 },
};
}
Multiple concurrent requests using the same client instance share token refresh operations. If multiple requests detect an invalid token simultaneously, only one refresh operation occurs, and all waiting requests resume once the new token is available.
Retry Behavior
When a GraphQL request fails due to an invalid or expired token, the client automatically:
- Marks the current token as invalid
- Requests a new token via the configured
getNewAuthTokencallback - Retries the original request with the new token
- Repeats up to 3 times before throwing an error
This ensures seamless operation even when tokens expire during request execution.
AuthError
Custom error class for authentication operations. All errors thrown by
@krakentech/blueprint-auth functions are instances of
AuthError.
Constructor
new AuthError(message: string, options?: { code?: ErrorCode; cause?: unknown })
Parameters:
| Parameter | Type | Description | Required |
|---|---|---|---|
message | string | Human-readable error message | ✅ |
options.code | ErrorCode | Error code (Blueprint or Kraken) | ❌ |
options.cause | unknown | Underlying error that caused this error | ❌ |
Properties
| Property | Type | Description |
|---|---|---|
message | string | Human-readable error message |
code | ErrorCode | Error code identifying the type of error |
cause | unknown | Original error that caused this error (if any) |
name | string | Always "AuthError" |
Usage
import { AuthError, BlueprintAuthErrorCode } from "@krakentech/blueprint-auth";
// throwing an AuthError
throw new AuthError("Invalid credentials", {
code: BlueprintAuthErrorCode.BadRequest,
});
// catching and handling AuthError
try {
await login({ context, input: { email, password } });
} catch (error) {
if (error instanceof AuthError) {
console.error("Auth error:", error.code, error.message);
if (error.code === BlueprintAuthErrorCode.TokenAccessInvalid) {
// handle expired token
}
}
}
Error Code Utilities
Use these utility functions to work with AuthError instances:
getErrorCode(error)- Extract the error code from any errorisBlueprintAuthErrorCode(code)- Check if an error code is Blueprint-specific
Types
AuthMethod
Represents the authentication method currently in use.
type AuthMethod =
| "email"
| "oauth"
| "scoped"
| "masquerade"
| "mobile-web-view"
| (string & {}); // Allows autocomplete while accepting unknown strings
Values
| Value | Description | Priority |
|---|---|---|
"masquerade" | Staff impersonation via masquerade token | Highest |
"mobile-web-view" | Mobile app integration via MWAuthToken | High |
"oauth" | OAuth-based authentication | Medium |
"email" | Email/password authentication | Medium |
"scoped" | Anonymous/pre-signed key access via scoped token | Lowest |
null | No authentication present | N/A |
Priority
In case multiple authentication cookies are present, the
AuthMethod is determined by priority order (highest to lowest):
masquerade- Takes precedence over all other authentication methodsmobile-web-view- Takes precedence over standard login and scoped sessionsoauthoremail- Standard authenticated sessions (determined byauthProvidercookie)scoped- Anonymous/pre-signed key access
This priority system ensures that masquerade and mobile app integration always take precedence, preventing lower-priority authentication from overriding higher-priority sessions.
Usage
The AuthMethod type is available in the
SessionState object returned by getSession()
and useSession():
const session = await getSession({ context });
if (session.isAuthenticated) {
return <LogoutButton />
} else {
return <LoginButton />
}
if (session.authMethod === "masquerade") {
return <MasqueradeBanner />
}
if (session.authMethod === "scoped") {
return <PaymentDetailsCard />
} else {
return <PaymentDetailsForm />
}
if (session.authMethod === "mobile-web-view") {
return <UpdateAppLink />
} else {
return <DownloadAppLink />
}
SessionState
Represents the current user session state. See getSession and
useSession for full documentation.
type SessionState = {
authMethod: AuthMethod | null;
isAuthenticated: boolean;
sub: string | null;
};
AuthScope
Represents the scope of authentication for GraphQL operations.
type AuthScope = "user" | "organization";
Values
| Value | Description |
|---|---|
"user" | User-scoped authentication - operations performed on behalf of a user |
"organization" | Organization-scoped authentication - operations performed with org-level credentials |
Usage
The AuthScope type is used in the
customization.setCustomHeaders callback and internally by GraphQL client
functions.
const authConfig = createAuthConfig({
customization: {
setCustomHeaders(headers, authScope) {
if (authScope === "organization") {
headers.set("X-Custom-Org-Header", "value");
}
},
},
});
CookieName
Valid authentication cookie names used throughout the package.
type CookieName =
| "accessToken"
| "authProvider"
| "masqueradeToken"
| "MWAuthToken"
| "MWRefreshToken"
| "pkce-verifier"
| "refreshToken"
| "scopedToken"
| "sub";
Usage
This type is used by createAuthCookieUtils functions
to ensure type-safe cookie operations. See the AUTH_COOKIE
constant for the actual cookie name values.
const { setAuthCookie } = createAuthCookieUtils({ context });
await setAuthCookie({
name: "accessToken", // type-safe: must be a valid CookieName
value: token,
expires: new Date(Date.now() + 3600000),
});
CookieMap
A Map containing authentication cookie names and their values.
type CookieMap = Map<CookieName, string | undefined>;
Usage
Returned by getAuthCookies() and used by getActiveAuthMethod() and
getCookieMapItem() for type-safe cookie operations. See
CookieName for valid cookie name values.
const { getAuthCookies, getActiveAuthMethod, getCookieMapItem } =
createAuthCookieUtils({ context });
const cookies = await getAuthCookies(); // Returns CookieMap
const authMethod = getActiveAuthMethod(cookies);
// get specific cookie from the map
const accessToken = getCookieMapItem({
cookies,
name: "accessToken",
});
BlueprintAuthErrorCode
Blueprint-specific error codes for authentication operations. All error codes
follow the pattern BP-AUTH-XXXX.
const BlueprintAuthErrorCode = {
/* General Errors */
Unknown: "BP-AUTH-0000",
BadRequest: "BP-AUTH-0001",
ResponseNotFound: "BP-AUTH-0003",
Forbidden: "BP-AUTH-0004",
/* Token Errors */
TokenUnknown: "BP-AUTH-0100",
TokenAccessInvalid: "BP-AUTH-0101",
TokenNotRefreshable: "BP-AUTH-0102",
/* API Handler Errors */
ApiHandlerUnknown: "BP-AUTH-0200",
ApiHandlerRequestNotFound: "BP-AUTH-0201",
ApiHandlerInvalidParameters: "BP-AUTH-0202",
ApiHandlerMethodNotAllowed: "BP-AUTH-0203",
/* Server Function Errors */
ServerFunctionUnknown: "BP-AUTH-0300",
ServerFunctionUnsupportedExecutionContext: "BP-AUTH-0301",
/* Operation Errors */
OperationUnknown: "BP-AUTH-0400",
OperationLoginUnknown: "BP-AUTH-0410",
OperationOAuthUnknown: "BP-AUTH-0420",
OperationLogoutUnknown: "BP-AUTH-0430",
OperationSessionUnknown: "BP-AUTH-0440",
OperationGraphQLUnknown: "BP-AUTH-0450",
/* Edge Config Errors */
EdgeConfigUnknown: "BP-AUTH-0500",
EdgeConfigFetch: "BP-AUTH-0501",
EdgeConfigFetchUpdated: "BP-AUTH-0502",
EdgeConfigUpdate: "BP-AUTH-0503",
/* Encryption Errors */
EncryptionUnknown: "BP-AUTH-0600",
/* Validation Errors */
ValidationUnknown: "BP-AUTH-0700",
ValidationApiUrl: "BP-AUTH-0701",
ValidationMissingProperties: "BP-AUTH-0702",
ValidationInvalidProperties: "BP-AUTH-0703",
/* Client Errors */
ClientUnknown: "BP-AUTH-0800",
ClientHookUsedOutsideOfProvider: "BP-AUTH-0802",
} as const;
type BlueprintAuthErrorCode =
(typeof BlueprintAuthErrorCode)[keyof typeof BlueprintAuthErrorCode];
Error Codes
| Code | Constant | Category | Description |
|---|---|---|---|
BP-AUTH-0000 | Unknown | General | Unknown error |
BP-AUTH-0001 | BadRequest | General | Bad request |
BP-AUTH-0003 | ResponseNotFound | General | Response not found |
BP-AUTH-0004 | Forbidden | General | Forbidden operation |
BP-AUTH-0100 | TokenUnknown | Token | Unknown token error |
BP-AUTH-0101 | TokenAccessInvalid | Token | Invalid or expired access token |
BP-AUTH-0102 | TokenNotRefreshable | Token | Token cannot be refreshed |
BP-AUTH-0200 | ApiHandlerUnknown | API Handler | Unknown API handler error |
BP-AUTH-0201 | ApiHandlerRequestNotFound | API Handler | API request not found |
BP-AUTH-0202 | ApiHandlerInvalidParameters | API Handler | Invalid parameters provided to API handler |
BP-AUTH-0203 | ApiHandlerMethodNotAllowed | API Handler | HTTP method not allowed |
BP-AUTH-0300 | ServerFunctionUnknown | Server Function | Unknown server function error |
BP-AUTH-0301 | ServerFunctionUnsupportedExecutionContext | Server Function | Server function called in unsupported context |
BP-AUTH-0400 | OperationUnknown | Operation | Unknown operation error |
BP-AUTH-0410 | OperationLoginUnknown | Operation | Unknown login operation error |
BP-AUTH-0420 | OperationOAuthUnknown | Operation | Unknown OAuth operation error |
BP-AUTH-0430 | OperationLogoutUnknown | Operation | Unknown logout operation error |
BP-AUTH-0440 | OperationSessionUnknown | Operation | Unknown session operation error |
BP-AUTH-0450 | OperationGraphQLUnknown | Operation | Unknown GraphQL operation error |
BP-AUTH-0500 | EdgeConfigUnknown | Edge Config | Unknown Edge Config error |
BP-AUTH-0501 | EdgeConfigFetch | Edge Config | Failed to fetch Edge Config |
BP-AUTH-0502 | EdgeConfigFetchUpdated | Edge Config | Failed to fetch updated Edge Config |
BP-AUTH-0503 | EdgeConfigUpdate | Edge Config | Failed to update Edge Config |
BP-AUTH-0600 | EncryptionUnknown | Encryption | Unknown encryption error |
BP-AUTH-0700 | ValidationUnknown | Validation | Unknown validation error |
BP-AUTH-0701 | ValidationApiUrl | Validation | Invalid API URL |
BP-AUTH-0702 | ValidationMissingProperties | Validation | Missing required properties |
BP-AUTH-0703 | ValidationInvalidProperties | Validation | Invalid property values |
BP-AUTH-0800 | ClientUnknown | Client | Unknown client-side error |
BP-AUTH-0802 | ClientHookUsedOutsideOfProvider | Client | React hook used outside of AuthProvider |
Usage
import {
BlueprintAuthErrorCode,
getErrorCode,
} from "@krakentech/blueprint-auth";
try {
await login({ context, input: { email, password } });
} catch (error) {
const errorCode = getErrorCode(error);
if (errorCode === BlueprintAuthErrorCode.TokenAccessInvalid) {
// handle invalid token
} else if (errorCode === BlueprintAuthErrorCode.ValidationMissingProperties) {
// handle validation error
}
}
ErrorCode
Union type of all possible error codes from Blueprint Auth and the Kraken API.
type ErrorCode = BlueprintAuthErrorCode | MappedKrakenErrorCode;
This type combines:
BlueprintAuthErrorCode- Blueprint-specific auth errors (e.g.,BP-AUTH-0001)MappedKrakenErrorCode- Kraken API errors from@krakentech/blueprint-api
Constants
AUTH_COOKIE
| Constant | Value | Description |
|---|---|---|
AUTH_COOKIE.accessToken | "accessToken" | Name of the access token cookie |
AUTH_COOKIE.authProvider | "authProvider" | Name of the auth provider cookie |
AUTH_COOKIE.MWAuthToken | "MWAuthToken" | Name of the MW auth token cookie |
AUTH_COOKIE.MWRefreshToken | "MWRefreshToken" | Name of the MW refresh token cookie |
AUTH_COOKIE.masqueradeToken | "masqueradeToken" | Name of the masquerade token cookie |
AUTH_COOKIE.pkceVerifier | "pkce-verifier" | Name of the PKCE verifier cookie |
AUTH_COOKIE.refreshToken | "refreshToken" | Name of the refresh token cookie |
AUTH_COOKIE.scopedToken | "scopedToken" | Name of the scoped token cookie |
AUTH_COOKIE.sub | "sub" | Name of the subject cookie |
HTTP Headers
| Constant | Value | Description |
|---|---|---|
krakenAuthTokenOverrideHeader | "x-kraken-auth-token-override" | Header for token override in scoped requests |
xClientIpHeader | "x-kraken-client-ip" | Header containing the client IP address |
xClientIpAuthorizationHeader | "x-kraken-client-ip-authorization" | Header with signed client IP for rate-limiting prevention |
xErrorPolicyHeader | "x-error-policy" | Per-request error policy override ("none", "ignore", "all") |
URL Parameters
| Constant | Value | Description |
|---|---|---|
sessionQueryKey | ["auth"] | Query key for session-related queries |
ignoredQueryParams | ["nextPage"] | Query parameters to ignore when constructing URLs |
nextPageParam | "nextPage" | URL parameter for redirect destination after auth actions |