Skip to main content

Auth Block

Auth Block

Enterprise-grade authentication for modern applications

The Auth Block is a complete authentication and authorization service that provides secure user management, JWT token handling, multi-factor authentication, passwordless login, AI agent identity, service tokens, OIDC provider capabilities, and multi-tenant support. It uses RS256 JWT tokens with company-specific RSA key pairs and follows the JSON:API specification.

Key Features​

  • RS256 JWT Authentication - Asymmetric encryption with company-level RSA keys
  • Multi-Factor Authentication - Two channels: email OTP (zero-friction) and TOTP (authenticator apps) with backup codes
  • Passwordless Login via Email OTP - 6-digit OTP with anti-enumeration and MFA gate
  • OIDC Provider - Discovery, JWKS, and token endpoint with 4 grant types including agent-identity
  • AI Agent Identity - Agent registration, Ed25519 signature verification, and OAuth token exchange
  • Service Tokens (M2M) - Agent tokens (24h) and service tokens (90 days) with scope validation
  • reCAPTCHA Bot Protection - Per-tenant inline enforcement with kill switch
  • Magic Link Authentication - Create, validate, exchange, and send passwordless login links
  • API Key Management - Service-to-service authentication with AWS Gateway integration
  • Multi-tenant Architecture - Complete data isolation per tenant using PostgreSQL schemas
  • OAuth 2.0 Refresh Tokens - Optional long-lived session support
  • Role-Based Access Control - Fine-grained permissions system
  • Block Permissions Provisioning - HMAC-authenticated internal scope registry

API Endpoint​

ServiceURL
Authhttps://auth.api.us.23blocks.com

Environment Routing: One URL, one environment. All shared-platform API keys are live keys:

  • pk_live_* / sk_live_* → your production tenant. Need a separate staging environment? It is available as a paid add-on on deployments in your own cloud account — see 23blocks in a Box.

Quick Start​

Installation​

npm install @23blocks/sdk

Basic Authentication​

import { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { authentication: 'https://auth.api.us.23blocks.com' },
apiKey: 'your-api-key', // Your live API key (pk_live_*)
});

// Register a new user
const user = await client.auth.register({
email: 'user@example.com',
password: 'SecurePassword123',
name: 'John Doe',
confirmSuccessUrl: 'https://yourapp.com/confirmed'
});

// Login
const session = await client.auth.login({
email: 'user@example.com',
password: 'SecurePassword123'
});

// Access token is available
console.log(session.accessToken);

Authentication​

Required Headers​

All authenticated requests require:

Authorization: Bearer [JWT_TOKEN]
X-API-Key: [COMPANY_API_KEY]
Content-Type: application/json

JWT Token Structure​

Tokens are signed using RS256 with company-specific RSA keys. You can verify tokens using the public JWKS endpoint:

GET /:company_url_id/.well-known/jwks.json

API Reference​

User Registration​

curl -X POST https://auth.api.us.23blocks.com/auth \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"user": {
"email": "newuser@example.com",
"password": "SecurePassword123",
"password_confirmation": "SecurePassword123",
"name": "Jane Smith",
"confirm_success_url": "https://yourapp.com/email-confirmed"
}
}'

Response:

{
"data": {
"id": "usr_def456",
"type": "user",
"attributes": {
"unique_id": "usr_def456",
"email": "newuser@example.com",
"name": "Jane Smith",
"confirmed": false,
"confirmation_sent_at": "2024-01-15T10:30:00Z"
}
},
"meta": {
"message": "A confirmation email has been sent to newuser@example.com"
}
}

Sign In​

curl -X POST https://auth.api.us.23blocks.com/auth/sign_in \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123"
}'

Response:

{
"data": {
"id": "usr_abc123",
"type": "user",
"attributes": {
"unique_id": "usr_abc123",
"email": "user@example.com",
"name": "John Doe",
"confirmed": true,
"role_id": 5,
"mfa_enabled": false,
"mfa_channel": null
}
},
"meta": {
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 86400
}
}

If the user has MFA enabled, the sign-in response will include an mfa_required flag. Send the MFA code in a follow-up request.

Token Validation​

curl -X GET https://auth.api.us.23blocks.com/auth/validate_token \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key"

Password Reset​

Request reset:

curl -X POST https://auth.api.us.23blocks.com/auth/password \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"email": "user@example.com",
"redirect_url": "https://app.example.com/reset-password"
}'

Passwordless Users (v4.39+): When the user has has_password: false, this endpoint returns an OTP envelope instead of a reset link:

{
"data": {
"type": "passwordless",
"attributes": {
"status": "otp_sent",
"email_hint": "u***@example.com",
"expires_in": 600
}
}
}

The user should complete authentication via the passwordless verify flow (POST /auth/passwordless/verify).

Update password:

curl -X PUT https://auth.api.us.23blocks.com/auth/password \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"password": "NewSecurePassword123",
"password_confirmation": "NewSecurePassword123",
"reset_password_token": "abc123resettoken"
}'

Passwordless Login via Email OTP​

Send a 6-digit one-time password to the user's email for passwordless authentication. Anti-enumeration protection ensures the endpoint always returns 200 regardless of whether the email exists.

Request OTP​

curl -X POST https://auth.api.us.23blocks.com/auth/passwordless/request \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"email": "user@example.com"
}'

Response (always 200 for anti-enumeration):

{
"meta": {
"message": "If the email exists, a verification code has been sent."
}
}

Verify OTP​

curl -X POST https://auth.api.us.23blocks.com/auth/passwordless/verify \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"email": "user@example.com",
"otp_code": "123456"
}'

Response:

{
"data": {
"id": "usr_abc123",
"type": "user",
"attributes": {
"unique_id": "usr_abc123",
"email": "user@example.com",
"name": "John Doe"
}
},
"meta": {
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 86400
}
}

OTP Rules:

  • 6-digit numeric code
  • 10-minute TTL
  • Maximum 5 verification attempts
  • MFA gate applies on verify (same as sign_in)

Passwordless Registration (v4.39+)​

Create user accounts without passwords using a two-step email OTP flow. Users register with only email and name, then verify via OTP to complete registration and receive a JWT.

Step 1: Request Registration OTP​

curl -X POST https://auth.api.us.23blocks.com/auth/passwordless/register \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"user": {
"email": "newuser@example.com",
"name": "Jane Smith"
}
}'

Response:

{
"data": {
"type": "passwordless_registration",
"attributes": {
"status": "otp_sent",
"email_hint": "new***@example.com",
"expires_in": 600
}
}
}

Step 2: Verify OTP and Complete Registration​

curl -X POST https://auth.api.us.23blocks.com/auth/passwordless/register/verify \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"email": "newuser@example.com",
"otp_code": "123456"
}'

Response:

{
"data": {
"id": "usr_def789",
"type": "user",
"attributes": {
"unique_id": "usr_def789",
"email": "newuser@example.com",
"name": "Jane Smith",
"confirmed": true,
"provider": "email",
"has_password": false
}
},
"meta": {
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 86400
}
}

Key Features:

  • No password required during registration or future logins
  • User is automatically confirmed after OTP verification
  • Future logins use standard passwordless flow (POST /auth/passwordless/request → /verify)
  • Users can optionally add a password later via account settings

Detecting Passwordless Users:

const isPasswordless = user.provider === 'email' && user.has_password === false;

Multi-Factor Authentication​

Auth Block supports two MFA channels:

  • Email - Zero-friction OTP sent to the user's email
  • TOTP - Time-based one-time passwords via authenticator apps (Google Authenticator, Authy, etc.)

MFA Endpoints​

All MFA endpoints are under /users/:unique_id/mfa/:

EndpointMethodDescription
/mfa/setupPOSTInitialize MFA setup (returns QR code for TOTP, or sends email OTP)
/mfa/enablePOSTEnable MFA after verifying code
/mfa/disablePOSTDisable MFA (requires verification)
/mfa/verifyPOSTVerify an MFA code
/mfa/statusGETCheck MFA status and channel

Setup MFA (TOTP)​

curl -X POST https://auth.api.us.23blocks.com/users/usr_abc123/mfa/setup \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-d '{"channel": "totp"}'

Response:

{
"data": {
"id": "mfa_setup_123",
"type": "mfa_setup",
"attributes": {
"channel": "totp",
"secret": "JBSWY3DPEHPK3PXP",
"qr_code_url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
"backup_codes": ["12345678", "87654321", "11111111", "22222222", "33333333", "44444444", "55555555", "66666666", "77777777", "88888888"]
}
}
}

Setup MFA (Email)​

curl -X POST https://auth.api.us.23blocks.com/users/usr_abc123/mfa/setup \
-H "Authorization: Bearer your-jwt-token" \
-H "X-API-Key: your-api-key" \
-d '{"channel": "email"}'

Enable MFA​

After verifying the setup code:

curl -X POST https://auth.api.us.23blocks.com/users/usr_abc123/mfa/enable \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{"mfa_code": "123456"}'

Login with MFA​

When MFA is enabled, sign-in and passwordless verify flows require an MFA code:

curl -X POST https://auth.api.us.23blocks.com/auth/sign_in \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"email": "user@example.com",
"password": "SecurePassword123",
"mfa_code": "123456"
}'

Backup Codes: 10 one-time backup codes are generated during setup. Each can be used once in place of an MFA code. Usage is tracked.

reCAPTCHA Bot Protection​

Inline reCAPTCHA enforcement protects authentication endpoints from automated attacks. Configurable per-tenant with an instant kill switch.

How It Works​

  1. Enable reCAPTCHA enforcement in your tenant configuration (auth_config['recaptcha_enforcement'])
  2. Frontend obtains a reCAPTCHA token from Google
  3. Send the token as a top-level recaptcha_token parameter with protected requests

Protected Endpoints​

  • User registration (POST /auth)
  • Sign in (POST /auth/sign_in)
  • Passwordless OTP request (POST /auth/passwordless/request)
  • Password reset (POST /auth/password)
  • Password OTP (POST /auth/password/otp)

Example with reCAPTCHA​

curl -X POST https://auth.api.us.23blocks.com/auth \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"recaptcha_token": "03AGdBq24PBCbwiDRaS_MJ7Z...",
"user": {
"email": "newuser@example.com",
"password": "SecurePassword123",
"password_confirmation": "SecurePassword123",
"name": "Jane Smith"
}
}'

reCAPTCHA Error Codes​

CodeStatusDescription
GW-RC-001422reCAPTCHA token required (enforcement is enabled but no token sent)
GW-RC-003403reCAPTCHA verification failed (invalid or expired token)
GW-RC-004403reCAPTCHA score too low (suspected bot)

Rate Limiting​

In addition to reCAPTCHA, Rack::Attack rate limiting enforces 5 registrations per IP per 5 minutes.

Kill Switch​

Tenants can disable reCAPTCHA enforcement instantly by toggling the feature flag. No frontend changes required — the API will simply stop requiring the recaptcha_token parameter.

User Invitations​

Invite users to join your application:

curl -X POST https://auth.api.us.23blocks.com/auth/invitation \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-d '{
"user": {
"email": "newuser@example.com",
"name": "New User",
"role_id": 5,
"appid": "your-api-key",
"accept_invitation_url": "https://app.example.com/accept-invite"
}
}'

Magic links provide passwordless authentication via secure, time-limited tokens with delivery lifecycle tracking and audit trails.

Endpoints​

EndpointMethodDescription
/companies/:id/magic_linksPOSTCreate a new magic link
/companies/:id/magic_links/:id/validateGETValidate a magic link token
/companies/:id/magic_links/:id/exchangePOSTExchange magic link for JWT
/companies/:id/magic_links/:id/send_emailPOSTSend magic link via email
/companies/:id/magic_links/:id/verify_codePOSTVerify exchange code
/companies/:id/magic_links/:idDELETEDestroy a magic link
curl -X POST https://auth.api.us.23blocks.com/companies/your-company/magic_links \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"email": "user@example.com",
"redirect_url": "https://app.example.com/dashboard",
"expires_in": 900
}'

Exchange Code Pattern​

Magic links use an exchange code pattern with delivery lifecycle tracking:

  1. Create the magic link
  2. Send via email (tracks delivery status)
  3. Exchange the link token for a short-lived exchange code
  4. Verify the exchange code to receive a JWT

AI Agent Identity & Authentication​

Register and authenticate AI agents with Ed25519 cryptographic signatures. Agents receive their own OAuth tokens via a dedicated grant type.

Agent Registration​

curl -X POST https://auth.api.us.23blocks.com/companies/your-company/agents \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"agent": {
"name": "backend-processor",
"description": "Processes background tasks",
"public_key": "MCowBQYDK2VwAyEA...",
"scopes": ["files:read", "files:write", "crm:read"]
}
}'

Agent Lifecycle​

EndpointMethodDescription
/companies/:id/agentsPOSTRegister a new agent
/companies/:id/agentsGETList all agents
/companies/:id/agents/:idGETGet agent details
/companies/:id/agents/:idPUTUpdate agent
/companies/:id/agents/:idDELETEDelete agent
/companies/:id/agents/:id/suspendPOSTSuspend agent
/companies/:id/agents/:id/reactivatePOSTReactivate agent

Agent-Initiated Registration (RFC 8628)​

Agents can self-register using the RFC 8628 device authorization flow. The agent requests a temporary user code, an admin approves it, and the agent receives JWT tokens.

Step 1 — Agent requests registration:

curl -X POST https://auth.api.us.23blocks.com/agent_registrations/request \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"agent": {
"name": "my-assistant",
"public_key": "MCowBQYDK2VwAyEA...",
"scopes": ["files:read", "crm:read"]
}
}'

Response:

{
"authorization_url": "https://app.23blocks.com/agents/authorize?code=your-company.ABCD-EFGH",
"user_code": "ABCD-EFGH",
"expires_in": 86400,
"interval": 5,
"token_endpoint": "https://auth.api.us.23blocks.com/your-company/oauth/token"
}
  • user_code format: XXXX-XXXX (excludes confusing characters: 0, O, 1, I, L)
  • Code expires after 24 hours
  • interval is the minimum polling delay in seconds
  • token_endpoint is the OAuth endpoint where agents exchange their AID identity for a JWT (added in v4.38.x)
  • authorization_url domain is controlled by the company's agent_authorization_domain field (default: app.23blocks.com). This is separate from preferred_domain, which only affects email and login white-labeling. Set agent_authorization_domain when deploying a custom agent approval UI.
  • Authorization codes now use structured format: {company_url_id}.{opaque_secret} (e.g., your-company.ABCD-EFGH). Legacy plain codes remain supported.

Step 2 — Admin resolves and approves the code:

# Resolve the code to see agent details
curl https://auth.api.us.23blocks.com/agent_registrations/resolve?code=ABCD-EFGH \
-H "Authorization: Bearer admin-jwt-token" \
-H "X-API-Key: your-api-key"

Response:

{
"data": {
"id": "agr_abc123",
"type": "agent_registration",
"attributes": {
"unique_id": "agr_abc123",
"name": "my-assistant",
"public_key": "MCowBQYDK2VwAyEA...",
"scopes": ["files:read", "crm:read"],
"status": "pending",
"company_url_id": "your-company",
"company_name": "Your Company",
"company_unique_id": "cmp_xyz789"
}
}
}

The resolve endpoint now returns tenant context (added in v4.38.x):

  • company_url_id - URL-safe company identifier
  • company_name - Human-readable company name
  • company_unique_id - Unique company identifier
# Approve the registration
curl -X POST https://auth.api.us.23blocks.com/agent_registrations/:unique_id/approve \
-H "Authorization: Bearer admin-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"role_id": "agent-role-id",
"approved_by_user_id": "admin-user-id"
}'

Other lifecycle actions:

  • POST /agent_registrations/:unique_id/reject — Reject a pending registration
  • POST /agent_registrations/:unique_id/suspend — Suspend an approved agent
  • POST /agent_registrations/:unique_id/reactivate — Reactivate a suspended agent

Step 3 — Agent polls for approval:

curl https://auth.api.us.23blocks.com/agent_registrations/status \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"user_code": "ABCD-EFGH"
}'

Once approved, the response includes JWT tokens:

{
"status": "approved",
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 86400,
"scope": "files:read crm:read",
"token_endpoint": "https://auth.api.us.23blocks.com/your-company/oauth/token"
}

The token_endpoint field (added in v4.38.x) is the OAuth endpoint where the agent can exchange credentials for future tokens.

Pending response returns { "status": "authorization_pending" }. Agent should retry after interval seconds.

Agent OAuth Token Exchange​

Agents authenticate by signing a challenge with their Ed25519 private key:

curl -X POST https://auth.api.us.23blocks.com/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "urn:aid:agent-identity",
"agent_id": "agent_abc123",
"signature": "base64-encoded-ed25519-signature",
"timestamp": "2026-05-19T12:00:00Z"
}'

Response:

{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 86400,
"scope": "files:read files:write crm:read"
}

Token Introspection (RFC 7662)​

Introspect both user and agent tokens:

curl -X POST https://auth.api.us.23blocks.com/oauth/introspect \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"token": "eyJhbGciOiJSUzI1NiIs..."
}'

Response:

{
"active": true,
"sub": "agent_abc123",
"client_id": "your-company",
"scope": "files:read files:write crm:read",
"token_type": "bearer",
"exp": 1716220800,
"iat": 1716134400,
"iss": "https://auth.api.us.23blocks.com/your-company"
}

Service Tokens (M2M)​

Service tokens provide long-lived authentication for machine-to-machine communication. Two categories are available:

CategoryLifetimeUse Case
Agent24 hoursShort-lived agent operations
Service90 daysLong-running service integrations

Endpoints​

EndpointMethodDescription
/companies/:id/service_tokensPOSTCreate a service token
/companies/:id/service_tokensGETList service tokens
/companies/:id/service_tokens/:idGETGet token details
/companies/:id/service_tokens/:idDELETERevoke a token
/companies/:id/service_tokens/:id/regeneratePOSTRegenerate a token

Create Service Token​

curl -X POST https://auth.api.us.23blocks.com/companies/your-company/service_tokens \
-H "Authorization: Bearer your-jwt-token" \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d '{
"service_token": {
"name": "payment-processor",
"category": "service",
"scopes": ["wallet:read", "wallet:write"]
}
}'

Limits: Maximum 100 active service tokens per company. Usage is tracked per token.

OIDC Provider​

The Auth Block acts as a full OpenID Connect provider with discovery, JWKS, and a multi-grant token endpoint. Supports both company-level and app-level OIDC.

Discovery Document​

# Company-level
curl https://auth.api.us.23blocks.com/your-company/.well-known/openid-configuration

# App-level
curl https://auth.api.us.23blocks.com/your-company/apps/your-app/.well-known/openid-configuration

JWKS Endpoint​

curl https://auth.api.us.23blocks.com/your-company/.well-known/jwks.json

Token Endpoint​

The token endpoint supports four grant types:

Grant TypeUse Case
authorization_codeStandard OAuth flow for user login
refresh_tokenRefresh an expired access token
client_credentialsM2M service authentication
urn:aid:agent-identityAI agent authentication with Ed25519
# Client credentials example
curl -X POST https://auth.api.us.23blocks.com/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "your-client-id",
"client_secret": "your-client-secret",
"scope": "read write"
}'

Block Permissions Provisioning​

Internal API for provisioning cross-block permissions using HMAC authentication:

curl -X POST https://auth.api.us.23blocks.com/block_permissions/provision \
-H "Content-Type: application/json" \
-H "X-HMAC-Signature: sha256=..." \
-d '{
"block": "files",
"scopes": ["files:read", "files:write", "files:delete"]
}'

The internal scope registry covers all blocks: Files, Sales, Search, Rewards, Content, CRM, Forms, Wallet, and more.

Data Types​

User​

FieldTypeDescription
unique_idstringUnique identifier
emailstringUser's email address
namestringFull name
confirmedbooleanEmail confirmed status
role_idintegerAssigned role ID
mfa_enabledbooleanMFA status
mfa_channelstringMFA channel: "email", "totp", or null
has_passwordbooleanWhether user has a password set (v4.39+). false for passwordless-only users
providerstringAuthentication provider: "email", "google", "github", etc.

Company​

FieldTypeDescription
unique_idstringUnique identifier
url_idstringURL-safe identifier
namestringCompany name
api_access_keystringAPI key
oidc_issuerstringOpenID Connect issuer URL

Error Handling​

The API uses JSON:API error format:

{
"errors": [
{
"status": "422",
"source": "Authentication Service",
"code": "10001",
"title": "Validation Error",
"detail": "Email is required and must be valid"
}
]
}

Common Error Codes​

StatusCodeDescription
40010001Invalid request format
40110002Invalid authentication
401103Missing or invalid API key
40310003Insufficient permissions
403GW-RC-003reCAPTCHA verification failed
403GW-RC-004reCAPTCHA score too low
40410004Resource not found
42210005Validation failed
422GW-RC-001reCAPTCHA token required
42910006Rate limited

Rate Limiting​

Endpoint TypeLimit
Authentication10 requests/minute/IP
Registration5 requests/5 minutes/IP (with reCAPTCHA)
Token validation60 requests/minute/token
General endpoints1000 requests/hour/API key

Rate limit headers in responses:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1642248000

Security Features​

  • RS256 JWT - Asymmetric encryption with per-company RSA keys
  • JWKS Endpoints - Public key verification for token validation
  • Ed25519 Agent Signatures - Cryptographic agent identity verification
  • Key Rotation - Automated key rotation with graceful transitions
  • 24-hour Token Lifetime - Short-lived access tokens
  • Tenant Isolation - PostgreSQL schema separation per tenant
  • reCAPTCHA Enforcement - Bot protection with per-tenant kill switch
  • Audit Logging - Complete audit trail for security events
  • Anti-enumeration - Passwordless endpoints always return 200

SDK Examples​

TypeScript/JavaScript​

import { create23BlocksClient } from '@23blocks/sdk';

const client = create23BlocksClient({
urls: { authentication: 'https://auth.api.us.23blocks.com' },
apiKey: process.env.BLOCKS_API_KEY,
});

// Check if token is valid
const isValid = await client.auth.validateToken();

// Get current user
const user = await client.auth.getCurrentUser();

// Update user profile
await client.auth.updateProfile({
name: 'Updated Name',
timezone: 'America/New_York'
});

// Enable MFA
const mfaSetup = await client.auth.setupMfa();
// Show QR code to user
console.log(mfaSetup.qrCodeUrl);

// After user scans QR and enters code
await client.auth.enableMfa('123456');

React Hook Example​

import { useAuth } from '@23blocks/react';

function LoginForm() {
const { login, isLoading, error } = useAuth();

const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData(e.target);

await login({
email: formData.get('email'),
password: formData.get('password')
});
};

return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" required />
<input name="password" type="password" required />
<button type="submit" disabled={isLoading}>
{isLoading ? 'Signing in...' : 'Sign In'}
</button>
{error && <p>{error.message}</p>}
</form>
);
}

Use This Block with AI Agents​

This block ships an official Claude Code plugin from the public 23blocks marketplace (19 plugins, 205 skills). Your agent gets full working knowledge of this API — endpoints, identity registration, and conventions.

# one-time: add the 23blocks marketplace
claude plugin marketplace add https://github.com/23blocks-OS/ai-agents

# install this block's plugin
claude plugin install auth-block

Configure BLOCKS_API_URL, BLOCKS_API_KEY, and BLOCKS_AUTH_TOKEN. Register identity first: each block is autonomous — register the user with this block's identity endpoint before private calls (only user_unique_id is required; email/phone are optional notification-routing fields).

Full reference: AI Agents & Claude Code Plugins · github.com/23blocks-OS/ai-agents