Third-Party Authentication
Third-party authentication enables you to use your existing OAuth2 authentication system with UTXOS wallets. By passing a user’s refresh token, you skip the UTXOS authorization step entirely, creating a seamless wallet experience.
Third-party authentication is available on the Scale plan only.
How does third-party authentication work?
- Your application authenticates users through your existing OAuth2 flow
- You obtain and store the user’s refresh token
- When enabling the UTXOS wallet, you pass the refresh token
- UTXOS validates the token and creates the wallet session automatically
This approach eliminates duplicate login prompts when your users already have an active session.
Provider Configuration
Each OAuth2 provider has specific requirements. Select your provider below for detailed instructions.
Google OAuth2 has a unique advantage: UTXOS does not require your Client ID and Secret for third-party authentication because Google allows access token generation from refresh tokens without client authentication.
Prerequisites
- A Google OAuth2 Client for Web Application
- Third-party authentication enabled in your UTXOS project dashboard
Enable in Dashboard
Navigate to your project settings in the UTXOS Dashboard and enable Third Party Authentication for Google.

Required Scopes
Your OAuth2 flow must request these scopes:
| Scope | Purpose |
|---|---|
https://www.googleapis.com/auth/userinfo.email | User’s email address |
https://www.googleapis.com/auth/userinfo.profile | User’s profile information |
Authorization URL Configuration
Configure your authorization URL to obtain a refresh token:
const googleSearchParams = new URLSearchParams({
client_id: process.env.GOOGLE_CLIENT_ID,
redirect_uri: process.env.GOOGLE_REDIRECT_URL,
response_type: "code",
access_type: "offline", // Required to obtain refresh_token
prompt: "consent", // Required to obtain refresh_token
scope: [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
].join(" "),
});
const authorizeUrl =
"https://accounts.google.com/o/oauth2/v2/auth?" +
googleSearchParams.toString();Both access_type: "offline" and prompt: "consent" are required to receive a refresh token from Google.
Token Exchange
After the user completes authorization, exchange the code for tokens:
const tokenResponse = await fetch("https://oauth2.googleapis.com/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: process.env.GOOGLE_CLIENT_ID,
client_secret: process.env.GOOGLE_CLIENT_SECRET,
code: authorizationCode,
grant_type: "authorization_code",
redirect_uri: process.env.GOOGLE_REDIRECT_URL,
}),
});
const { refresh_token } = await tokenResponse.json();
// Store refresh_token securely for later useEnable UTXOS Wallet
Pass the refresh token when enabling the wallet:
import { Web3Wallet } from "@anthropic-ai/web3-wallet";
const wallet = await Web3Wallet.enable({
projectId: process.env.UTXOS_PROJECT_ID,
networkId: 0,
directTo: "google",
refreshToken: storedRefreshToken,
});
const address = await wallet.getChangeAddress();
console.log("Wallet address:", address);Complete Integration Example
Here is a full example integrating Google third-party authentication:
import { Web3Wallet } from "@anthropic-ai/web3-wallet";
// Your OAuth2 callback handler
async function handleOAuthCallback(code: string): Promise<void> {
// Exchange code for tokens
const tokenResponse = await fetch("https://oauth2.googleapis.com/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
client_id: process.env.GOOGLE_CLIENT_ID,
client_secret: process.env.GOOGLE_CLIENT_SECRET,
code,
grant_type: "authorization_code",
redirect_uri: process.env.GOOGLE_REDIRECT_URL,
}),
});
const { refresh_token, access_token } = await tokenResponse.json();
// Store tokens securely (e.g., in your database)
await saveUserTokens(userId, { refresh_token, access_token });
}
// When the user needs to interact with their wallet
async function getWallet(userId: string): Promise<Web3Wallet> {
const { refresh_token } = await getUserTokens(userId);
const wallet = await Web3Wallet.enable({
projectId: process.env.UTXOS_PROJECT_ID,
networkId: 0,
directTo: "google",
refreshToken: refresh_token,
});
return wallet;
}
// Usage
const wallet = await getWallet(currentUserId);
const address = await wallet.getChangeAddress();
const balance = await wallet.getBalance();Security Best Practices
Token Storage
- Store refresh tokens encrypted in your database
- Never expose refresh tokens to the client
- Use secure, HTTP-only cookies if tokens must be in the browser
Token Refresh
- Implement automatic token refresh before expiration
- Handle refresh failures gracefully with re-authentication
Error Handling
try {
const wallet = await Web3Wallet.enable({
projectId: process.env.UTXOS_PROJECT_ID,
networkId: 0,
directTo: "google",
refreshToken: storedRefreshToken,
});
} catch (error) {
if (error.code === "INVALID_REFRESH_TOKEN") {
// Token expired or revoked - redirect to re-authenticate
redirectToOAuthFlow();
} else {
// Handle other errors
console.error("Wallet initialization failed:", error);
}
}Troubleshooting
”Invalid refresh token” Error
The refresh token has expired or been revoked. Redirect the user through the OAuth flow again to obtain a new token.
”Missing required scopes” Error
Your OAuth flow did not request all required scopes. Update your authorization URL to include the necessary scopes for your provider.
”Third-party auth not enabled” Error
Enable third-party authentication for the provider in your UTXOS project dashboard.
Token Not Received
For Google, ensure both access_type: "offline" and prompt: "consent" are included. For other providers, check that offline access is requested.
