Skip to main content

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:

OptionDescriptionTypeEnvironment variableRequired
krakenConfig.authEndpointThe Kraken auth endpointstringKRAKEN_AUTH_ENDPOINT✅
krakenConfig.oauthClientIdThe Kraken OAuth client IDstringKRAKEN_OAUTH_CLIENT_ID✅
apiRoutes.krakenOAuthKraken OAuth API endpointstring✅
validation.accessTokenIssuersExact trusted access token issuersstring[]KRAKEN_ACCESS_TOKEN_ISSUERS✅

Environment variables​

Define the following environment variables in your .env.local file:

.env.local
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.

Vercel Deployment

When deploying to Vercel, configure environment variables in the Vercel dashboard rather than committing them to .env files.

Environment Variables

The use of environment variables is strongly recommended for supported options.

Configuration object​

lib/auth/config.ts
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/api/auth/kraken-oauth.ts
import { createKrakenOAuthHandler } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";

export default 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:

import { generateKrakenOAuthURI } from "@krakentech/blueprint-auth/server";
import { authConfig } from "@/lib/auth/config";

const oauthUri = await generateKrakenOAuthURI(authConfig, { context });

Initiate the OAuth flow​

Generate the OAuth URI in the getServerSideProps function of your login page and pass it to the OAuthButton component.

pages/login.tsx
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 } };
}

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.

No client secret required

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​

NameDescription
Client IDA 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 SecretA confidential value that some OAuth flows use to authenticate the application. This integration does not use one. It uses PKCE instead.
Redirect URIThe 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 URIThe 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.
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.

Cookies set during the flow

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:

FieldValueDescription
authMethod"oauth"The verified grant is OPENID-CONNECT
authSource"web"The token came from the web accessToken cookie
isAuthenticatedtrueThe 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/account.tsx
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",
},
};
}

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:

  1. Reads the code verifier from the cookie.
  2. Exchanges the code and verifier for an identity token, access token, and refresh token.
  3. Removes pkceVerifier after the exchange succeeds.
  4. Verifies the identity token issuer and OAuth client ID audience.
  5. Verifies that the access token is an OAuth access token.
  6. Requires both verified tokens to have the same sub.
  7. Stores accessToken, refreshToken, and oAuthIdToken.
  8. 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.

Useful resources​

  1. OAuth 2.0 Simplified

  2. Modern Guide: What is OAuth 2.0 and How Does It Work?