Get Started with ORGNET

Real working examples — from a single protected page to full cross-domain SSO and AI agent auth.

1. Protect a page 2. Read user identity 3. Cross-domain SSO 4. PHP server-side 5. AI agent auth

Example 1 — Protect a Web Page

Add the OrgNet SDK and protect any page with two lines of configuration. If the user isn't authenticated, they're redirected to your OrgNet login page and returned after sign-in.

Browser / HTML

Works in any HTML page — no framework required.

JavaScript
<!-- 1. Add the OrgNet SDK to your <head> -->
<!-- SDK URL available after registering your app in the dashboard -->
<script src="https://cdn.orgnet.app/v1/orgnet.min.js"></script>

<script>
  // 2. Initialise with your client ID from the OrgNet dashboard
  const orgnet = new OrgNetClient({
    clientId:    "your_client_id",
    redirectUri: "https://yourapp.com/callback"
  });

  // 3. Protect the page — redirects to OrgNet login if not authenticated.
  // Returns silently if already authenticated.
  orgnet.protectPage();
</script>
How it works: protectPage() checks for a valid Access Token silently via the OrgNet SSO bridge. If no token exists, it initiates the OAuth 2.1 Authorization Code + PKCE flow. The user logs in on auth.orgnet.app and is returned to your redirectUri with a code, which the SDK exchanges for tokens automatically.

Example 2 — Read the Authenticated User's Identity

On a protected page, read the full user object. OrgNet's JWT carries both the person's identity and their active org context — no extra API call needed for most cases.

Get User + Org Context

The user object reflects the active org identity — including emp_id, roles, and permissions.

JavaScript
(async () => {

  if (await orgnet.isAuthenticated()) {

    const user = await orgnet.getUser();

    // The full user object from the OrgNet JWT:
    // {
    //   sub:          "per_01HXABC123",     // OrgNet person ID (stable)
    //   email:        "alice@acme.com",      // Login email
    //   emp_id:       "E001",                // Employee ID from your system
    //   org_id:       "org_01HXACME",        // Active organisation
    //   org_name:     "Acme Corp",            // Display name
    //   roles:        ["Editor"],            // Active roles for this app
    //   perms:        ["doc:read","doc:write"], // Resolved permissions
    //   identity_count: 2                    // Total orgs this person belongs to
    // }

    document.getElementById("username").textContent = user.email;
    document.getElementById("org-name").textContent  = user.org_name;

    // Check a permission before showing a UI element
    if (user.perms.includes("doc:write")) {
      document.getElementById("edit-btn").style.display = "block";
    }

  }
})();

Example 3 — Cross-Domain SSO

Users who are logged in on any of your registered domains are automatically authenticated on every other domain — no login prompt. The SDK handles the token bridge silently.

Silent SSO Token Derivation

app2.com gets a valid token from a session started on app1.com — zero user friction.

JavaScript
// On app2.com — user logged in on app1.com, no login prompt shown

const orgnet = new OrgNetClient({
  clientId:    "app2_client_id",
  redirectUri: "https://app2.com/callback"
});

// getAccessToken() calls POST /token/derive on auth.orgnet.app
// via a secure hidden iframe — the Master Session Token (MST)
// in the HttpOnly cookie on auth.orgnet.app is used to issue a
// fresh, app-scoped Access Token. The user sees nothing.
const token = await orgnet.getAccessToken();

// Use the token on your API calls
const res = await fetch("https://api.app2.com/data", {
  headers: { "Authorization": `Bearer ${token}` }
});

// Listen for auth state changes (e.g. logout on another domain)
orgnet.onAuthStateChange((event) => {
  if (event === "SIGNED_OUT") window.location.href = "/logged-out";
});

Example 4 — PHP Server-Side Token Validation

Validate OrgNet JWTs on your PHP/Laravel backend before processing any API request. The Composer package handles signature verification, expiry checking, and revocation lookup.

Laravel Middleware

Install via Composer, add one middleware class, and protect any route.

PHP / Laravel
# Install the OrgNet PHP SDK
composer require orgnet/php-sdk

# Add to config/orgnet.php
'jwks_uri'  => 'https://auth.orgnet.app/.well-known/jwks.json',
'issuer'    => 'https://auth.orgnet.app',
'audience'  => 'https://yourapp.com',

Protect a Route

OrgNetMiddleware validates the Bearer token, checks revocation, and injects the user into the request.

PHP / Laravel
// routes/api.php
Route::middleware(['orgnet.auth'])->group(function () {

    Route::get('/documents', function (Request $request) {

        // OrgNetUser is injected — all claims from the JWT
        $user = $request->orgnet_user;

        // $user->sub       — OrgNet person ID
        // $user->emp_id    — Employee ID from your system
        // $user->org_id    — Active organisation
        // $user->roles     — Array of active roles
        // $user->perms     — Array of resolved permissions

        // Check permission before proceeding
        if (!$user->hasPermission('doc:read')) {
            return response()->json(['error' => 'Forbidden'], 403);
        }

        // Scope data to the user's active org
        return Document::where('org_id', $user->org_id)->get();

    });
});

Example 5 — AI Agent Authentication (OpenClaw)

AI agents are not users. They authenticate via the OAuth 2.1 Client Credentials grant — no browser, no redirect, no user involved. Tokens are short-lived and scope-locked.

Client Credentials — Agent Boot Sequence

Load credentials from your secrets vault, authenticate, and use the token on every API call.

JavaScript / Node
// 1. Load credentials from your secrets vault — never hardcode
const CLIENT_ID     = process.env.ORGNET_AGENT_CLIENT_ID;
const CLIENT_SECRET = process.env.ORGNET_AGENT_CLIENT_SECRET;

async function getAgentToken() {
  const res = await fetch("https://auth.orgnet.app/oauth/token", {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      grant_type:    "client_credentials",
      client_id:     CLIENT_ID,
      client_secret: CLIENT_SECRET,
      scope:         "openclaw:task:execute openclaw:memory:read"
      // ↑ Request only the scopes your agent actually needs
    })
  });

  const { access_token, expires_in } = await res.json();

  // Token claims include: orgnet:type="agent", orgnet:org_id,
  // orgnet:agent_id, orgnet:scopes, exp (15 min from now)

  return { access_token, expires_at: Date.now() + (expires_in - 60) * 1000 };
  // ↑ Store expires_at 60s early to rotate proactively
}

// 2. Use the token — re-authenticate when close to expiry
let tokenCache = null;

async function callApi(endpoint, body) {
  if (!tokenCache || Date.now() > tokenCache.expires_at) {
    tokenCache = await getAgentToken(); // Re-authenticate
  }
  return fetch(endpoint, {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${tokenCache.access_token}`,
      "Content-Type":  "application/json"
    },
    body: JSON.stringify(body)
  });
}
Security note: Agent tokens have a 15-minute TTL and no refresh tokens. Re-authenticating via Client Credentials on expiry is the correct pattern — it limits the blast radius of any token being stolen. Never log or store the raw access_token value.

What's Next?

📖 Full Documentation

JWT claim reference, RBAC model, token lifecycle, and the complete REST API.

🛡️ RBAC & Permissions

Assign roles, define permissions, and enforce them in your app with one method call.

🌐 SSO Architecture

How the Master Session Token and /token/derive endpoint power cross-domain SSO.

🤖 Agent Security Deep Dive

Rate limiting, replay prevention, audit logs, and service account management.