Masquerade Authentication
Introduction
Masquerade authentication enables authorized staff members to temporarily impersonate users for customer support and troubleshooting purposes. Unlike standard login which uses email/password credentials, masquerade auth creates authenticated sessions using pre-generated masquerade tokens, providing staff with secure access to user accounts.
- Session-based: Creates standard authenticated sessions with
authMethodfor tracking - Secure token handling: Tokens are invalidated on error and require fresh authentication
Getting started
Complete the Getting Started: Pages Router or Getting Started: App Router guide
Configuration
Basic Configuration
import { createAuthConfig } from "@krakentech/blueprint-auth";
export const authConfig = createAuthConfig({
appRoutes: {
dashboard: { pathname: "/dashboard" },
home: { pathname: "/" },
login: { pathname: "/login" },
masquerade: {
// Extract the user ID and token from the URL path.
getMasqueradeParams({ url }) {
const segments = url.pathname.split("/").filter(Boolean);
const [route, userId] = segments;
const masqueradeToken = segments.at(-1);
if (
segments.length >= 3 &&
route === "masquerade" &&
userId &&
masqueradeToken
) {
return { userId, masqueradeToken };
}
},
// Pathname where masquerade URLs are handled
pathname: "/masquerade",
// Redirect after authentication without a dedicated masquerade page.
customSuccessResponse({ url }, { redirect }) {
return redirect(new URL("/dashboard", url.origin));
},
},
},
});
Advanced Configuration (with custom redirects)
import { createAuthConfig } from "@krakentech/blueprint-auth";
export const authConfig = createAuthConfig({
appRoutes: {
dashboard: { pathname: "/dashboard" },
home: { pathname: "/" },
login: { pathname: "/login" },
masquerade: {
getMasqueradeParams({ url }) {
const segments = url.pathname.split("/").filter(Boolean);
const [route, userId] = segments;
const masqueradeToken = segments.at(-1);
if (
segments.length >= 3 &&
route === "masquerade" &&
userId &&
masqueradeToken
) {
return { userId, masqueradeToken };
}
},
pathname: "/masquerade",
// Optional: Custom redirect on success
customSuccessResponse({ url }, { redirect }) {
// Example: redirect to dashboard home page
return redirect(new URL("/dashboard", url.origin));
},
// Optional: Custom error handling
customErrorResponse({ url, errorCode }, { redirect }) {
return redirect(new URL(`/login?code=${errorCode}`, url.origin));
},
},
},
});
Configuration Options
| Option | Type | Required | Description |
|---|---|---|---|
pathname | string | ✅ | Route where masquerade auth is handled |
getMasqueradeParams | (options: { url: NextURL }) => { userId: string | null | undefined; masqueradeToken: string | null | undefined } | undefined | ✅ | Extracts userId and masqueradeToken from URL |
customSuccessResponse | (options: { url: NextURL }, helpers: { redirect, rewrite }) => NextResponse | undefined | Promise<NextResponse | undefined> | ❌ | Override redirect after successful authentication |
customErrorResponse | (options: { url: NextURL; errorCode: ErrorCode }, helpers: { redirect, rewrite }) => NextResponse | undefined | Promise<NextResponse | undefined> | ❌ | Override redirect on authentication failure |
Middleware
- Next.js ≤15
- Next.js 16+
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|.*\\..*).*)"],
};
import { createAuthMiddleware } from "@krakentech/blueprint-auth/middleware";
import { authConfig } from "@/lib/auth/config";
export const proxy = createAuthMiddleware(authConfig);
export const config = {
matcher: ["/", "/((?!api|_next|_vercel|.*\\..*).*)"],
};
See matcher coverage for the recommended pattern and exclusions.
Masquerade route
You do not need a dedicated masquerade page. The middleware handles authentication
when staff navigate to /masquerade/{userId}/.../{masqueradeToken}. The middle
segments are optional.
Use appRoutes.masquerade.customSuccessResponse to redirect staff to the dashboard
after authentication, as shown in the advanced configuration above. Keep any
account-specific routing in your existing dashboard rather than a separate
masquerade page.
Session state
Middleware verifies masquerade tokens on matched routes, but does not replace
checks at protected server boundaries. Use getAuth.user and enforce resource
permissions before accessing protected data or performing mutations in pages,
API routes, Route Handlers, and Server Actions. Session-based UI indicators do
not authorize an operation. See
Route protection.
Checking session state is useful when you need to display masquerade-specific UI
elements or track staff activity. Use getSession or useSession to
conditionally render masquerade indicators and apply different behavior for
masqueraded sessions.
Session state fields
| Field | Value | Description |
|---|---|---|
authMethod | "masquerade" | The verified grant is MASQUERADE |
authSource | "web" | The token came from the web accessToken cookie |
isAuthenticated | true | The request has a verified user token |
A successful masquerade request clears the current managed session. Blueprint
Auth then stores the verified token in accessToken. A failed masquerade
request also clears the managed session. This prevents use of the previous user
identity after a failure.
See Session management for an overview of the session lifecycle.
Common patterns
- Masquerade Indicator
- Conditional Features
- Server-Side Checks
Display a visual indicator when staff are masquerading to prevent confusion and ensure they're aware they're viewing a customer's account.
A header component that displays a prominent masquerade banner when staff are impersonating a user, helping prevent accidental actions on customer accounts.
Show implementation
"use client";
import { useSession } from "@/lib/auth/client";
import { Logo } from "@/components/Logo";
import { LogoutButton } from "@/components/LogoutButton";
import { MasqueradeBadge } from "@/components/MasqueradeBadge";
import { NavigationMenu } from "@/components/NavigationMenu";
export function Header() {
const { data: session, isError, isFetched } = useSession();
return (
<header>
{!isFetched ? (
<p role="status">Loading session...</p>
) : isError ? (
<p role="alert">Unable to load the session.</p>
) : (
<>
{session.authMethod === "masquerade" && <MasqueradeBadge />}
{session.isAuthenticated && <LogoutButton />}
</>
)}
<NavigationMenu />
<Logo />
</header>
);
}
Disable or modify features when staff are masquerading to prevent unintended actions or provide staff-specific functionality.
A billing page that prevents payment method changes during masquerade sessions but allows viewing payment information for support purposes.
Show implementation
import { BlueprintAuthErrorCode } from "@krakentech/blueprint-auth";
import type {
GetServerSidePropsContext,
InferGetServerSidePropsType,
} from "next";
import {
getAuth,
getGraphQLClient,
redirectToLogin,
} from "@/lib/auth/server";
import { graphql } from "@/lib/graphql";
import { PaymentMethods } from "@/components/PaymentMethods";
const BillingQuery = graphql(`
query BillingPage($accountNumber: String!) {
account(accountNumber: $accountNumber) {
id
number
paymentMethods {
id
type
lastFourDigits
}
}
}
`);
export default function BillingPage({
account,
isMasquerading,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<div>
<h1>Billing Information</h1>
<PaymentMethods
methods={account.paymentMethods}
readOnly={isMasquerading}
/>
</div>
);
}
export async function getServerSideProps(
context: GetServerSidePropsContext<{ accountNumber: string }>,
) {
const accountNumber = context.params?.accountNumber;
if (!accountNumber) {
return { notFound: true };
}
const auth = await getAuth.user({ context });
if (!auth) {
return redirectToLogin({
context,
errorCode: BlueprintAuthErrorCode.AuthenticationRequired,
});
}
const graphQLClient = getGraphQLClient.user({ auth });
const { account } = await graphQLClient.request(BillingQuery, {
accountNumber,
});
if (!account) {
return { notFound: true };
}
return {
props: {
account,
isMasquerading: auth.session.authMethod === "masquerade",
},
};
}
Server-side operations need different behavior when staff are masquerading, such as bypassing certain validations or applying special business rules.
A server action that allows viewing sensitive customer information during masquerade sessions but requires additional verification for regular users.
Show implementation
"use server";
import { getAuth, getGraphQLClient } from "@/lib/auth/server";
import { graphql } from "@/lib/graphql";
const SensitiveDataQuery = graphql(`
query GetSensitiveData($accountNumber: String!) {
account(accountNumber: $accountNumber) {
id
personalDetails {
email
phoneNumber
address
}
}
}
`);
export async function getSensitiveData(accountNumber: string) {
const auth = await getAuth.user();
// Staff can view without additional verification.
if (auth?.session.authMethod === "masquerade") {
const graphQLClient = getGraphQLClient.user({ auth });
return graphQLClient.request(SensitiveDataQuery, { accountNumber });
}
// Regular users need to verify their identity
throw new Error("Additional verification required");
}
Security Considerations
- Token sensitivity: masquerade tokens grant full account access. Handle them as passwords.
- HTTPS only: never transmit masquerade tokens over unencrypted connections.
- Token invalidation: authentication errors clear the tokens.
- No token refresh: masquerade tokens cannot be refreshed. Staff must authenticate again.
FAQ
How does masquerade authentication work?
- Staff clicks masquerade button in Kraken support site, which navigates to
masquerade URL with embedded token, for example
/masquerade/{userId}/.../{masqueradeToken} - Next.js middleware intercepts the request
getMasqueradeParamsfunction extractsuserIdandmasqueradeTokenfrom URL- Middleware calls
masqueradeAuthenticationGraphQL mutation with the token and user ID - Kraken validates the token and user ID, then returns an access token.
- Middleware verifies
tokenUse: "access"andgty: "MASQUERADE". - Middleware clears the current managed session.
- Middleware stores the token in
accessToken. - Staff gains access to the user's account.
What happens if a staff member is already authenticated?
The middleware removes all managed session cookies. It then creates a new masquerade session. This prevents use of the staff member's identity or an old masquerade identity.
How do staff exit masquerade mode?
Staff exit masquerade mode by using the standard logout functionality. Call the
logout function or use the useLogout hook. Logout clears the managed session
cookies, including accessToken.
What happens when a masquerade token is invalid?
When an invalid masquerade token is provided:
- Authentication fails in middleware.
- Blueprint Auth clears all managed session cookies and
oAuthIdToken. - Blueprint Auth keeps
pkceVerifierfor an OAuth flow that is in progress. - The user is redirected to the login page or the configured error page.
- Staff must get a new masquerade token before they try again.
Next Steps
Now that you have masquerade authentication configured, explore these related guides:
- Anonymous Auth: Enable pre-signed key authentication for temporary access
- Kraken OAuth: Enable OAuth-based authentication flows
- Organization-Scoped Auth: Restrict authentication to specific organizations
API Reference
Quick reference to relevant functions:
createAuthConfig: Configure masquerade auth routescreateAuthMiddleware: Enable middleware handlinggetAuth.user: Resolve the masquerade tokengetGraphQLClient.user: Make authenticated GraphQL requests with the resolved context