Skip to content

DO NOT MERGE, REFERENCE ONLY Support high assurance level - #545

Draft
bheesham wants to merge 11 commits into
mozilla-iam:masterfrom
bheesham:assurance-levels-support-high
Draft

DO NOT MERGE, REFERENCE ONLY Support high assurance level#545
bheesham wants to merge 11 commits into
mozilla-iam:masterfrom
bheesham:assurance-levels-support-high

Conversation

@bheesham

@bheesham bheesham commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Jira: IAM-1989


tl;dr: for some RPs we need to support a stricter policy for MFA. This PR adds support for HIGH.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for a stricter authenticator assurance policy (HIGH) in the accessRules Auth0 Action, along with Terraform secret wiring and test updates, to enable RPs to require stronger MFA characteristics.

Changes:

  • Introduces an AAL→AAI mapping (including HIGH) and updates decision logic to select the highest AAL across matching authorization rules.
  • Updates Duo configuration handling to select credentials based on the required AAL.
  • Adjusts Jest tests to reflect new HIGH behavior (Duo treated as satisfying HARDWARE).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
tf/actions/accessRules.js Adds HIGH AAL support, mapping/selection logic, and Duo config selection changes.
tf/tests/accessRules.test.js Updates tests for the new HIGH behavior expectations.
tf/actions.tf Renames/splits Duo Action secrets into medium/high variants for the Action runtime.
Comments suppressed due to low confidence (1)

tf/actions/accessRules.js:382

  • For LDAP (strategy === "ad") users that require Duo, enableDuo is set but aai remains empty. That causes MEDIUM requirements to fail the AAI check (since AAI_MAPPING["MEDIUM"] is non-empty), denying access before the Duo challenge can be triggered. If enabling Duo is intended to satisfy MEDIUM, add the relevant AAI indicator(s) when enableDuo is set.
    // Allow certain LDAP service accounts to fake their MFA. For all other LDAPi accounts, enforce MFA
    if (event.connection.strategy === "ad") {
      // No support for HIGH or MAXIMUM assurance levels.
      if (mfaBypassAccounts.includes(event.user.email)) {
        console.log(
          `LDAP service account (${event.user.email}) is allowed to bypass MFA`
        );
        aai.add("2FA");
      } else {
        enableDuo = true;
        console.log(
          `duosecurity: ${event.user.email} is in LDAP and requires 2FA check`
        );
      }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tf/actions/accessRules.js
Comment thread tf/actions/accessRules.js
Comment thread tf/actions/accessRules.js Outdated
Comment thread tf/actions/accessRules.js
@bheesham
bheesham force-pushed the assurance-levels-support-high branch from 93e70b5 to 3116de6 Compare July 6, 2026 20:17
@bheesham
bheesham force-pushed the assurance-levels-support-high branch from 3116de6 to e00eede Compare July 13, 2026 14:57
@bheesham
bheesham force-pushed the assurance-levels-support-high branch 2 times, most recently from 68a4d04 to 9f4c881 Compare July 24, 2026 19:54
@bheesham

Copy link
Copy Markdown
Contributor Author

Tested successfully on dev:

Screenshot 2026-07-24 at 15 54 53

@bheesham
bheesham force-pushed the assurance-levels-support-high branch from adc9883 to 66b397b Compare July 24, 2026 21:58
Comment thread tf/actions/accessRules.js Outdated
// in access file.
const AAL_DEFAULT = "MEDIUM";

// The minimum AAL employees may have.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love it. If landed, I hope you'll add notes to apps.yml that explain that AAL: LOW has a new path / doesn't mean what is written. But that's a nitpick, whatevs.

Really, I worry that there might be RPs in here that will burp because of a new minimum. Just top of my head, there appears to be a conflation of AD_MIN being taken to mean 'employee' when it's LDAP users, which may have non-employees.

This might be fine! But I am first-blush skeptical.

@bheesham bheesham Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, there was a bug here. The bit of code where this is used should have instead lived in a different if statement: where we check if Duo is included in their profile.

The original one didn't hit the duo branch, and I missed that in this implementation. The test now passes here, and continues to pass on master.

The behaviour for LDAPers hasn't changed (anymore!), and I added to the comment for AAL_AD_MIN. But yeah, because this was always the behaviour, the docs in apps.yml are still out of date. PR incoming.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bheesham added 3 commits July 31, 2026 00:33
This commit redoes a bit of the logic and expands the test case to allow
`HARDWARE`.

Jira: IAM-1989
This commit configures the Duo client differently, depending on the
level of assurance we want. The client we use has different policies
applied, restricting the kind of access required.

Jira: IAM-1989
@bheesham
bheesham force-pushed the assurance-levels-support-high branch from ea2274e to 03b5744 Compare July 31, 2026 04:44
Comment thread tf/actions/accessRules.js
// 2 Check if user.aal is allowed for this RP
if (AAI_MAPPING[aal].size === 0) {
console.log(
"No required indicator in aai_mapping for this RP (mapping empty for this AAL), access will be granted"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should default-allow here. aal goes through checks above, and should arrive here as a valid value because of AAL_DEFAULT existing. And if it doesn't, then we've missed something above, big time.

IMO, default-deny here. It probably isn't a big win, I get it.

Comment thread tf/actions/accessRules.js
Comment thread tf/actions/accessRules.js Outdated
// supports. (And because that means either 2FA or Hardware, the minimum is
// 2FA).
//
// Before IAM-1989, you can see this in play:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(er, before and after. nothing related to this is changing.)

@bheesham
bheesham marked this pull request as draft August 6, 2026 22:32
@bheesham

bheesham commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

I chatted with @VegasNative about this, and I'm way off base! AAL is defined here, and I'll quote for convenience.

AAL1 permits single-factor authentication using a wide variety of authenticators listed in SP 800-63B Section 4.1.1. By far the most common authenticator at AAL1 is the memorized secret, but from the standpoint of meeting AAL1 requirements it is equally acceptable to use a physical authenticator such as an OTP device.

This is our LOWEST.

AAL2 requires the use of two authentication factors, either (1) a physical authenticator and a memorized secret, or (2) a physical authenticator and a biometric that has been associated with it. Multi-factor authentication can be performed using either a multi-factor authenticator or through the use of two independent authenticators.

This is our MEDIUM.

This PR adds HIGH, but I don't think that's the intention here. We want to restrict which factors are used in the authentication process, not necessarily give a higher level of assurance.

Some of the logic here can be kept, but I think anything related to us saying HIGH AAL should be removed. I think what we really want is to add a new key to the apps.yml spec, to specify which authenticators should be allowed, and add that to the AAI (ref for future dev). (Maybe?)

I have a meeting scheduled with @gene1wood tomorrow to chat more.

@bheesham

bheesham commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

(Dunno though! I'll keep reading.)

@bheesham

bheesham commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

More info! I chatted with @gene1wood!

re: changing remembered devices in Duo: no policy; it was easier to remember in Auth0 than in Duo. I believe we should be able to change the settings for only the SSO application in Duo. That would still remember clients for 30 days. It does come at the cost of an extra HTTP call, but, it's probably fine.

re: AAL The AAL stuff is really a mapping Mozilla's risk standard levels (referenced in, the archived, mozilla-iam repository). I'll have to ensure the docs in mozilla-iam are copied over to Confluence, or some easier to find place.

A brief detour into AALs

Quoting the docs:

The AALs are ranked using the Mozilla Standard Levels, i.e. LOW/MEDIUM/HIGH/MAXIMUM. The AAL is used to determine if a user should be granted access per relying party.

And, quoting a bit from SP 800-63B Section 4.1.1:

AAL1 provides some assurance that the claimant controls an authenticator bound to the subscriber’s account. AAL1 requires either single-factor or multi-factor authentication using a wide range of available authentication technologies. Successful authentication requires that the claimant prove possession and control of the authenticator through a secure authentication protocol.

A memorized secret covers this when we don't prompt for MFA, and roughly corresponds to our LOW risk.

At AAL2, authentication SHALL occur by the use of either a multi-factor authenticator or a combination of two single-factor authenticators. A multi-factor authenticator requires two factors to execute a single authentication event, such as a cryptographically-secure device with an integrated biometric sensor that is required to activate the device. Authenticator requirements are specified in Section 5.

AAL2 maps to roughly our MEDIUM. Since we always ask for a password, the following applies to us:

When a combination of two single-factor authenticators is used, it SHALL include a Memorized Secret authenticator (Section 5.1.1) and one possession-based (i.e., “something you have”) authenticator from the following list:

But, most of that's not really relevant to the issue: an RP requiring specific factors to be used.

There's some info I was able to gather [0] [1], paraphrasing here for
posterity.

Info from @VegasNative: AALs are defined differently. This led to the
conversation with Gene, since I was thoroughly confused at this point.

Turns out, I missed the intent of the ticket, what AALs are, and how we
use them. Since Gene's here, I figured it's best to have a quick convo
to learn more.

Info from @gene1wood:

    re: changing remembered devices in Duo: no policy; it was easier to
    remember in Auth0 than in Duo. I believe we should be able to change
    the settings for only the SSO application in Duo. That would still
    remember clients for 30 days. It does come at the cost of an extra
    HTTP call, but, it's probably fine.

    re: AAL The AAL stuff is really a mapping Mozilla's [risk standard levels]
    (referenced in, the archived, [mozilla-iam] repository). I'll have to
    ensure the docs in mozilla-iam are copied over to Confluence, or some
    easier to find place.

Jira: IAM-1989

[0]: mozilla-iam#545 (comment)
[1]: mozilla-iam#545 (comment)
[risk standard levels]: https://infosec.mozilla.org/guidelines/risk/standard_levels
[mozilla-iam]: https://github.com/mozilla-iam/mozilla-iam#authentication-assurance
Jira: IAM-1989
@bheesham bheesham changed the title Support high assurance level DO NOT MERGE, REFERENCE ONLY Support high assurance level Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants