Integrate your existing authentication provider and add smart wallet functionality to your app without changing your users' login experience. We support JWT-based and OIDC-compliant authentication providers.
Before implementing JWT authentication, verify that your authentication system meets these requirements:
Your authentication system must be OpenID Connect (OIDC) compliant and capable of issuing JWT tokens.
OpenID Connect Discovery Endpoint
Host a discovery endpoint at: <YOUR_API_DOMAIN>/.well-known/openid-configuration
The response must include these required fields from the OpenID spec:
{
"issuer": "<YOUR_API_DOMAIN>",
"jwks_uri": "<YOUR_JWKS_ENDPOINT_URL>",
"id_token_signing_alg_values_supported": ["RS256"],
"authorization_endpoint": "<YOUR_AUTH_ENDPOINT>",
"response_types_supported": ["<YOUR_SUPPORTED_RESPONSE_TYPE>"],
"subject_types_supported": ["<YOUR_SUPPORTED_SUBJECT_TYPE>"]
}Field explanations:
issuer: Your API domain (must match theissclaim in your JWTs)jwks_uri: Endpoint URL where Alchemy can retrieve the JWT public key for verificationid_token_signing_alg_values_supported: Must include "RS256" algorithm
JWT Header Requirements
Your JWT header must include:
| Field | Description | Example |
|---|---|---|
alg | Algorithm used to sign the JWT | "RS256" |
typ | Token type | "JWT" |
kid | Key ID that matches the kid field from your JWKs URI | "key-1" |
Important: The kid field in the JWT header must correspond to a key identifier from your JWKS endpoint to enable proper key lookup during token verification.
JWT Payload Requirements
Your JWTs must contain these claims:
| Claim | Description | Example |
|---|---|---|
iss | Issuer - your auth provider's API domain | "https://auth.example.com" |
sub | Subject - unique user identifier | "user123" or "550e8400-e29b-41d4-a716-446655440000" |
aud | Audience - client ID issued by Alchemy | "your-alchemy-audience-id" |
nonce | Target public key hash (see below) | "a1b2c3d4..." |
Important: The nonce claim must be toHex(sha256(targetPublicKey)) without the leading 0x.
You can generate the targetPublicKey from the Alchemy Signer
SDK
If your OAuth provider reserves the nonce claim, you can use tknonce as an
alternative. Only one of nonce or tknonce needs to be set.
The combination of (iss, sub, aud) acts as a unique user identifier.
Ensure these values are consistent for each user.
The aud claim must be set to your Alchemy-provided audience ID. You can obtain the audience claim from your Smart Wallet settings in the Alchemy Dashboard.
npm install @account-kit/signer @account-kit/reactBefore creating your JWT, generate the required targetPublicKey:
import { AlchemySignerWebClient } from "@account-kit/signer";
import { sha256, stringToBytes } from 'viem'
const client = new AlchemySignerWebClient({
connection: {
apiKey: "your-api-key",
},
iframeConfig: {
iframeContainerId: "signer-iframe-container",
},
});
// Generate the target public key
const targetPublicKey = await client.targetPublicKey();
// Use this in your JWT's nonce claim
const nonce = sha256(stringToBytes(targetPublicKey)).slice(2)After generating your JWT with the proper claims, authenticate the user:
import { useAuthenticate } from "@account-kit/react";
// Inside your component
const { authenticate, isPending } = useAuthenticate();
const handleJwtAuth = async (jwt: string) => {
try {
await authenticate({
type: "custom-jwt",
jwt // Your generated JWT with required claims
});
} catch (error) {
console.error("Authentication failed:", error);
}
};Monitor authentication status and handle the connected user:
import { useSignerStatus, useUser } from "@account-kit/react";
const MyComponent = () => {
const { isConnected } = useSignerStatus();
const user = useUser();
if (isConnected && user) {
return (
<div>
<p>Welcome, {user.email}!</p>
<p>Wallet Address: {user.address}</p>
</div>
);
}
return <div>Not authenticated</div>;
};The JWT authentication flow works as follows:
- User Authentication: User logs into your existing auth system
- JWT Generation: Your backend generates a JWT with required claims
- Submit to Alchemy: Frontend submits JWT to Alchemy's auth endpoint
- Verification: Alchemy verifies JWT using your JWKS endpoint
- Wallet Access: User gains access to their smart wallet
sequenceDiagram
participant User
participant YourApp as Your Application
participant YourAuth as Your Auth System
participant Alchemy as Alchemy API
User->>YourApp: Login request
YourApp->>YourAuth: Authenticate user
YourAuth->>YourApp: Return JWT
YourApp->>Alchemy: Submit JWT (/v1/auth-jwt)
Alchemy->>YourApp: Verify JWT and return credentials/wallet info
YourApp->>User: Wallet readyUse jwt.io to decode and validate your JWT structure before integration.
issmatches your OpenID config issuersubcontains unique user identifieraudcontains your Alchemy-provided audience IDnonceortknoncecontainstoHex(sha256(targetPublicKey))without0x- JWT is signed with RS256 algorithm
- Verify your
.well-known/openid-configurationendpoint is accessible - Test JWKS endpoint returns valid public keys
- Validate JWT signature verification works
- Test complete authentication flow with sample users
Once your users have been authenticated, you can start sending transactions.
Start sponsoring gas fees for transactions via the Gas Manager.