@auki/authentication
v0.1.0
Published
Auki Network authentication library for JavaScript/TypeScript (Browser & Node.js)
Downloads
3
Readme
@auki/authentication
Auki Network authentication library for JavaScript/TypeScript. Works in both Browser and Node.js environments.
This library provides authentication to the Auki Network's hierarchical authentication system:
- Network Authentication - Authenticate to the Auki API
- Discovery Authentication - Authenticate to the Discovery service
- Domain Access - Get access tokens for specific domains
Installation
npm install @auki/authenticationOr from a local package:
npm install /path/to/auki-authentication-0.1.0.tgzUsage
There are two ways to use this library:
- High-level Client API (recommended) - Async/await API that handles HTTP requests automatically
- Low-level Bindings API - Sans-I/O core for custom HTTP client integration
1. High-Level Client API (Recommended)
The Client class provides a convenient async API that manages HTTP requests internally.
Quick Start
import { Client } from "@auki/authentication";
// Create client with configuration (async for Node.js)
const client = await Client.create({
apiUrl: "https://api.aukiverse.com",
refreshUrl: "https://api.aukiverse.com/user/refresh",
ddsUrl: "https://dds.posemesh.org",
clientId: "my-app",
});
// Set credentials
client.setCredentials({
type: "email",
email: "[email protected]",
password: "secret",
});
// Get domain access - automatically handles full authentication chain!
const domainAccess = await client.getDomainAccess("my-domain-id");
console.log("Connected to:", domainAccess.domain_server.url);
console.log("Access token:", domainAccess.access_token);Alternative: Use the convenience method to create a client with credentials in one step:
const client = await Client.withCredentials(
{ type: "email", email: "[email protected]", password: "secret" },
{
apiUrl: "https://api.aukiverse.com",
refreshUrl: "https://api.aukiverse.com/user/refresh",
ddsUrl: "https://dds.posemesh.org",
clientId: "my-app",
}
);Basic Usage
import { Client } from "@auki/authentication";
// 1. Configure the client
const config = {
apiUrl: "https://api.aukiverse.com",
refreshUrl: "https://api.aukiverse.com/user/refresh",
ddsUrl: "https://dds.posemesh.org",
clientId: "my-app",
refreshThresholdMs: 300000, // Optional: 5 minutes
};
// 2. Create client (async for Node.js)
const client = await Client.create(config);
// 3. Set credentials
const credentials =
// Email/Password
{ type: "email", email: "[email protected]", password: "secret" };
// OR App Key
// { type: 'appKey', appKey: 'your-key', appSecret: 'your-secret' }
// OR Opaque Token
// { type: 'opaque', token: 'your-token', expiryMs: 1234567890 }
client.setCredentials(credentials);
try {
// Get domain access - automatically handles the full chain:
// 1. Network authentication (if needed)
// 2. Discovery authentication (if needed)
// 3. Domain access request
const domainAccess = await client.getDomainAccess("my-domain-id");
console.log("Domain access granted!");
console.log(" Server:", domainAccess.domain_server.name);
console.log(" URL:", domainAccess.domain_server.url);
console.log(" Region:", domainAccess.domain_server.cloud_region);
console.log(" Access Token:", domainAccess.access_token);
} catch (error) {
console.error("Authentication failed:", error.message);
if (error.retryable) {
// This error can be retried
}
}Manual Step-by-Step (Optional)
For advanced use cases where you need explicit control over each step:
// Step 1: Authenticate to network only
const networkToken = await client.authenticate();
console.log("Network token expires at:", networkToken.expires_at);
// Step 2: Authenticate to discovery only
const discoveryToken = await client.authenticateDiscovery();
console.log("Discovery token expires at:", discoveryToken.expires_at);
// Step 3: Get domain access (assumes prior auth)
const domainAccess = await client.getDomainAccess("my-domain-id");Note: In most cases, you only need getDomainAccess() - it automatically handles all prerequisite authentication steps.
State Persistence
Save and restore authentication state (useful for avoiding re-authentication):
// Save state (excludes credentials)
const stateJson = client.saveState();
localStorage.setItem("auth-state", stateJson);
// Restore state later
const savedState = localStorage.getItem("auth-state");
const client = Client.fromState(savedState, config);
// Validate state (clears expired tokens)
client.validateState();
// Check if still authenticated
if (client.isAuthenticated()) {
console.log("Still authenticated!");
} else {
// Need to re-authenticate
await client.authenticate();
}Token Refresh Monitoring
client.onRefreshFailed((info) => {
console.log(`${info.tokenType} token refresh failed:`, info.reason);
if (info.requiresReauth) {
// Token expired, need full re-authentication
client.authenticate().catch(console.error);
}
});Checking Tokens
// Check authentication state
const isAuth = client.isAuthenticated();
// Get cached tokens
const networkToken = client.getNetworkToken();
if (networkToken) {
console.log("Token:", networkToken.token);
console.log("Expires:", networkToken.expires_at);
}
const discoveryToken = client.getDiscoveryToken();
const domainAccess = client.getCachedDomainAccess("domain-id");Utility Functions
import { currentTimeMs, isExpired, isNearExpiry } from "@auki/authentication";
// Get current time
const now = currentTimeMs();
// Check if token is expired
if (isExpired(token.expires_at)) {
console.log("Token expired");
}
// Check if token needs refresh
if (isNearExpiry(token.expires_at, 300000)) {
// 5 minutes
console.log("Token expires soon");
}2. Low-Level Bindings API (Advanced)
For advanced use cases where you need full control over HTTP requests, you can use the underlying WASM bindings directly. This is a sans-I/O API where you handle all I/O operations.
Import Raw Bindings
import {
WasmClient,
WasmConfig,
WasmCredentials,
} from "@auki/authentication/dist/bindings/authentication.js";Sans-I/O Pattern
import {
WasmClient,
WasmConfig,
WasmCredentials,
} from "@auki/authentication/dist/bindings/authentication.js";
// 1. Create credentials
const credentials = WasmCredentials.email_password(
"[email protected]",
"password"
);
// 2. Create config
const config = new WasmConfig(
"https://api.aukiverse.com",
"https://dds.posemesh.org",
"my-client-id"
);
config.refresh_threshold_ms = BigInt(300000); // 5 minutes
// 3. Create client
const client = new WasmClient(credentials, config);
// 4. Get actions to perform
const actions = client.authenticate(BigInt(Date.now()));
// 5. Execute actions (you handle HTTP)
for (const action of actions) {
if (action.type === "HttpRequest") {
// Use your own HTTP client
const response = await yourHttpClient.request({
url: action.url,
method: action.method,
headers: action.headers,
body: action.body,
});
// 6. Feed response back to client
const events = client.handle_response(response.status, response.text);
// 7. Process events
for (const event of events) {
if (event.type === "NetworkAuthSuccess") {
console.log("Token:", event.token);
console.log("Expires:", event.expires_at);
} else if (event.type === "NetworkAuthFailed") {
console.error("Failed:", event.reason);
}
}
} else if (action.type === "Wait") {
// Handle retry delays
await new Promise((r) => setTimeout(r, action.duration_ms));
}
}Available Methods
// Authentication flow
client.authenticate(now_ms: bigint): Action[]
client.authenticate_discovery(now_ms: bigint): Action[]
client.get_domain_access(domain_id: string, now_ms: bigint): Action[]
// Handle HTTP responses
client.handle_response(status: number, body: string): Event[]
// State queries
client.is_authenticated(now_ms: bigint): boolean
client.check_auth_state(now_ms: bigint): WasmAuthenticationState
client.network_token(): Token | null
client.discovery_token(): Token | null
client.domain_access(domain_id: string): DomainAccess | null
client.all_domains(): DomainAccess[]
// State management
client.save_state(): string
client.validate_state(now_ms: bigint): Event[]
WasmClient.from_state(state_json: string, config: WasmConfig): WasmClient
// Credentials
client.set_credentials(credentials: WasmCredentials): void
client.has_credentials(): boolean
client.requires_credentials(now_ms: bigint): boolean
// Control
client.force_reauth(): Event[]
client.clear_domain_access(domain_id: string): void
client.clear_all_domain_accesses(): voidAction Types
type Action =
| {
type: "HttpRequest";
url: string;
method: string;
headers: object;
body?: string;
}
| { type: "Wait"; duration_ms: number };Event Types
type Event =
| { type: "NetworkAuthSuccess"; token: string; expires_at: number }
| { type: "NetworkAuthFailed"; reason: string; retry_possible: boolean }
| { type: "NetworkTokenRefreshed"; token: string; expires_at: number }
| {
type: "NetworkTokenRefreshFailed";
reason: string;
requires_reauth: boolean;
}
| { type: "DiscoveryAuthSuccess"; token: string; expires_at: number }
| { type: "DiscoveryAuthFailed"; reason: string }
| { type: "DomainAccessGranted"; domain: DomainAccess }
| { type: "DomainAccessDenied"; domain_id: string; reason: string }
| { type: "AuthenticationRequired" }
| { type: "TokensInvalidated" };TypeScript Support
This library is written in TypeScript and includes full type definitions.
import type {
Client,
ClientConfig,
Credentials,
Token,
DomainAccess,
DomainServer,
AuthenticationError,
RefreshFailureInfo,
} from "@auki/authentication";Examples
See the examples/ directory for complete working examples:
- basic.js - Complete authentication flow with all steps
- test_refresh.js - Token refresh testing
- test_refresh_expired.js - Expired token handling
Running Examples
Copy environment template:
cp ../../.env.example ../../.envEdit
.envwith your credentials:API_URL=https://api.aukiverse.com DDS_URL=https://dds.posemesh.org [email protected] PASSWORD=your-password DOMAIN_ID=your-domain-idRun example:
npm run example:basic
Error Handling
import { AuthenticationError } from "@auki/authentication";
try {
await client.authenticate();
} catch (error) {
if (error instanceof AuthenticationError) {
console.error("Auth error:", error.message);
console.log("Retryable:", error.retryable);
}
}Browser vs Node.js
This library works in both environments:
Browser:
<script type="module">
import { Client } from "@auki/authentication";
// Use client...
</script>Node.js:
import { Client } from "@auki/authentication";
// or
const { Client } = require("@auki/authentication");Architecture
This library uses a sans-I/O architecture at its core:
- The Rust core implements all authentication logic without I/O
- The TypeScript wrapper provides a convenient async API
- HTTP requests use the standard
fetchAPI (works in browsers and Node.js 18+) - You can use the low-level bindings for custom HTTP client integration
Building from Source
# From repository root
make javascript
# Package it
cd pkg/javascript && npm packSee the root README.md for more details.
License
MIT
Support
- Issues: https://github.com/aukilabs/experimental-modules/issues
- Documentation: https://github.com/aukilabs/experimental-modules
