> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/security/authentication-providers-and-mfa.md).

# Authentication providers and MFA

Decide which authentication provider type and which second factor a situation calls for, then go to the page that configures it.

## What this is, and when you need it

Authentication in OpenIAM is four objects, not one. An **authentication provider** (`AUTH_PROVIDER`) decides *how credentials are checked* and which password and authentication policies apply. An **authentication level** (`AUTH_LEVEL`) names *a kind of proof* — a password, a TOTP code, a FIDO assertion. An **authentication rule** (`AUTH_RULE`) chains those levels into a flow. A **content provider** or **URI pattern** attaches a rule to the traffic it protects.

You edit the provider when you change *how* a credential is verified. You edit the rule when you change *which and how many* proofs are demanded. Confusing the two is the most common reason a new second factor is configured correctly and never prompts.

This page is where you **decide** which provider type and which factor you need. It is not where you configure one: every method has its own page, named in the tables below.

{% hint style="danger" %}
Every change these pages describe is in the blast radius that [Change configuration safely](/administration-guide/start/change-safely.md) calls unrecoverable: a broken sign-in path locks out the administrator making the change. Do [Keep a working way in](#keep-a-working-way-in) first, whichever method you are about to configure.
{% endhint %}

## The provider types you can create

`AUTH_PROVIDER_TYPE` is a small, closed table of **10 values**. You cannot add a type: the **Type** drop-down on **Access Control → Authentication Providers → New** (`/webconsole/newAuthProvider`) offers exactly these and nothing else.

| `PROVIDER_TYPE`          | Webconsole label       | Create one when                                                                                                                            | Configure it on                                                                                   |
| ------------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| `OPENIAM_POLICY`         | Default Auth Provider  | You are checking a username and password against a managed system, or adding any second factor. Renamed *Authentication policy* in 4.2.0.7 | This page, plus the per-factor pages below                                                        |
| `SAML_PROVIDER`          | SAML Identity Provider | OpenIAM authenticates the user and issues an assertion to someone else's application                                                       | [OpenIAM as a SAML identity provider](/administration-guide/federation/saml-identity-provider.md) |
| `SAML_SP_PROVIDER`       | SAML Service Provider  | Someone else's IdP authenticates users *into* OpenIAM                                                                                      | [OpenIAM as a SAML service provider](/administration-guide/federation/saml-service-provider.md)   |
| `OAUTH_CLIENT`           | OAuth Client           | An application needs access tokens or ID tokens from OpenIAM                                                                               | [OAuth 2.0 and OpenID Connect](/administration-guide/federation/oauth-and-oidc.md)                |
| `GOOGLE_AUTH_PROVIDER`   | Google Auth Provider   | Users sign in with a Google account                                                                                                        | [Social sign-in](/administration-guide/security/social-authentication.md)                         |
| `FACEBOOK_AUTH_PROVIDER` | Facebook Auth Provider | Users sign in with a Facebook account                                                                                                      | [Social sign-in](/administration-guide/security/social-authentication.md)                         |
| `LINKEDIN_AUTH_PROVIDER` | LinkedIn Auth Provider | Users sign in with a LinkedIn account                                                                                                      | [Social sign-in](/administration-guide/security/social-authentication.md)                         |
| `APPLEID_AUTH_PROVIDER`  | Apple ID Auth Provider | Users sign in with Apple                                                                                                                   | [Social sign-in](/administration-guide/security/social-authentication.md)                         |
| `CRIIPTO_AUTH_PROVIDER`  | Criipto Auth Provider  | You broker a national eID through Criipto                                                                                                  | Referenced from an `OPENIAM_POLICY` provider — see below                                          |
| `DUO_AUTH_PROVIDER`      | DUO Auth Provider      | You already run a Duo tenant                                                                                                               | [Add Duo as a second factor](/administration-guide/security/duo.md)                               |

The middle column is the label the Webconsole shows in that drop-down and in the provider list. `GOOGLE_AUTH_PROVIDER`, `FACEBOOK_AUTH_PROVIDER`, `LINKEDIN_AUTH_PROVIDER` and `APPLEID_AUTH_PROVIDER` are the four types OpenIAM treats as social, and they are cached as one group, so they all refresh together on the provider sweep. Which cache group a type belongs to is not shown anywhere in the console.

`CRIIPTO_AUTH_PROVIDER` and `DUO_AUTH_PROVIDER` are **not** picked directly at sign-in. They are referenced from an `OPENIAM_POLICY` provider, through the **Criipto Auth Domain** field (`AUTH_PROVIDER.CRIIPTO_AUTH_DOMAIN`, since 4.2.1.6) and the **DUO Authentication Provider** field (`AUTH_PROVIDER.DUO_PROVIDER_ID`, since 4.2.1.8).

## Choose the second factor

Every second factor is a capability of the `OPENIAM_POLICY` provider, and it only ever prompts because a rule demands it. Pick by what the population can actually hold:

| You want                                                 | Authentication level                   | Configure it on                                                                            | The trap to know before you start                                                                                   |
| -------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| A code from an authenticator app                         | `TOTP_AUTH`                            | [Add TOTP as a second factor](/administration-guide/security/totp.md)                      | OpenIAM's time step is 60 seconds and the QR code does not say so, so most apps produce a code the server rejects   |
| A phishing-resistant hardware or platform key            | `WEB_AUTH`                             | [FIDO2 and WebAuthn](/administration-guide/security/fido2-and-webauthn.md)                 | Credentials bind to one hostname, and a user with no key cannot register one from behind a sign-in that demands one |
| A push approval or a code through an existing Duo tenant | `DUO_AUTH`                             | [Add Duo as a second factor](/administration-guide/security/duo.md)                        | The redirect URI must match Duo's registration exactly, and the state lives in Redis                                |
| A code by SMS, voice or email                            | `SMS_AUTH`, `VOICE_AUTH`, `EMAIL_AUTH` | [SMS and one-time passwords](/administration-guide/platform/sms-and-otp.md)                | Code length is clamped to 4–9 digits and the message template's only placeholder is `%s`                            |
| A client certificate or smart card                       | `CERT_AUTH`                            | [Certificate authentication](/administration-guide/security/certificate-authentication.md) | Nothing validates the CA unless you write the script that does                                                      |
| Security questions, on recovery paths                    | `CHALLENGE_RESPONSE_AUTH`              | [Configure password recovery](/administration-guide/security/password-recovery.md)         | The shipped recovery rule offers **Password** to a user who has forgotten it                                        |
| A national eID through Criipto                           | `CRIIPTO_AUTH`                         | The **Criipto Auth Domain** field on an `OPENIAM_POLICY` provider                          | The type has no content-provider attachment; it is reached from the policy provider only                            |
| A stronger factor on one URL only                        | any of the above                       | [Step-up authentication](/administration-guide/security/step-up-authentication.md)         | The level lives on the URI pattern, not the provider                                                                |
| A factor demanded only when the sign-in looks unusual    | any of the above                       | [Adaptive authentication](/administration-guide/security/adaptive-authentication.md)       | Four of the fourteen risk signals fail *open*                                                                       |

Every level OpenIAM can route to, its IdP page and whether it demands an already-authenticated session are in [Authentication levels, rules and capability flags](/administration-guide/security/authentication-providers-and-mfa/authentication-provider-reference.md).

## Capability flags decide which fields you see

The single most common support question about the provider form is "why is there no TOTP checkbox on this provider?" The answer is almost never the provider. It is a `CHAR(1)` flag on the provider's **type**, and none of them is editable from the Webconsole.

Read the pair like this: the **type** flag decides whether the checkbox is rendered at all, and the **provider** flag *is* the checkbox. The runtime gate is the provider flag — OpenIAM does not send a user to the TOTP page unless that provider's **Supports TOTP Authentication** box is ticked, and the auth-level picker on a content provider greys out `SMS_AUTH`, `EMAIL_AUTH`, `TOTP_AUTH` and `CERT_AUTH` on exactly the same flags. You can tell the two apart on screen without a query: a checkbox that is **missing** means the type flag is `N`, and a checkbox that is **present but clear** means the provider flag is `N`.

{% hint style="info" %}
**Every second factor is a capability of `OPENIAM_POLICY` and of nothing else.** `SUPPORTS_TOTP`, `SUPPORTS_SMS_OTP`, `SUPPORTS_EMAIL_OTP`, `SUPPORTS_CERT_AUTH`, `SUPPORTS_CRIIPTO_AUTH` and `SUPPORTS_DUO_AUTH` ship `Y` on that type alone. If you are trying to add a second factor to a SAML or social provider, the field is absent by design, not by misconfiguration. Put the factor on the `OPENIAM_POLICY` provider that the content provider points at.
{% endhint %}

Two more flags decide the form's shape rather than a factor. `HAS_AUTHN_POLICY` and `AUTHN_POLICY_REQUIRED` ship `Y` on `OPENIAM_POLICY`, `SAML_SP_PROVIDER`, `CRIIPTO_AUTH_PROVIDER` and `DUO_AUTH_PROVIDER`, which is why those four demand an **Authentication policy**; `SUPPORTS_JUST_IN_TIME_AUTH` ships `Y` on `SAML_SP_PROVIDER` only, and does not do what its name suggests — see [Just-in-time provisioning](/administration-guide/federation/jit-provisioning.md). The policy the field points at is `AUTH_PROVIDER.AUTH_POLICY_ID`, separate from the password policy in `AUTH_PROVIDER.POLICY_ID`; the shipped default provider uses `POLICY_ID='4000'` and `AUTH_POLICY_ID='4001'`.

{% hint style="warning" %}
**`IS_LINKABLE_TO_CP` is not what the drop-down obeys.** The **Authentication Provider** list on a content provider is filtered against a fixed list built into the product, and `DUO_AUTH_PROVIDER` and `CRIIPTO_AUTH_PROVIDER` are absent from it even though they ship with the column set to `'Y'`. Changing the column will not make them appear — and it should not, because those two types are referenced from a policy provider rather than attached to a content provider. The mismatch cannot be confirmed from the console: the only thing you can observe is a type present in `AUTH_PROVIDER_TYPE` and missing from the list.
{% endhint %}

The full flag list, which types ship each one, and the whole `Authentication` property category are in [Authentication levels, rules and capability flags](/administration-guide/security/authentication-providers-and-mfa/authentication-provider-reference.md).

## Keep a working way in

Before you touch a provider, a rule or a content provider — whichever method you are configuring — make sure one path to the Webconsole survives whatever you break. Four precautions, in order:

{% stepper %}
{% step %}

### Leave the shipped default provider alone

The shipped provider is `OPENIAM_DEFAULT_AUTH`, name **Default Openiam Auth Policy**, type `OPENIAM_POLICY`, `MANAGED_SYS_ID='0'`, `IS_DEFAULT='Y'`, `SPRING_BEAN_NAME='defaultLoginModule'`, `POLICY_ID='4000'`, `AUTH_POLICY_ID='4001'`. It is the provider OpenIAM falls back to, and it earns that only by having `IS_DEFAULT` true **and** type `OPENIAM_POLICY` — change either and there is no default at all. Build a new provider alongside it; do not repoint this one. OpenIAM will not let you delete it: the attempt returns *"The default authentication provider cannot be deleted"*, which is also the quickest way to confirm you are looking at the right row.
{% endstep %}

{% step %}

### Leave `DEF_PASSWD_AUTH_RULE` on `DEFAULT_CP`

The shipped content provider is `DEFAULT_CP`, **Default Content Provider**, pointing at `OPENIAM_DEFAULT_AUTH`, and every content provider carries `DEF_PASSWD_AUTH_RULE` at `EXEC_ORDER` 0. Add your new rule at a higher `EXEC_ORDER`, or attach it to a specific URI pattern, rather than replacing that row. Password-only sign-in is your floor. Confirm it is still there on the content provider's rule list before you leave the screen.
{% endstep %}

{% step %}

### Test the break-glass account before, not after

In a separate browser session, sign in as an administrator whose path uses only `OPENIAM_DEFAULT_AUTH` and `DEF_PASSWD_AUTH_RULE`, and confirm you reach `/webconsole/`. Keep that session open while you make the change. Re-test after.
{% endstep %}

{% step %}

### Stage the new factor as optional first

Attach the new rule to one narrow URI pattern and one test identity before it goes on the content provider. A rule on a content provider applies to everyone that provider serves, including you.
{% endstep %}
{% endstepper %}

{% hint style="danger" %}
**Break-glass: restoring password sign-in after a lockout.** There is no in-product path back from a content provider whose only rule demands a factor nobody can satisfy — if nobody can sign in, nobody can fix it in the Webconsole. The recovery is at the database, and it is outside the supported change path.

Diagnose read-only first, on the affected content provider:

{% code overflow="wrap" %}

```sql
SELECT CONTENT_PROVIDER_ID, RULE_ID, EXEC_ORDER FROM CP_RULE_XREF
 WHERE CONTENT_PROVIDER_ID = 'DEFAULT_CP' ORDER BY EXEC_ORDER;
```

{% endcode %}

If no row names `DEF_PASSWD_AUTH_RULE`, put one back at `EXEC_ORDER` 0 — the narrowest write that restores a way in — then wait out `org.openiam.auth.provider.sweep.time` (60 s) before you retry sign-in.

What this costs: the write bypasses the Webconsole entirely, so it produces **no audit record** of the change and no validation of what you inserted, and it is invisible to anyone reading the audit trail afterwards. Note it in your own change record. It also does not repair whatever rule caused the lockout; fix that from the Webconsole once you are back in, and delete the emergency row if you did not mean to keep it. The supported alternative — slower, but auditable — is to have OpenIAM support or the deployment owner make the change for you.
{% endhint %}

## Why a change does not seem to take

Provider and policy changes are picked up by scheduled sweeps, not immediately: `org.openiam.auth.provider.sweep.time` is `60000` ms and `org.openiam.policy.sweep.time` is `72000` ms. Re-test after a minute, not after a second. If the prompt still does not fire after a sweep, the question is almost always "which rule is attached to this path" rather than "is the provider right" — `/webconsole/authenticationDebug` reports how a given request was evaluated and names the rules that actually applied.

## Related

* [The authentication model](/administration-guide/security/authentication-model.md) — how a request reaches a rule, and how a URI pattern's rules replace a content provider's
* [Authentication levels, rules and capability flags](/administration-guide/security/authentication-providers-and-mfa/authentication-provider-reference.md) — every level, every shipped rule, every flag, and the `Authentication` property category
* [Password and authentication policy parameters](/administration-guide/reference/policy-parameters.md) — policies `4000` and `4001`
* [Change configuration safely](/administration-guide/start/change-safely.md) — the standard this section assumes

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/security/authentication-providers-and-mfa.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
