# Okta: authentication policies and global session policy for phishing-resistant MFA

Source: https://startwithidentity.com/recipes/okta-phishing-resistant-authentication-policies/
Last updated: 2026-11-05
License: content by Start with Identity. Cite the source URL.

---

To make Okta sign-in phishing-resistant, you enforce it in the app sign-in policy, not the global session policy. In [Okta](https://startwithidentity.com/vendors/iam/okta/) Identity Engine the global session policy decides how an Okta session is established and how long it lives, while each app sign-in (authentication) policy decides which factors are acceptable for that app. You enable the Passkey (FIDO2 WebAuthn) authenticator and Okta Verify for FastPass, require enrollment for a pilot group, add a rule whose **Possession factor constraints** include **Phishing resistant**, and change the catch-all rule so users who fall through are denied. The result: a stolen password plus an SMS, email or push code no longer opens the Okta Dashboard, the Okta Admin Console or any app on that policy, which is the control that defeats an [AiTM phishing proxy](https://startwithidentity.com/techniques/aitm-phishing-proxy/) and [push bombing](https://startwithidentity.com/techniques/mfa-fatigue-push-bombing/).

## Before you start: which policy does what

| Policy | Admin Console location | Role in this rollout |
|---|---|---|
| Global session policy | Security > Global Session Policy | Establishes the Okta session; set it to defer to app policy factors |
| Authenticator enrollment policy | Security > Authenticators > Enrollment | Makes users enroll a passkey or Okta Verify |
| App sign-in policy | Security > Authentication Policies > App sign-in | Where the Phishing resistant constraint is enforced, per app |
| Okta Admin Console policy | Same tab, policy named Okta Admin Console | Protects administrators; do this first |

Rules in a policy are evaluated in priority order and evaluation stops at the first match, per Okta's [global session policy evaluation](https://help.okta.com/oie/en-us/content/topics/identity-engine/policies/osop-evaluation.htm) doc, so a narrow pilot rule must sit above broader ones. See [authentication policy](https://startwithidentity.com/glossary/authentication-policy/) and [phishing-resistant MFA](https://startwithidentity.com/glossary/phishing-resistant-mfa/) for the concepts, and the [MFA matrix](https://startwithidentity.com/tools/mfa-matrix/) for which factors qualify.

## 1. Add the phishing-resistant authenticators

Per [Add the Passkey (FIDO2 WebAuthn) authenticator](https://help.okta.com/OIE/en-us/content/topics/identity-engine/authenticators/add-passkeys.htm):

```text
Security > Authenticators > Setup > Add Authenticator
  Passkey (FIDO2 WebAuthn) tile > Add
  Credential settings: Create passkeys = On
  Access controls: User verification (Enrollment / Authentication) = Required
  Optional: Block synced passkeys = On (device-bound keys only)
  Add
```

The [access controls](https://help.okta.com/oie/en-us/content/topics/identity-engine/authenticators/passkeys-access-controls.htm) page lists **Required**, **Preferred** (default) and **Discouraged** for user verification. Okta FastPass, the passwordless option in Okta Verify, also satisfies the phishing-resistant constraint, so add Okta Verify too if you use it.

**Check:** Both authenticators show on the **Setup** tab with status Active.
**Common failure:** Blocking synced passkeys stops iPhone users who have no security key; Okta's [configure passkeys](https://help.okta.com/oie/en-us/content/topics/identity-engine/authenticators/configure-passkeys.htm) page says they then need FastPass or an NFC or USB-C key.
**Rollback:** **Actions > Edit** to relax settings. Remove the authenticator from policies before you delete it.

## 2. Create the pilot group and enrollment policy

Create a group under **Directory > Groups > Add group** (for example `PR-MFA-Pilot`). Do not add your break-glass administrator. Then, under **Security > Authenticators > Enrollment**, add an authenticator enrollment policy assigned to the pilot group with **Passkey (FIDO2 WebAuthn)** set to **Required** (or Okta Verify Required for a FastPass rollout), and a rule where **Enrollment is** allowed for all authenticators. Move it to the top of the priority list, as Okta's [phishing-resistant policy guide](https://help.okta.com/oie/en-us/content/topics/identity-engine/authenticators/pr-set-up-policies.htm) does.

**Check:** A pilot user signing in is prompted to enroll a passkey.
**Common failure:** The policy sits below the default enrollment policy, so it never matches.
**Rollback:** Deactivate the policy; existing enrollments remain.

## 3. Configure the global session policy

Under **Security > Global Session Policy**, add a policy for the pilot group with a rule (labels per [Add a global session policy rule](https://help.okta.com/oie/en-us/content/topics/identity-engine/policies/add-okta-sign-on-policy-rule.htm)):

```text
Establish the user session with:  Any factor used to meet the Authentication Policy requirements
Multifactor authentication (MFA) is:  Required
Users will be prompted for MFA:  At every sign in
Maximum Okta global session idle time:  set to your standard
```

Okta's [FastPass app sign-in guide](https://help.okta.com/oie/en-us/content/topics/identity-engine/devices/fp/fp-asop.htm) says to protect apps with strong app sign-in policies before you drop the password requirement here, because this moves control to the app policies.

**Check:** The new policy is ranked above Default Policy.
**Common failure:** Leaving **A password** selected means a passwordless FastPass flow still asks for a password.
**Rollback:** Deactivate the policy; the Default Policy applies again.

## 4. Add the phishing-resistant app sign-in rule

Go to **Security > Authentication Policies > App sign-in**, open the policy (start with **Okta Dashboard**), then **Rules > Add rule**. Field names are from [Add an app sign-in policy rule](https://help.okta.com/oie/en-us/content/topics/identity-engine/policies/add-app-sign-on-policy-rule.htm):

```text
IF User's group membership includes:  At least one of: PR-MFA-Pilot
THEN Access is:  Allowed after successful authentication
User must authenticate with:  Any 2 factor types
Possession factor constraints are:  [x] Phishing resistant  [x] Require user interaction
Prompt for authentication:  set to your re-authentication standard
```

Save and drag the rule to the top. A new policy starts with a catch-all rule that allows any two factor types. Once pilot users are covered, edit the catch-all rule so **Access is: Denied**, which is what the FastPass guide recommends for the bottom rule. Only do that when every population on the policy has a rule above it.

**Check:** The rule list shows the pilot rule at priority 1 and the catch-all last.
**Common failure:** **Possession factor constraints** is greyed out because **User must authenticate with** is set to Password or a one-factor option; the constraint does not apply to those.
**Rollback:** Deactivate the rule, or move it below the catch-all.

## 5. Protect the Okta Admin Console

Per [Enable MFA for the Admin Console](https://help.okta.com/oie/en-us/content/topics/security/mfa/mfa-enable-admins.htm): **Security > Authentication Policies > App sign-in > Okta Admin Console**, edit the **Admin App Policy** rule, choose a two-factor option, require a phishing-resistant possession factor, and prompt every time the user signs in. Repeat for that policy's catch-all rule.

This is the rule that matters most. In the [2023 help desk attacks on Okta super administrators](https://startwithidentity.com/breaches/incidents/2023-okta-customer-help-desk-super-admin-takeover/), attackers talked service desks into resetting admin MFA, then changed authentication policies and added an identity provider. Pair this rule with strict factor-reset verification for admins.

**Check:** An admin with only a password and SMS is blocked from the Admin Console.
**Common failure:** Locking out every admin. Keep a tested break-glass account enrolled in a FIDO2 key before you save.
**Rollback:** Edit the rule back from a still-valid admin session.

## 6. Optional: manage rules through the Policies API

List app sign-in policies (`type` is required) and create a rule. The constraint shape is from Okta's Management API spec (`ACCESS_POLICY`, `phishingResistant: REQUIRED`); creating rules needs the `okta.policies.manage` scope.

```bash
curl -s "https://${OKTA_DOMAIN}/api/v1/policies?type=ACCESS_POLICY" \
  -H "Authorization: Bearer ${TOKEN}"

curl -s -X POST "https://${OKTA_DOMAIN}/api/v1/policies/${POLICY_ID}/rules" \
  -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
  -d '{
    "type": "ACCESS_POLICY",
    "name": "PR-MFA pilot",
    "conditions": { "people": { "groups": { "include": ["<group-id>"] } } },
    "actions": { "appSignOn": {
      "access": "ALLOW",
      "verificationMethod": {
        "type": "ASSURANCE",
        "factorMode": "2FA",
        "reauthenticateIn": "PT2H",
        "constraints": [ { "possession": { "phishingResistant": "REQUIRED" } } ]
      } } }
  }'
```

**Check:** The response returns a rule `id` and `status: ACTIVE`. Okta caps app sign-in policies at 100 rules.
**Common failure:** A 403 means the token lacks `okta.policies.manage`.
**Rollback:** `POST /api/v1/policies/{policyId}/rules/{ruleId}/lifecycle/deactivate`.

## 7. Expand in stages

Add groups to the rule wave by wave (IT, then admins of other SaaS apps, then everyone), assign the remaining apps to the policy from its **Applications** tab, and only then flip catch-alls to deny. The [MFA rollout guide](https://startwithidentity.com/guides/authentication/mfa-rollout/) covers communications and exception handling.

## Verify it works

1. **Negative test:** Sign in as a pilot user with password plus an SMS, email or push code. Access to the Okta Dashboard should be refused.
2. **Positive test:** Sign in with the security key, platform passkey or FastPass. Access should be allowed.
3. **System Log:** Query the events defined in Okta's [event types catalog](https://developer.okta.com/docs/reference/api/event-types/):

```bash
curl -s -G "https://${OKTA_DOMAIN}/api/v1/logs" \
  -H "Authorization: Bearer ${TOKEN}" \
  --data-urlencode 'filter=eventType eq "application.policy.sign_on.deny_access"' \
  --data-urlencode 'since=2026-11-05T00:00:00Z'
```

Expect `application.policy.sign_on.deny_access` for the negative test, `policy.evaluate_sign_on` (outcome ALLOW, CHALLENGE or DENY; in Identity Engine one event can cover both the global session and authentication policy) for both, `user.authentication.auth_via_mfa` for the factor used, and `user.mfa.factor.activate` when a pilot user enrolls. Alert on `policy.rule.update` and `policy.lifecycle.update` so any weakening of these rules pages someone.

## Related

- [Phishing-resistant MFA](https://startwithidentity.com/glossary/phishing-resistant-mfa/) and [FIDO2](https://startwithidentity.com/glossary/fido2/)
- [Authentication policy](https://startwithidentity.com/glossary/authentication-policy/)
- [AiTM phishing proxy](https://startwithidentity.com/techniques/aitm-phishing-proxy/) and [help desk social engineering](https://startwithidentity.com/techniques/help-desk-social-engineering/)
- [MFA rollout guide](https://startwithidentity.com/guides/authentication/mfa-rollout/)
- [Entra Conditional Access baseline](https://startwithidentity.com/recipes/entra-conditional-access-baseline/)
- [Add passkeys with WebAuthn](https://startwithidentity.com/recipes/add-passkeys-webauthn/)
