Home Realm Discovery (HRD)
Home Realm Discovery enables automatic routing of users to their organization’s identity provider based on their email domain.
Overview
When a user enters their email address, HRD checks if the email domain is associated with a configured upstream identity provider. If a match is found, the user is redirected to their organization’s SSO provider instead of seeing the password login form.
sequenceDiagram
participant User
participant Client
participant AuthOS
participant IdP
User->>Client: Enter email
Client->>AuthOS: POST /api/auth/lookup-email
AuthOS-->>Client: {redirect_to: "github", org: "acme"}
Client->>AuthOS: GET /auth/github?org=acme&service=app
AuthOS-->>IdP: Redirect to IdP
IdP-->>AuthOS: OAuth callback
AuthOS-->>Client: Tokens
Endpoints
POST /api/auth/lookup-email
Look up email domain to determine authentication method.
Synopsis
| Property | Value |
|---|---|
| Authentication | Public |
| Rate Limit | 10 requests/minute per IP |
| Idempotent | Yes |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email |
string |
Yes | User’s email address |
org_slug |
string |
Yes | Organization slug |
service_slug |
string |
Yes | Service slug |
Example Request
curl -X POST https://sso.example.com/api/auth/lookup-email \
-H "Content-Type: application/json" \
-d '{
"email": "user@acme.com",
"org_slug": "acme-corp",
"service_slug": "main-app"
}'
Response - SSO Redirect Required (200 OK)
{
"method": "redirect",
"provider": "github",
"redirect_url": "/auth/github?org=acme-corp&service=main-app"
}
Response - Password Login (200 OK)
{
"method": "password"
}
Response Fields
| Field | Type | Description |
|---|---|---|
method |
string |
"redirect" or "password" |
provider |
string |
OAuth provider name (when method is redirect) |
redirect_url |
string |
URL to redirect user to (when method is redirect) |
Errors
| Status | Code | Condition |
|---|---|---|
400 |
BAD_REQUEST |
Invalid email format |
404 |
NOT_FOUND |
Organization or service not found |
Configuring HRD
Step 1: Verify Domain Ownership
Before enabling HRD for a domain, you must verify ownership:
curl -X POST https://sso.example.com/api/organizations/acme-corp/domains \
-H "Authorization: Bearer {jwt}" \
-H "Content-Type: application/json" \
-d '{
"domain": "acme.com"
}'
Response:
{
"domain": "acme.com",
"verification_token": "authos-verify=abc123def456",
"verified": false
}
Add the verification token as a TXT record:
_authos-verify.acme.com TXT "authos-verify=abc123def456"
Step 2: Verify the Domain
curl -X POST https://sso.example.com/api/organizations/acme-corp/domains/acme.com/verify \
-H "Authorization: Bearer {jwt}"
Step 3: Configure Upstream Provider
curl -X POST https://sso.example.com/api/organizations/acme-corp/upstream-providers \
-H "Authorization: Bearer {jwt}" \
-H "Content-Type: application/json" \
-d '{
"provider": "saml",
"name": "Okta SSO",
"domains": ["acme.com"],
"config": {
"idp_metadata_url": "https://acme.okta.com/app/.../sso/saml/metadata",
"sp_entity_id": "https://sso.example.com/saml/acme-corp"
}
}'
Supported Providers
| Provider | Type | Configuration |
|---|---|---|
| GitHub | OAuth 2.0 | Client ID, Client Secret |
| OAuth 2.0 | Client ID, Client Secret | |
| Microsoft | OAuth 2.0 | Client ID, Client Secret, Tenant ID |
| SAML | SAML 2.0 | IDP Metadata URL or manual config |
SSO Enforcement
When HRD is configured for a domain, you can optionally enforce SSO:
curl -X PATCH https://sso.example.com/api/organizations/acme-corp/upstream-providers/{id} \
-H "Authorization: Bearer {jwt}" \
-H "Content-Type: application/json" \
-d '{
"enforce_sso": true
}'
With enforcement enabled:
- Users with matching email domains must authenticate via SSO
- Password login is disabled for these users
- Password reset is disabled for these users
Client Integration
React Example
import { useState } from 'react';
function LoginForm() {
const [email, setEmail] = useState('');
const [showPassword, setShowPassword] = useState(false);
async function handleEmailSubmit(e) {
e.preventDefault();
const response = await fetch('/api/auth/lookup-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email,
org_slug: 'acme-corp',
service_slug: 'main-app'
})
});
const result = await response.json();
if (result.method === 'redirect') {
// Redirect to SSO provider
window.location.href = result.redirect_url;
} else {
// Show password field
setShowPassword(true);
}
}
return (
<form onSubmit={handleEmailSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
/>
{showPassword && (
<input type="password" placeholder="Password" />
)}
<button type="submit">
{showPassword ? 'Sign In' : 'Continue'}
</button>
</form>
);
}
Security Considerations
- Domain Verification Required - HRD only routes verified domains
- No Email Enumeration - Always returns a response regardless of user existence
- Rate Limited - Prevents domain probing attacks
- HTTPS Required - All HRD endpoints require HTTPS