← Live API Status

OIDC Enterprise Evaluation Guide

Confidential

What You're Evaluating

STEADYWATCH™ OIDC is a biometric-backed Identity Provider implementing RFC 8628 (Device Authorization Grant) — a direct replacement for Cisco DUO and similar push-based MFA systems. Authentication is initiated from any browser, delivered as a push notification to the user's iPhone, and completed via Face ID. No passwords, no TOTP codes, no hardware tokens.

Every authentication event produces a signed JWT with biometric attestation claims (sw_biometric_factor, sw_prime, sw_confidence) that your application can inspect.

No Installation Required

This evaluation connects to a live, hosted instance. No IBM Quantum account, no Docker setup, no iOS app required to test the protocol. You need only:

Check API status before proceeding:
infin-8.github.io/STEADYWATCH-QUANTUM-DEMO/status.html
The status page shows real-time connectivity and the current API base URL. Copy it before running the commands below.

API Base URL

https://<current-tunnel-url>.trycloudflare.com

Get the current URL from the status page. Set it as a shell variable for convenience:

export SW_API="https://<current-tunnel-url>.trycloudflare.com"

Protocol Overview

SteadyWatch OIDC implements the OAuth 2.0 Device Authorization Grant (RFC 8628). The flow:

1. Your app   → POST /oauth2/device/authorize        (request auth)
              ← { device_code, user_code, verification_uri }

2. Your app   → show user_code to user OR auto-approve via biometric push

3. iPhone     ← push notification arrives → Face ID fires → approved

4. Your app   → POST /oauth2/token (polling)
              ← { access_token, id_token } (JWT)

This is identical to how Google, GitHub, and Apple TV implement device login — except the approval step is biometric, not a browser click.

Quickstart

1. Discovery Document

Verify the IdP is live and inspect its capabilities:

curl "$SW_API/.well-known/openid-configuration"

Expected response:

{
  "issuer": "https://<tunnel-url>.trycloudflare.com",
  "token_endpoint": ".../oauth2/token",
  "jwks_uri": ".../oauth2/jwks",
  "device_authorization_endpoint": ".../oauth2/device/authorize",
  "grant_types_supported": ["urn:ietf:params:oauth:grant-type:device_code"],
  "id_token_signing_alg_values_supported": ["RS256"]
}

2. Request a Device Code

curl -X POST "$SW_API/oauth2/device/authorize" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=steadywatch-demo&scope=openid profile"

Expected response:

{
  "device_code": "sw_dev_abc123...",
  "user_code": "XKCD-7291",
  "verification_uri": "https://<tunnel>/oauth2/device/approve",
  "expires_in": 300,
  "interval": 5
}

Copy the device_code — you'll need it for token polling.

3. Approve (Simulated — No iPhone Required)

For evaluation without the iOS app, approve directly via the API:

curl -X POST "$SW_API/oauth2/device/approve" \
  -H "Content-Type: application/json" \
  -d '{"user_code": "XKCD-7291", "approved": true}'

In production, this step happens silently on the user's iPhone after Face ID passes.

4. Poll for the Token

curl -X POST "$SW_API/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=sw_dev_abc123...&client_id=steadywatch-demo"

Before approval: returns authorization_pending — poll every 5 seconds.

After approval:

{
  "access_token": "eyJ...",
  "id_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "openid profile"
}

5. Inspect the ID Token

The id_token is a signed JWT. Decode the payload (middle segment, base64):

# Quick decode (no verification)
echo "eyJ..." | cut -d. -f2 | base64 -d 2>/dev/null | python3 -m json.tool

Expected claims:

{
  "iss": "https://<tunnel-url>.trycloudflare.com",
  "sub": "user_<device_id>",
  "aud": "steadywatch-demo",
  "exp": 1234567890,
  "iat": 1234567890,
  "sw_biometric_factor": "face_id",
  "sw_prime": 5,
  "sw_confidence": 0.97,
  "sw_session_id": "sw_sess_..."
}

Custom claims:

ClaimMeaning
sw_biometric_factorBiometric method used (face_id)
sw_primeEntropy prime used in key derivation (5, 13, or 17)
sw_confidenceFace ID match confidence score (0–1)
sw_session_idUnique per-authentication session ID

6. Verify the Token Signature

Fetch the public key and verify the JWT signature:

curl "$SW_API/oauth2/jwks"

Returns a standard JWKS document. Use any RFC 7517-compliant JWT library to verify:

import jwt, requests

jwks = requests.get(f"{SW_API}/oauth2/jwks").json()
# jwt.decode(id_token, jwks, algorithms=["RS256"], audience="steadywatch-demo")

Interactive Demo

A browser-based demo showing the full device authorization flow is available at:
infin-8.github.io/STEADYWATCH-QUANTUM-DEMO/oidc.html

STEADYWATCH™ OIDC vs Cisco DUO

FeatureSTEADYWATCH™ OIDCCisco DUO
ProtocolRFC 8628 (standard OIDC)Proprietary
Approval mechanismFace ID (biometric)Push tap (no biometric)
Token formatStandard JWTProprietary session
Custom attestation claimsYesNo
Self-hostableYes (Raspberry Pi to cloud)No
Vendor lock-inNone — standard OIDCHigh
Per-device key derivationYes (quantum-seeded)No

Architecture Overview

Browser / App
    ↓ POST /oauth2/device/authorize
Flask OIDC Provider (RFC 8628)
    ↓ APNs push notification
iPhone (STEADYWATCH™ HANDHELD)
    ↓ Face ID biometric verification
    ↓ Quantum key derivation (VAULT entropy + SE key)
Flask OIDC Provider
    ↓ Issues signed JWT with biometric claims
Browser / App
    ← access_token + id_token

Key properties:

Integration

Point your application's OIDC discovery URL to:

https://<tunnel-url>.trycloudflare.com/.well-known/openid-configuration

Compatible with Auth0, Okta (as external IdP), Keycloak, and any custom OAuth2 middleware.

Production deployments include client credentials, tenant isolation with per-tenant JWKS, rate limiting, audit logging, and custom claim mapping.

For integration support or production access: nathaniel.a.vazquez@gmail.com