Use when implementing OAuth login with zero-knowledge proofs, integrating Google/Facebook/Twitch authentication, or enabling privacy-preserving login on SUI. Triggers on zkLogin integration, OAuth authentication, or privacy-focused auth requirements.
From sui-dev-agentsnpx claudepluginhub first-mover-tw/sui-dev-agents --plugin sui-dev-agentsThis skill uses the workspace's default tool permissions.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
OAuth-based wallet authentication with zero-knowledge proofs.
zkLogin allows users to:
import { ZkLoginProvider } from '@mysten/zklogin';
const zkLogin = new ZkLoginProvider({
network: 'testnet',
provider: 'google' // or 'facebook', 'twitch'
});
// 1. Initiate login
async function login() {
const { url, nonce } = await zkLogin.getLoginUrl();
// Store nonce for later
sessionStorage.setItem('zklogin_nonce', nonce);
// Redirect to OAuth provider
window.location.href = url;
}
// 2. Handle callback
async function handleCallback() {
const params = new URLSearchParams(window.location.search);
const jwt = params.get('id_token');
const nonce = sessionStorage.getItem('zklogin_nonce');
// Generate ZK proof
const proof = await zkLogin.getProof(jwt, nonce);
// Get SUI address
const address = await zkLogin.getAddress(proof);
return { proof, address };
}
// 3. Sign transactions
async function signTransaction(tx: Transaction) {
const signedTx = await zkLogin.signTransaction(tx);
return signedTx;
}
// No special Move code needed!
// zkLogin addresses are regular SUI addresses
// Use tx_context::sender(ctx) as normal
public fun create_profile(
name: String,
ctx: &mut TxContext
) {
let user = tx_context::sender(ctx); // Works with zkLogin!
// Create user profile
// ...
}
// Complete zkLogin implementation
import { ZkLoginProvider, generateNonce } from '@mysten/zklogin';
import { SuiGrpcClient } from '@mysten/sui/grpc';
class ZkLoginAuth {
private provider: ZkLoginProvider;
private client: SuiGrpcClient;
constructor() {
this.provider = new ZkLoginProvider({
network: 'testnet',
provider: 'google'
});
this.client = new SuiGrpcClient({ network: 'testnet' });
}
async login() {
// Generate nonce
const nonce = generateNonce();
localStorage.setItem('zklogin_nonce', nonce);
// Get OAuth URL
const authUrl = this.provider.getAuthUrl({
nonce,
redirectUrl: 'http://localhost:3000/callback'
});
// Redirect
window.location.href = authUrl;
}
async handleCallback() {
const params = new URLSearchParams(window.location.search);
const jwt = params.get('id_token');
const nonce = localStorage.getItem('zklogin_nonce');
if (!jwt || !nonce) {
throw new Error('Missing JWT or nonce');
}
// Generate ZK proof
const proof = await this.provider.getProof(jwt, nonce);
// Derive address
const address = this.provider.getAddress(proof);
// Store session
localStorage.setItem('zklogin_proof', JSON.stringify(proof));
localStorage.setItem('zklogin_address', address);
return { address, proof };
}
async signAndExecuteTransaction(tx: Transaction) {
const proof = JSON.parse(localStorage.getItem('zklogin_proof')!);
const signed = await this.provider.signTransaction(tx, proof);
const result = await this.client.core.executeTransaction({
transaction: signed,
signature: proof.signature
});
return result;
}
}
function useZkLogin() {
const [address, setAddress] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(false);
const login = async (provider: 'google' | 'facebook') => {
setIsLoading(true);
const zkLogin = new ZkLoginProvider({ network: 'testnet', provider });
const { url, nonce } = await zkLogin.getLoginUrl();
sessionStorage.setItem('nonce', nonce);
window.location.href = url;
};
const handleCallback = async () => {
const auth = new ZkLoginAuth();
const { address } = await auth.handleCallback();
setAddress(address);
setIsLoading(false);
};
return { address, login, handleCallback, isLoading };
}
❌ Exposing OAuth client secret in frontend
❌ Not validating JWT signature
❌ Reusing nonce across sessions
❌ Storing ZK proof in localStorage unencrypted
❌ No fallback when OAuth provider is down
❌ Not handling token expiration
Query latest zkLogin updates:
const zkLoginInfo = await sui_docs_query({
type: "github",
target: "zklogin",
query: "OAuth integration examples and best practices"
});
Seamless user onboarding with familiar OAuth login!