Skip to main content
Version: Next

Architecture & Headless UI

Shyntr is headless by design. The broker handles protocol state, token issuance, and trust boundaries, while login, consent, and logout UI remain outside the core service.

Headless Philosophy

Traditional identity products bundle protocol logic and UI together. That usually creates:

  • limited customization
  • inconsistent product UX
  • tighter vendor lock-in
  • harder integration with existing systems

Shyntr separates those responsibilities:

┌─────────────────────────────────────────────────────────────┐
│ Your Application │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Login UI │ │ Consent UI │ │ Logout UI │ │
│ │ (React, │ │ (Your own │ │ (Custom branded │ │
│ │ Next.js, │ │ design) │ │ experience) │ │
│ │ Vue, etc.) │ │ │ │ │ │
│ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │
│ │ │ │ │
│ └────────────────┼─────────────────────┘ │
│ │ │
│ Admin API Calls │
└──────────────────────────┼──────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│ Shyntr │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Authentication Engine │ │
│ │ • Challenge Generation • Token Issuance │ │
│ │ • Session Management • Protocol Translation │ │
│ │ • Security Validation • Multi-Tenancy │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

Network Boundary Enforcement

Shyntr also enforces security at the outbound network layer.

Outbound HTTP requests triggered during identity flows, such as:

  • OIDC discovery
  • JWKS retrieval
  • SAML metadata retrieval
  • webhook delivery

are evaluated through outbound policy controls before the request is executed.

This helps ensure that:

  • identity flows cannot trigger arbitrary outbound requests
  • internal infrastructure is not reachable by default
  • tenant-specific or global policy still governs execution

Outbound requests follow a layered decision model:

  • tenant-specific policy if defined
  • global fallback policy otherwise
  • deny when the destination does not satisfy policy

The Headless Flow

Here is the standard headless authentication pattern.

Step 1: Challenge Generation

When a user needs to authenticate, Shyntr generates a login_challenge and redirects the user to your external login UI.

User → Application → Shyntr → Your Login UI
(with login_challenge)

Step 2: User Verification

Your UI and backend verify the user. You can implement:

  • username and password
  • MFA
  • social login
  • SAML or OIDC federation
  • LDAP-backed authentication
  • custom application-specific authentication
Example: React Login Component
import { useSearchParams } from 'react-router-dom';

function LoginPage() {
const [searchParams] = useSearchParams();
const loginChallenge = searchParams.get('login_challenge');

const handleLogin = async (credentials) => {
const user = await validateUser(credentials);

const response = await fetch('/admin/login/accept', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
login_challenge: loginChallenge,
subject: user.id,
context: {
email: user.email,
name: user.name
}
})
});

const { redirect_to } = await response.json();
window.location.href = redirect_to;
};

return (
<form onSubmit={handleLogin}>
{/* Your custom login form */}
</form>
);
}

Step 3: Accept the Challenge

Your backend calls the Admin API to accept or reject the login or consent challenge.

Accept Login Request
curl -X PUT "http://localhost:7497/admin/login/accept?login_challenge=challenge_abc123" \
-H "Content-Type: application/json" \
-d '{
"subject": "user_12345",
"remember": true,
"remember_for": 3600,
"context": {
"email": "user@example.com",
"name": "John Doe"
}
}'

Step 4: Flow Continuation and Token Issuance

Shyntr validates the protocol state, enforces flow rules, and returns the redirect needed to continue the exchange. For OIDC clients, that results in token issuance once the authorization flow completes.

The consent flow follows the same pattern:

┌──────────────────────────────────────────────────────────────┐
│ Consent Flow │
├──────────────────────────────────────────────────────────────┤
│ │
│ 1. Shyntr redirects to → EXTERNAL_CONSENT_URL │
│ (with consent_challenge parameter) │
│ │
│ 2. Your Consent UI shows: │
│ • requesting application details │
│ • requested scopes │
│ • grant / deny actions │
│ │
│ 3. Your UI or backend calls: │
│ PUT /admin/consent/accept or /admin/consent/reject │
│ │
│ 4. Shyntr continues the authorization flow │
│ │
└──────────────────────────────────────────────────────────────┘

Configuration

Configure your external UI URLs with environment variables:

.env
EXTERNAL_LOGIN_URL=https://auth.yourapp.com/login
EXTERNAL_CONSENT_URL=https://auth.yourapp.com/consent
Production Security

Use HTTPS for external UI URLs in production. Shyntr relies on exact URI validation and strict redirect handling; mismatched public URLs will break flows and weaken your deployment boundary.

Admin API Endpoints

EndpointMethodDescription
/admin/loginGETGet login challenge details
/admin/login/acceptPUTAccept and complete login
/admin/login/rejectPUTReject login
/admin/consentGETGet consent challenge details
/admin/consent/acceptPUTAccept consent
/admin/consent/rejectPUTReject consent
/admin/management/...GET/POST/PUT/DELETEInternal management endpoints used by the Dashboard and automation

Admin API Security Boundary

Shyntr's admin routes are internal control-plane endpoints.

That includes both:

  • headless challenge endpoints such as /admin/login and /admin/consent
  • management endpoints under /admin/management/...

These routes are not protected by built-in application-layer authentication inside Shyntr. In the current codebase they are exposed on the admin server with logging, error handling, and CORS configuration, but without a built-in admin auth layer.

That means:

  • they must be protected at the trusted edge
  • they should sit behind a gateway, reverse proxy, VPN, service mesh, or equivalent policy layer
  • they should only be reachable by trusted internal callers such as your Auth Portal, Dashboard, or operator tooling
  • they must never be exposed directly on a public interface

If you publish the admin port directly to the public internet, you are exposing your control plane.

Required Deployment Rule

Do not expose ADMIN_PORT directly to the public internet. Terminate access at a trusted edge and enforce authentication, authorization, and network policy there.

CORS in the Headless Model

Because your Auth Portal and the Admin API usually run on different origins, browser-based requests need explicit CORS configuration.

You must configure ADMIN_CORS_ALLOWED_ORIGINS to include the exact Auth Portal origin that needs to call the Admin API.

Benefits of Headless Architecture

AspectBenefit
Design FreedomUse your own frontend stack and UI patterns
Brand ConsistencyKeep login, consent, and logout aligned with your product
Protocol SeparationLet Shyntr own protocol state while your app owns UX
Custom Identity SourcesIntegrate LDAP, upstream IdPs, or your own user backend
Operational FlexibilityDeploy UI and broker separately

Next Steps