Multi-Client OIDC Authentication
Overview
Waldur Mastermind supports authentication from multiple client applications to a single backend. This feature allows different client domains to authenticate users via OIDC while ensuring users are redirected back to the correct client application after authentication.
How It Works
Authentication Flow
- User initiates login: User clicks "Sign in with OIDC" on a client application (e.g.,
https://app1.example.com) - Return URL stored: Mastermind stores either:
- The
return_urlquery parameter (if provided), OR - The HTTP Referer header (fallback)
- OIDC redirect: User is redirected to the OIDC provider for authentication
- OIDC callback: After authentication, OIDC provider redirects to Mastermind's callback URL
- Validation: Mastermind validates the stored return URL against the allowed redirects list
- User redirect: User is redirected back to the original client application with authentication token
Security
- Whitelist validation: Only pre-configured client domains are allowed
- Open redirect prevention: Referrer URLs are validated against the allowed list
- Base URL matching: Referrer validation uses only scheme and domain (path is ignored)
Validation Rules
The allowed_redirects field enforces strict security rules to prevent open redirect attacks and ensure proper authentication flow:
URL Format Requirements
- Origin-only URLs: Only scheme + domain + port allowed (no paths, query parameters, or fragments)
- Valid:
https://homeport.example.com - Invalid:
https://homeport.example.com/path,https://homeport.example.com?query=value - No trailing slashes: URLs must not end with
/ - Valid:
https://homeport.example.com - Invalid:
https://homeport.example.com/ - Exact matching: URLs are validated exactly as configured (no pattern matching or wildcards)
Security Requirements
- HTTPS-only: All URLs must use
https://scheme (exceptions: localhost and 127.0.0.1) - Valid:
https://homeport.example.com,http://localhost:8080,http://127.0.0.1:8000 - Invalid:
http://homeport.example.com,ftp://example.com - No wildcards: Domain patterns like
*.example.comare not supported - Complete URLs required: Each Homeport instance must be explicitly listed
Validation Examples
Valid configurations:
1 2 3 4 5 6 7 8 | |
Invalid configurations:
1 2 3 4 5 6 7 8 9 | |
Configuration
Identity Provider Setup
Configure the allowed_redirects field for each Identity Provider via the API:
1 2 3 4 5 6 7 8 9 10 11 12 | |
OIDC Provider Configuration
Important: All Homeport instances use the same callback URL on Mastermind:
1 | |
Register this single callback URL with your OIDC provider. No per-Homeport callback registration is required.
Homeport Integration
Note: This section provides API-level documentation for the backend feature. For complete frontend integration guide with code examples, see the Homeport repository documentation.
Homeport frontends can specify the return URL in two ways:
Method 1: Explicit return_url Parameter (Recommended)
Pass the return URL as a query parameter when redirecting to the OIDC init endpoint:
1 2 3 4 5 6 7 | |
Benefits: - More explicit and reliable - Works regardless of browser referrer policy - Easier to debug and test
Method 2: HTTP Referer Header (Automatic Fallback)
If no return_url is provided, Mastermind automatically uses the HTTP Referer header:
1 2 3 4 5 6 | |
Note: Ensure your Homeport has an appropriate referrer policy:
1 2 | |
Or in JavaScript:
1 2 3 4 | |
Priority
When both are available, return_url takes priority over the HTTP Referer header.
API Endpoints
Create/Update Identity Provider
Endpoint: POST /api/identity-providers/ or PATCH /api/identity-providers/{provider}/
Request Body:
1 2 3 4 5 6 7 8 9 10 11 | |
Field Validation:
- allowed_redirects must be a list of valid URLs
- Each URL must include scheme (http:// or https://) and domain
- URLs are normalized (trailing slashes are handled automatically)
Get Identity Providers
Endpoint: GET /api/identity-providers/
Response:
1 2 3 4 5 6 7 8 9 10 11 12 | |
Behavior
With allowed_redirects Configured
- Matching referrer: User is redirected to the Homeport that initiated the request
- No referrer: User is redirected to the first URL in
allowed_redirects - Invalid referrer: Authentication fails with 401 error (referrer not in allowed list)
Without allowed_redirects (Backward Compatibility)
If allowed_redirects is empty or not set, the system falls back to the HOMEPORT_URL constance setting:
1 2 3 4 | |
This maintains backward compatibility with existing single-Homeport deployments.
Migration Guide
Upgrading from Single Homeport
-
Run migrations:
1python manage.py migrate waldur_auth_social -
Update Identity Provider via API:
1 2 3 4 5 6
curl -X PATCH https://api.waldur.example.com/api/identity-providers/keycloak/ \ -H "Authorization: Token YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "allowed_redirects": ["https://homeport1.example.com"] }' -
Add additional Homeports as needed:
1 2 3 4 5 6 7 8 9
curl -X PATCH https://api.waldur.example.com/api/identity-providers/keycloak/ \ -H "Authorization: Token YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "allowed_redirects": [ "https://homeport1.example.com", "https://homeport2.example.com" ] }'
Adding a New Homeport
- Configure your new Homeport to use the same Mastermind API URL
- Add the new Homeport URL to
allowed_redirects:1 2 3 4 5 6
{ "allowed_redirects": [ "https://existing-homeport.com", "https://new-homeport.com" ] } - No OIDC provider reconfiguration needed (callback URL remains the same)
Examples
Example 1: University with Multiple Portals
1 2 3 4 5 6 7 8 | |
Example 2: Multi-Tenant SaaS
1 2 3 4 5 6 7 8 | |
Example 3: Development and Production
1 2 3 4 5 6 7 8 | |
Troubleshooting
Error: "Return URL domain is not in the allowed redirects list"
Cause: The Homeport URL that initiated the authentication is not in the allowed_redirects list, or the URL format is invalid.
Solution: Add the Homeport URL to the Identity Provider's allowed_redirects with correct format:
1 2 3 4 5 6 7 | |
Important: Ensure URLs are normalized:
- Use https://homeport.com not https://homeport.com/
- Use HTTPS except for localhost/127.0.0.1
- Include only origin (no paths or query parameters)
Users redirected to wrong Homeport
Cause: Referrer header not being sent by the browser.
Solutions:
1. Ensure Homeport is setting proper referrer policy
2. Check that the login link properly navigates to the Mastermind OIDC init URL
3. If referrer is unavailable, users will be redirected to the first URL in allowed_redirects
Backward compatibility issues
Cause: Existing deployment not configured with allowed_redirects.
Solution: The system automatically falls back to HOMEPORT_URL constance setting when allowed_redirects is empty. No action required unless you want to enable multi-Homeport support.
Technical Details
Database Schema
1 2 3 4 5 6 7 8 9 10 11 12 | |
Session Storage
During authentication, the following session keys are used:
- oidc_state: CSRF protection token
- oidc_code_verifier: PKCE code verifier (if PKCE enabled)
- oidc_referrer: HTTP Referer header from the init request
URL Normalization
Referrer URLs are normalized for comparison:
- Scheme and domain are extracted (e.g., https://homeport.com/login → https://homeport.com)
- Trailing slashes are handled consistently
- Path, query, and fragment components are ignored for validation
API Reference
IdentityProvider Model Fields
| Field | Type | Description |
|---|---|---|
provider |
String | Provider identifier (tara, keycloak, eduteams) |
allowed_redirects |
JSON Array | List of allowed redirect URLs (origin-only, no trailing slashes) |
client_id |
String | OIDC client ID |
client_secret |
String | OIDC client secret |
discovery_url |
String | OIDC discovery endpoint |
is_active |
Boolean | Whether provider is enabled |
Field Validation Rules
The allowed_redirects field enforces strict validation:
- Format: Must be a JSON array of strings
- URL structure: Each entry must be origin-only (scheme + domain + optional port)
- HTTPS requirement: Must use
https://(excepthttp://localhostorhttp://127.0.0.1) - No trailing slashes: URLs must not end with
/ - No paths/query/fragments: Only the origin part is allowed
- Exact matching: No wildcard or pattern matching support
- Empty arrays: Valid (falls back to
HOMEPORT_URLsetting)
OIDC Claim Discovery and Mapping Wizard
Waldur provides API endpoints to help administrators discover available OIDC claims from identity providers and generate appropriate attribute mappings.
Discover OIDC Metadata
Fetch the OIDC discovery document and get suggested claim mappings for Waldur user fields.
Endpoint: POST /api/identity-providers/discover_metadata/
Permissions: Staff only
Request:
1 2 3 4 | |
Response:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Response Fields:
| Field | Description |
|---|---|
claims_supported |
Claims the OIDC provider can return (from discovery document) |
scopes_supported |
Scopes the OIDC provider supports |
endpoints |
OIDC endpoints extracted from discovery document |
waldur_fields |
Waldur User model fields with suggested OIDC claim mappings |
waldur_fields[].field |
Waldur User model field name |
waldur_fields[].description |
Human-readable field description |
waldur_fields[].suggested_claims |
Ordered list of OIDC claims that could map to this field |
waldur_fields[].available_claims |
Claims from this IdP that match the suggestions |
suggested_scopes |
Recommended scopes to request based on available claims |
Generate Default Mapping
Generate a ready-to-use attribute_mapping configuration based on IdP's supported claims.
Endpoint: POST /api/identity-providers/generate-mapping/
Permissions: Staff only
Request:
1 2 3 4 | |
Response:
1 2 3 4 5 6 7 8 9 10 | |
The generated mapping can be used directly when creating or updating an identity provider.
Wizard Workflow
- Discover: Call
discover_metadatawith the IdP's discovery URL - Review: Examine available claims and suggested mappings
- Generate: Call
generate-mappingto get a ready-to-use configuration - Customize: Modify the generated mapping if needed
- Create: Use the mapping when creating the identity provider
Example: Setting Up a New Identity Provider
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | |
Claim Mapping Priority
When generating suggestions, claims are prioritized in this order:
- Existing provider defaults: Claims from Waldur's built-in provider configurations (TARA, eduTEAMS, Keycloak)
- Standard OIDC claims: Common OIDC claim names (e.g.,
given_name,email) - SCHAC/eduPerson claims: Research and education federation attributes
This ensures generated mappings are compatible with known working configurations.
Supported Waldur User Fields
The following user fields can be mapped from OIDC claims:
| Field | Common OIDC Claims | Description |
|---|---|---|
first_name |
given_name |
User's first/given name |
last_name |
family_name |
User's last/family name |
email |
email, mail |
User's email address |
organization |
schac_home_organization, org |
Organization name |
affiliations |
voperson_external_affiliation |
Organizational affiliations |
civil_number |
sub, schacPersonalUniqueID |
National identity number |
phone_number |
phone_number |
Phone number |
birth_date |
birthdate |
Date of birth |
gender |
gender |
Gender (ISO 5218) |
nationality |
schacCountryOfCitizenship |
Citizenship country code |
eduperson_assurance |
eduperson_assurance |
Identity assurance level |
For a complete list, see User Profile Attributes.
Notes on claims_supported
The claims_supported field in OIDC discovery is optional per the specification. If an IdP does not provide this field:
claims_supportedwill be an empty array in the responseavailable_claimsfor each Waldur field will also be empty- You can still manually configure
attribute_mappingbased on IdP documentation
In such cases, consider performing a test authentication to discover actual claims returned by the IdP's userinfo endpoint.