Kraken OAuth
To enable login functionality on a consumer site, you can authenticate with
Kraken as an identity provider instead of directly providing email and password
to the obtainKrakenToken mutation. This approach is particularly beneficial
when customers use the same login for multiple applications, as it allows the
creation of a single login form that can be used independently by different
consuming applications.
Getting started​
This guide extends the Blueprint Auth setup for the Pages Router or the App Router. Complete one setup guide before you continue.
Configuration​
To enable Kraken OAuth, you need to provide the following configuration options:
| Option | Description | Type | Environment variable | Required |
|---|---|---|---|---|
krakenConfig.authEndpoint | The Kraken auth endpoint | string | KRAKEN_AUTH_ENDPOINT | ✅ |
krakenConfig.oauthClientId | The Kraken OAuth client ID | string | KRAKEN_OAUTH_CLIENT_ID | ✅ |
apiRoutes.krakenOAuth | Kraken OAuth API endpoint | string | ✅ | |
validation.accessTokenIssuers | Exact trusted access token issuers | string[] | KRAKEN_ACCESS_TOKEN_ISSUERS | ✅ |
Environment variables​
Define the following environment variables in your .env.local file:
KRAKEN_AUTH_ENDPOINT="https://auth.xxxx-kraken.systems/"
KRAKEN_ACCESS_TOKEN_ISSUERS="https://api.xxxx-kraken.systems/v1/graphql/,https://auth.xxxx-kraken.systems/token/,https://support.xxxx-kraken.systems"
KRAKEN_OAUTH_CLIENT_ID="Kraken OAuth client ID"
Use the exact access token issuers for your Kraken environment. For OAuth, add
token/ to the exact Kraken auth endpoint. Replace the example domains above
with your values. Issuer matching is case-sensitive. Paths and trailing slashes
are significant.
When deploying to Vercel, configure environment variables in the
Vercel dashboard rather than
committing them to .env files.
The use of environment variables is strongly recommended for supported options.
Configuration object​
import { createAuthConfig } from "@krakentech/blueprint-auth";
export const authConfig = createAuthConfig({
apiRoutes: {
graphql: { kraken: "/api/graphql/kraken" },
krakenOAuth: "/api/auth/kraken-oauth",
login: "/api/auth/login",
logout: "/api/auth/logout",
session: "/api/auth/session",
},
appRoutes: {
dashboard: { pathname: "/dashboard" },
home: { pathname: "/" },
login: { pathname: "/login" },
},
});
Middleware​
The middleware is responsible for protecting routes and refreshing auth tokens.
Make sure the createAuthMiddleware function in your middleware.ts file
receives the required Kraken OAuth configuration options.
API handler​
The API handler is responsible for storing auth tokens obtained from the Kraken Authorisation Server API as cookies. It redirects the user to the dashboard page if authentication is successful, or to the login page in case an error occurs.
Create the Kraken OAuth API handler using
createKrakenOAuthHandler.
- 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);
Server Function​
The generateKrakenOAuthURI Server Function is responsible for generating the
Kraken OAuth URI, which is used to initiate the OAuth flow.
Choose one server function setup:
- Direct
- Server-side
- App Router
import { generateKrakenOAuthURI } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";
const oauthUri = await generateKrakenOAuthURI(authConfig, { context });
import { createServerSideAuth } from "@krakentech/blueprint-auth/server";
import { cacheAdapter } from "./cache";
import { authConfig } from "./config";
export const { generateKrakenOAuthURI } = createServerSideAuth(authConfig, {
cacheAdapter,
});
import { createAppRouterAuth } from "@krakentech/blueprint-auth/server";
import { cookies, headers } from "next/headers";
import { cache } from "react";
import { cacheAdapter } from "./cache";
import { authConfig } from "./config";
export const { generateKrakenOAuthURI } = createAppRouterAuth(authConfig, {
cache,
cacheAdapter,
cookies,
headers,
});
Initiate the OAuth flow​
- Pages Router
- App Router
Generate the OAuth URI in the getServerSideProps function of your login page
and pass it to the OAuthButton component.
import type {
GetServerSidePropsContext,
InferGetServerSidePropsType,
} from "next";
import { Button } from "@radix-ui/themes";
import { LoginForm } from "@/components/LoginForm";
import { generateKrakenOAuthURI } from "@/lib/auth/server";
export default function LoginPage({
oAuthURI,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
return (
<>
<LoginForm />
<Button asChild>
<a href={oAuthURI}>Log in with Kraken</a>
</Button>
</>
);
}
export async function getServerSideProps(context: GetServerSidePropsContext) {
const oAuthURI = await generateKrakenOAuthURI({ context });
return { props: { oAuthURI } };
}
generateKrakenOAuthURI writes the Proof Key for Code Exchange (PKCE) verifier
cookie. Server Components
cannot write cookies. Call this function from a Server Action.
Create a Server Action that generates the URL and redirects the current browser window.
"use server";
import { redirect } from "next/navigation";
import { generateKrakenOAuthURI } from "@/lib/auth/server";
export async function startKrakenOAuthAction() {
redirect(await generateKrakenOAuthURI());
}
Submit the action from the login page.
import { LoginForm } from "@/components/LoginForm";
import { startKrakenOAuthAction } from "@/actions/startKrakenOAuth";
export default function LoginPage() {
return (
<>
<LoginForm />
<form action={startKrakenOAuthAction}>
<button type="submit">Log in with Kraken</button>
</form>
</>
);
}
Learn more about the OAuth flow​
This section explains the OAuth concepts behind the integration. You only need to set the options in the Configuration section.
This integration uses PKCE. Instead of a
static client secret, the package generates a one-time code verifier and
challenge for each login and stores the verifier in a pkceVerifier cookie. You
do not need to obtain, store, or configure a client secret anywhere.
OAuth values​
| Name | Description |
|---|---|
| Client ID | A public identifier for the application. It is unique to the application and is used by the Kraken server to identify the application making the request. It is generated when an application is registered with Kraken. |
| Client Secret | A confidential value that some OAuth flows use to authenticate the application. This integration does not use one. It uses PKCE instead. |
| Redirect URI | The URL to which the Kraken server will send the user after they have successfully completed authorisation. This must match one of the redirect URIs registered with the application. It is used to ensure that the authorization code is sent to the correct application. |
| Authorize URI | The URL of the Kraken server's authorisation endpoint. The application sends the user to this URL in order to start the authorization process. The Authorize URI includes parameters that tell the Kraken server about the request, including the Client ID, Redirect URI, and Code Challenge. |
In this context, a code challenge is a cryptographic value that the client application generates and sends to the Kraken server as part of the authorization request. The code challenge is used to verify the integrity of the authorization process and prevent certain types of attacks, such as authorization code interception.
Blueprint Auth sets pkceVerifier when the flow starts. After a successful
exchange and token verification, it sets accessToken, refreshToken, and
oAuthIdToken. It does not use sub or authProvider cookies.
The Kraken auth server can set other cookies, such as octosession.
Session State​
When users authenticate via Kraken OAuth, the session state will reflect the OAuth authentication method:
| Field | Value | Description |
|---|---|---|
authMethod | "oauth" | The verified grant is OPENID-CONNECT |
authSource | "web" | The token came from the web accessToken cookie |
isAuthenticated | true | The request has a verified user token |
See Session management for an overview of the session lifecycle.
Check the authentication method before you show method-specific user interface. Use the factory call for your router.
- Pages Router
- App Router
import type { GetServerSidePropsContext } from "next";
import { getSession } from "@/lib/auth/server";
type AccountPageProps = { usedOAuth: boolean };
export default function AccountPage({ usedOAuth }: AccountPageProps) {
return (
<p>
{usedOAuth
? "Authenticated with OAuth"
: "Authenticated without OAuth"}
</p>
);
}
export async function getServerSideProps(context: GetServerSidePropsContext) {
const session = await getSession({ context });
return {
props: {
usedOAuth: session.authMethod === "oauth",
},
};
}
import { getSession } from "@/lib/auth/server";
export default async function AccountPage() {
const session = await getSession();
return (
<p>
{session.authMethod === "oauth"
? "Authenticated with OAuth"
: "Authenticated without OAuth"}
</p>
);
}
FAQ​
What happens in generateKrakenOAuthURI?
The generateKrakenOAuthURI Server Function performs the following tasks:
- Generate a unique code verifier and code challenge.
- Store the code verifier in a secure HTTP-only cookie to send with the request headers.
- Create a URI to be navigated to, using the Redirect URI, Client ID and Authorise URI.
How is the OAuth flow initiated?
The OAuth flow is initiated when a user clicks on the "Login with Kraken Auth"
button. The browser navigates to the Kraken URI generated using
generateKrakenOAuthURI, where the user authenticates and authorises the
application.
How is the OAuth flow completed?
After the user authorises the application on the Kraken website, they are redirected back to the Kraken OAuth API route with an authorisation code. The Kraken OAuth handler then:
- Reads the code verifier from the cookie.
- Exchanges the code and verifier for an identity token, access token, and refresh token.
- Removes
pkceVerifierafter the exchange succeeds. - Verifies the identity token issuer and OAuth client ID audience.
- Verifies that the access token is an OAuth access token.
- Requires both verified tokens to have the same
sub. - Stores
accessToken,refreshToken, andoAuthIdToken. - Redirects the user to the dashboard.
Blueprint Auth does not restore pkceVerifier if token verification fails after
the exchange. It does not perform an OpenID Connect nonce check.
How are errors handled?
The serverless function responsible for handling the OAuth flow includes error handling logic via an error handler to deal with authorisation related errors. When an error is caught, the user is redirected to the application's login page by default, where a relevant error message may be displayed.
How are the tokens used?
The access token authenticates subsequent Kraken API requests. Blueprint Auth
uses the refresh token to replace the access token before it expires. The
accessToken cookie expiry comes from the verified exp claim.
How does Blueprint Auth refresh an access token?
Blueprint Auth sends the refresh token to Kraken before the access token expires. It verifies the replacement access token before use. If Kraken rejects an expired, invalid, or unauthorized refresh token, Blueprint Auth ends the local session. See Session management for the complete refresh failure policy.
What happens when a user logs out?
Logout removes the managed session cookies and oAuthIdToken. It keeps
pkceVerifier so an OAuth flow that is in progress can finish.