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)