Skip to content

Add a null check to getMfaChallengeResponse#50570

Merged
zmb3 merged 3 commits intomasterfrom
joerger/web-mfa-add-null-check
Dec 30, 2024
Merged

Add a null check to getMfaChallengeResponse#50570
zmb3 merged 3 commits intomasterfrom
joerger/web-mfa-add-null-check

Conversation

@Joerger
Copy link
Copy Markdown
Contributor

@Joerger Joerger commented Dec 24, 2024

Changelog: Fixed a bug in the WebUI that could cause an access denied error when accessing application.

Fix a bug caused by #49679 which was meant to check for null/undefined.

Closes #50556

Comment thread web/packages/teleport/src/services/mfa/makeMfa.ts
Comment thread web/packages/teleport/src/services/auth/auth.ts Outdated
Comment thread web/packages/teleport/src/services/auth/auth.ts
@ravicious
Copy link
Copy Markdown
Member

Why the app access bug is present on branch/v17 but not on master

As discussed on Slack, on branch/v17, the faulty getMfaChallengeResponse is called every time an app session is created through the app launcher:

Details

const session = await service.createAppSession(params);

// Prompt for MFA if per-session MFA is required for this app.
const challenge = await auth.getMfaChallenge({
scope: MfaChallengeScope.USER_SESSION,
allowReuse: false,
isMfaRequiredRequest: {
app: resolveApp,
},
});
const resp = await auth.getMfaChallengeResponse(challenge);

On master, that function is not called at all and the code for handling MFA returns early if challenge is falsy. That was implemented in #49794 which added support for SSO MFA.

Details

const createAppSessionParams = params as CreateAppSessionParams;
createAppSessionParams.mfaResponse = await mfa.getChallengeResponse();
const session = await service.createAppSession(createAppSessionParams);

challenge = challenge ? challenge : await auth.getMfaChallenge(req);
if (!challenge) {
setMfaRequired(false);
return;
}

Broken password change flow with second_factor: "optional"

I wanted to find a way to reproduce the problem with that function on master, as it's still used in a couple of places. However, most of those places are triggered only when MFA is actually available. One of the places it's used is useReAuthenticate which is used in the password change flow.

I launched Teleport with TELEPORT_ALLOW_NO_SECOND_FACTOR=yes and second_factor: "optional", I created a new user with an MFA device, then I removed the device in hopes that I'd be able to trigger the bug during the password change. However, before I was able to trigger a call to getMfaChallengeResponse, I ran into another problem:

const reauthOptions = getReauthOptions(mfaOptions, hasPasswordless);
setReauthMethod(reauthOptions[0].value);

This throws an error, as reauthOptions is empty if there's no MFA options available.

I don't know how many customers actually use TELEPORT_ALLOW_NO_SECOND_FACTOR, but it's an issue we should probably solve separately from this specific problem.


As it is, the easiest way to check if this PR fixes the problem is to cherry pick it on branch/v17.

Copy link
Copy Markdown
Member

@ravicious ravicious left a comment

Choose a reason for hiding this comment

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

This fixes the problem on v17.

I wanted to suggest adding some tests, but SSO MFA is going to land in v17 and useMfa already has tests for when MFA is not required.

Since strict null checks are not enabled, another option to guarantee that the "no MFA challenge" is always handled would be to use a discriminated union, e.g. { kind: 'no-challenge' } | { kind: 'challenge', foo: Bar }. This would also help with adding null checks "just in case", as functions that actually need to work on a challenge could accept only the union variant with the challenge.

It's tempting to use { required: false } | { required: true, foo: Bar }. Unfortunately, discriminated unions on boolean fields don't work well with strict null checks turned off.

Copy link
Copy Markdown
Collaborator

@zmb3 zmb3 left a comment

Choose a reason for hiding this comment

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

Thanks @ravicious

@zmb3 zmb3 enabled auto-merge December 30, 2024 14:51
@zmb3 zmb3 added this pull request to the merge queue Dec 30, 2024
Merged via the queue into master with commit c4da026 Dec 30, 2024
@zmb3 zmb3 deleted the joerger/web-mfa-add-null-check branch December 30, 2024 15:03
@public-teleport-github-review-bot
Copy link
Copy Markdown

@Joerger See the table below for backport results.

Branch Result
branch/v17 Create PR

carloscastrojumo pushed a commit to carloscastrojumo/teleport that referenced this pull request Feb 19, 2025
* Add a null check to getMfaChallengeResponse.

* Add other null checks, just in case.

* Update signatures to include undefined, consistently return undefined

---------

Co-authored-by: Rafał Cieślak <rafal.cieslak@goteleport.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Application Redirects Fail with 'Access Denied' Error After Updating to Teleport Version 17.1.1 Due to Certificate Validation Issues

3 participants