# Okta + Relyra
> Tested against: Okta SAML app UI, April 2026
This is the authoritative Day-1 runbook for the Okta preset. Start here only
after the local `FakeIdP` proof in [Getting Started](../getting_started.md) is
green.
## Tested against
- Okta SAML 2.0 app integration flow
- `Relyra.Provider.Okta`
- `Relyra.Provider.apply_defaults(:okta, ...)`
## Relyra owns
- Strict SP-initiated defaults for the Okta preset
- Signed assertion and signed response requirements
- Safe default `Name ID format` and SHA-256 algorithm policy
- Operator-facing footgun checks for SHA-1 signing and unnecessary
IdP-initiated flows
## IdP owns
- The Okta application integration
- The exact `Audience URI (SP Entity ID)` and `Single sign-on URL` values
- The active signing certificate exported from the Okta admin surface
- Claim mapping and any org-specific access policy around the app
## Host owns
- Phoenix router wiring, session behavior, and downstream authorization
- The app's canonical ACS URL and service-provider entity ID
- Secret management, deployment, and domain ownership
## 1. Create the SAML app in Okta
In Okta, create a new **SAML 2.0** app integration and populate the vendor
fields Relyra expects:
- **Audience URI (SP Entity ID)**: your `sp_entity_id`
- **Single sign-on URL**: your ACS URL
- **Name ID format**: leave **Unspecified** unless you have a strong reason to
change it
- **Signature Algorithm**: keep **RSA-SHA256**
- **X.509 Certificate**: download the active SHA-256 signing certificate
Okta vocabulary matters here because Relyra's preset hints and operator
messages use these exact labels.
## 2. Configure Relyra
Use the preset so the safe defaults stay aligned with the library's Okta
contract:
```elixir
connection =
Relyra.Provider.apply_defaults(:okta, [
sp_entity_id: "https://sp.example.com/metadata",
acs_url: "https://sp.example.com/saml/acs",
idp_sso_url: "https://example.okta.com/app/.../sso/saml",
idp_certificates: ["-----BEGIN CERTIFICATE-----..."]
])
```
Key defaults applied by the preset:
- `allow_idp_initiated?: false`
- `require_signed_assertions?: true`
- `require_signed_response?: true`
- `name_id_format: "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"`
- `algorithm_policy.signing: :rsa_sha256`
## 3. Proof of success
Use one concrete receipt before treating the provider path as complete:
- A successful SP-initiated login returns to your host app through the ACS
route you configured.
- The configured `sp_entity_id` exactly matches Okta's
**Audience URI (SP Entity ID)**.
- The active signing certificate in Relyra matches the one exported from Okta.
Proof receipt:
- A real Okta login succeeds after the local `FakeIdP` proof already passed.
## 4. Common failures
| Symptom | Why it happens | Fix |
| --- | --- | --- |
| Audience mismatch | Okta's **Audience URI (SP Entity ID)** does not exactly match `sp_entity_id` | Make the values identical, including trailing slash behavior. |
| Signed response rejected | The wrong Okta certificate or a stale certificate is configured | Export the active **X.509 Certificate** again and update `idp_certificates`. |
| Login works in dev but not prod | Signing policy drifted to SHA-1 or another weak default | Keep **Signature Algorithm** on RSA-SHA256 and preserve the preset defaults. |
| IdP-initiated login is flaky | The preset is intentionally optimized for SP-initiated flows | Leave `allow_idp_initiated?` disabled unless you are explicitly supporting that flow. |
## 5. Day-2 notes
- Re-check the active signing certificate during rotation events.
- Treat any move toward IdP-initiated login as a deliberate product decision,
not a convenience toggle.
- Keep metadata, audit review, telemetry, and diagnostic-bundle handling in the
host application's production follow-on plan.
## Related case studies
- [Phoenix SaaS tenant onboarding](../case_studies/phoenix_saas_tenant_onboarding.md)
at `guides/case_studies/phoenix_saas_tenant_onboarding.md`
- [Operator-managed rollout](../case_studies/operator_managed_rollout.md)
at `guides/case_studies/operator_managed_rollout.md`