Coming Soon
Sign in with Nerve is under development. Preview the planned functionality below.
Sign in with NerveComing Soon
OAuth-like authentication for AI agents. Enable your platform to verify agent identities with cryptographic proof.
The OAuth of AI Agents
"Sign in with Nerve" lets AI agents authenticate with your service using their cryptographic identity. No passwords, no API keys - just Ed25519 signatures and W3C DIDs.
Two Authentication Flows
UI Flow (OAuth-like)
For web applications where users interact via browser. Redirects to NervePay for agent selection, then back with an auth code.
- 1.User clicks "Sign in with Nerve" button
- 2.Redirect to NervePay authorize page
- 3.User selects agent identity
- 4.Redirect back with authorization code
- 5.Exchange code for access token
Server Flow (Headless)
For AI agents authenticating programmatically without a UI. Uses Ed25519 signatures to prove identity.
- 1.Request authentication challenge
- 2.Agent signs challenge with private key
- 3.Submit signed challenge
- 4.Receive access token
Button Component
React / Next.js
import { SignInWithNerve } from '@nervepay/react';
function LoginPage() {
return (
<SignInWithNerve
clientId="your-app.com"
redirectUri="https://your-app.com/auth/callback"
scope="identity"
/>
);
}UI Flow Implementation
1. Add the Button
Add the "Sign in with Nerve" button to your login page:
<!-- HTML/JavaScript --> <a href="https://nervepay.xyz/auth/nerve/authorize? client_id=your-app.com& redirect_uri=https://your-app.com/callback& scope=identity& response_type=code& state=random-csrf-token" class="nerve-button"> Sign in with Nerve </a>
2. Handle the Callback
When the user authorizes, they'll be redirected to your callback URL with a code:
// Your callback endpoint receives:
// GET /callback?code=abc123&state=random-csrf-token
// Verify state matches what you sent
if (state !== storedState) throw new Error('CSRF detected');
// Exchange code for token
const response = await fetch('https://api.nervepay.xyz/v1/oauth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'authorization_code',
code: code,
redirect_uri: 'https://your-app.com/callback',
client_id: 'your-app.com',
}),
});
const { access_token, agent_did, agent_name, reputation_score } = await response.json();3. Verify the Token (Optional)
For additional security, verify the token with NervePay:
const verifyResponse = await fetch('https://api.nervepay.xyz/v1/oauth/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ access_token }),
});
const {
valid,
agent_did,
agent_name,
public_key,
reputation_score,
capabilities,
} = await verifyResponse.json();
if (valid) {
// Agent is authenticated! Create session, etc.
}Server Flow Implementation (Headless)
Use this flow when an AI agent needs to authenticate programmatically without user interaction. The agent proves its identity by signing a challenge with its Ed25519 private key.
1. Request Challenge
# Request a challenge for the agent to sign
curl -X POST https://api.nervepay.xyz/v1/oauth/challenge \
-H "Content-Type: application/json" \
-d '{
"client_id": "your-app.com",
"agent_did": "did:nervepay:agent:abc123...",
"scope": "identity"
}'
# Response:
{
"challenge": "{"challenge_id":"...","agent_did":"...","nonce":"..."}",
"challenge_id": "uuid",
"expires_at": "2026-02-03T12:05:00Z",
"message": "Sign this challenge..."
}2. Agent Signs Challenge
import nacl from 'tweetnacl';
import { Buffer } from 'buffer';
// Agent's private key (Ed25519, 64 bytes base58)
const privateKey = bs58.decode(process.env.AGENT_PRIVATE_KEY);
// Sign the challenge
const message = Buffer.from(challenge);
const signature = nacl.sign.detached(message, privateKey);
const signatureBase64 = Buffer.from(signature).toString('base64');3. Authenticate with Signature
curl -X POST https://api.nervepay.xyz/v1/oauth/authenticate \
-H "Content-Type: application/json" \
-d '{
"challenge_id": "uuid-from-step-1",
"agent_did": "did:nervepay:agent:abc123...",
"signature": "base64-encoded-signature"
}'
# Response:
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600,
"agent_did": "did:nervepay:agent:abc123...",
"agent_name": "My Agent",
"reputation_score": 85.5,
"scope": "identity",
"public_key": "ed25519:..."
}Complete Python Example
import requests
import nacl.signing
import base64
import base58
class NerveAuth:
"""Authenticate an AI agent with NervePay using Sign in with Nerve."""
def __init__(self, agent_did: str, private_key_base58: str):
self.agent_did = agent_did
self.private_key = base58.b58decode(private_key_base58)
self.base_url = "https://api.nervepay.xyz"
def authenticate(self, client_id: str) -> dict:
"""Authenticate and get access token."""
# Step 1: Request challenge
challenge_resp = requests.post(
f"{self.base_url}/v1/oauth/challenge",
json={
"client_id": client_id,
"agent_did": self.agent_did,
"scope": "identity"
}
)
challenge_data = challenge_resp.json()
# Step 2: Sign challenge
signing_key = nacl.signing.SigningKey(self.private_key[:32])
signature = signing_key.sign(challenge_data["challenge"].encode())
signature_b64 = base64.b64encode(signature.signature).decode()
# Step 3: Authenticate
auth_resp = requests.post(
f"{self.base_url}/v1/oauth/authenticate",
json={
"challenge_id": challenge_data["challenge_id"],
"agent_did": self.agent_did,
"signature": signature_b64
}
)
return auth_resp.json()
# Usage
auth = NerveAuth(
agent_did="did:nervepay:agent:abc123...",
private_key_base58="your-private-key-base58"
)
token_data = auth.authenticate(client_id="your-app.com")
print(f"Access Token: {token_data['access_token']}")
print(f"Agent: {token_data['agent_name']} (rep: {token_data['reputation_score']})")API Reference
GET /auth/nerve/authorizeOAuth authorize page (UI flow). Redirects user to select agent identity.
| Parameter | Required | Description |
|---|---|---|
| client_id | Yes | Your application identifier |
| redirect_uri | Yes | Where to redirect after auth |
| scope | No | Requested permissions (default: identity) |
| state | No | CSRF protection token |
POST /v1/oauth/tokenExchange authorization code for access token.
POST /v1/oauth/challengeRequest authentication challenge (server-side flow).
POST /v1/oauth/authenticateSubmit signed challenge to get access token (server-side flow).
POST /v1/oauth/verifyVerify an access token and get agent information.