Skip to content

[Browser MFA] Add CompleteBrowserMFAChallenge gRPC#63873

Merged
danielashare merged 1 commit into
masterfrom
danielashare/browser-mfa-validate-browser-mfa-chal
Mar 25, 2026
Merged

[Browser MFA] Add CompleteBrowserMFAChallenge gRPC#63873
danielashare merged 1 commit into
masterfrom
danielashare/browser-mfa-validate-browser-mfa-chal

Conversation

@danielashare
Copy link
Copy Markdown
Contributor

@danielashare danielashare commented Feb 17, 2026

This PR adds the CompleteBrowserMFAChallenge gRPC endpoint. The RFD for this addition can be found here.

These changes address this part of the flow:

sequenceDiagram
    proxy->>auth: rpc CompleteBrowserMFAChallenge
    auth->>auth: Encrypt WebAuthn response<br/>with secret_key
    auth-->>proxy: Return http://127.0.0.1:port/callback?response={encrypted_webauthn}
    proxy-->>browser: HTTP 200 with redirect URL
Loading

I would like to draw particular attention to login.go. In order to validate the WebAuthn response from the browser without consuming it, I had to split the validation logic out of login.go's finish function in to its own function. I want to avoid consuming it because in the full Browser MFA flow, the WebAuthn response is returned to tsh where it will exchange the response for certificates etc. I wonder if it is worth validating the MFA response from the browser before sending it back to tsh where it will then send the MFA response back to the server where it will have to be validated again anyway?
Decided in comments that there isn't any point double validating the response, instead response is validated once by tsh.

Manual tests:

  • Login with OTP
  • Login with WebAuthn
  • Login with TouchID
  • Login with YubiKey
  • Passwordless login with TouchID
  • Passwordless login with YubiKey
  • Passwordless login with WebAuthn

@danielashare danielashare self-assigned this Feb 17, 2026
@danielashare danielashare added no-changelog Indicates that a PR does not require a changelog entry backport/branch/v18 labels Feb 17, 2026
@danielashare danielashare force-pushed the danielashare/browser-mfa-validate-browser-mfa-chal branch 2 times, most recently from d516d0c to 9075cce Compare February 18, 2026 12:20
Copy link
Copy Markdown
Contributor

@codingllama codingllama left a comment

Choose a reason for hiding this comment

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

Reviewed a good chunk of it, but not all.

As stated in the proto PR, I think the RPC could be in the specialized MFAService instead.

This could also, potentially, be split into a few distinct smaller PRs: lib/webauthn changes, browser MFA encrypt/decrypt, and the RPC itself. Once we add tests in various layers it'll likely grow.

Comment thread lib/auth/authclient/clt.go
Comment thread lib/auth/grpcserver.go Outdated
Comment thread lib/auth/browser_mfa.go Outdated
Comment thread lib/auth/grpcserver.go Outdated
Comment thread lib/auth/auth_with_roles.go Outdated
Comment thread lib/auth/grpcserver.go Outdated
Comment thread lib/auth/browser_mfa.go Outdated
Comment thread lib/auth/webauthn/login_mfa.go Outdated
Comment thread lib/auth/webauthn/login_mfa.go Outdated
Comment thread lib/auth/webauthn/login_mfa.go Outdated
@danielashare danielashare force-pushed the danielashare/browser-mfa-validate-browser-mfa-chal branch 3 times, most recently from 2d299c0 to 5b450e8 Compare February 19, 2026 16:39
@danielashare danielashare changed the base branch from danielashare/browser-mfa-proto to danielashare/browser-mfa-webauthn-validation February 19, 2026 16:40
@danielashare
Copy link
Copy Markdown
Contributor Author

Apologies @codingllama, your comments have lost their context since I split out the webauthn changes

@codingllama
Copy link
Copy Markdown
Contributor

Apologies codingllama, your comments have lost their context since I split out the webauthn changes

No worries, give me a ping when this is good for another pass.

@danielashare danielashare force-pushed the danielashare/browser-mfa-webauthn-validation branch 7 times, most recently from 6a05b78 to a1f454e Compare February 23, 2026 13:16
@danielashare danielashare changed the base branch from danielashare/browser-mfa-webauthn-validation to danielashare/browser-mfa-proto February 23, 2026 13:34
@danielashare
Copy link
Copy Markdown
Contributor Author

No worries, give me a ping when this is good for another pass.

Cheers, @codingllama, I think this is ready for another pass.
I've removed the webauthn validation changes from this branch and moved them to their own branch (as you've seen).

I shouldn't have pointed the browser-mfa-webauthn-validation branch at master because this branch, which relies on those changes, also relies on the proto changes. So, I've pointed this branch at the proto branch and once that goes in, I can point this one back at browser-mfa-webauthn-validation.

@danielashare danielashare force-pushed the danielashare/browser-mfa-validate-browser-mfa-chal branch from 2a10623 to 000dd03 Compare February 23, 2026 15:34
@danielashare danielashare force-pushed the danielashare/browser-mfa-proto branch from e08f5d2 to 55869d8 Compare February 26, 2026 23:29
Copy link
Copy Markdown
Contributor

@Joerger Joerger left a comment

Choose a reason for hiding this comment

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

Partial review here.

I wonder if it is worth validating the MFA response from the browser before sending it back to tsh where it will then send the MFA response back to the server where it will have to be validated again anyway?

Agreed, I don't think it is necessary to validate it ahead of time. Perhaps it would be better to remove the validation and name it CompleteBrowserMFAChallenge instead. It doesn't hurt to validate it upfront, but I don't remember a technical/security requirement for it.

Comment thread api/proto/teleport/legacy/client/proto/authservice.proto
Comment thread lib/auth/mfa/mfav1/service.go Outdated
@danielashare danielashare force-pushed the danielashare/browser-mfa-proto branch 2 times, most recently from 8ea0de0 to 0cb377a Compare February 28, 2026 03:16
@danielashare danielashare force-pushed the danielashare/browser-mfa-proto branch from 0cb377a to 8a5561b Compare March 2, 2026 07:40
Base automatically changed from danielashare/browser-mfa-proto to master March 2, 2026 09:08
@danielashare danielashare force-pushed the danielashare/browser-mfa-validate-browser-mfa-chal branch from 000dd03 to 9284a34 Compare March 3, 2026 12:26
@danielashare danielashare changed the title [Browser MFA] Add ValidateBrowserMFAChallenge gRPC [Browser MFA] Add CompleteBrowserMFAChallenge gRPC Mar 3, 2026
@danielashare danielashare force-pushed the danielashare/browser-mfa-validate-browser-mfa-chal branch from b7ec9db to 82e1d3b Compare March 20, 2026 14:22
Comment thread lib/auth/authclient/clt.go Outdated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Would something like CLILoginResponse be a better name for this?

Comment thread lib/auth/internal/browser_mfa.go Outdated
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package internal
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Internal packages (ie those that are under an internal/ directory) are great, but I don't love naming the package itself internal.

How about lib/auth/internal/browsermfa? Something that still describes what the package contains.

Comment thread lib/auth/internal/browser_mfa.go Outdated
)

// Payload type required by (lib/client/sso/redirector.go).
type ssoRedirectorResponse = authclient.SSHLoginResponse
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there any particular reason to make this a type alias? Why not use authclient.SSHLoginResponse directly?

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.

There's a conversation somewhere in this PR (that I can't seem to find now), where Alan found it confusing that Browser MFA returns an SSHLoginResponse. So the type alias is to make the code easier to understand that we're returning this data to the redirector

Comment thread lib/auth/browser_mfa_test.go Outdated
Comment thread lib/auth/browser_mfa_test.go Outdated
tests := []struct {
name string
setupSession func(t *testing.T) string
assertError func(t *testing.T, err error)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
assertError func(t *testing.T, err error)
assertError require.ErrorAssertionFunc

Consider using the existing library type instead of defining your own.

Comment thread lib/auth/browser_mfa.go Outdated
@danielashare danielashare force-pushed the danielashare/browser-mfa-validate-browser-mfa-chal branch 2 times, most recently from f533310 to 823277e Compare March 22, 2026 08:20
@danielashare danielashare force-pushed the danielashare/browser-mfa-validate-browser-mfa-chal branch from 1f76179 to 1f9c073 Compare March 25, 2026 07:24
@danielashare danielashare added this pull request to the merge queue Mar 25, 2026
Merged via the queue into master with commit 1c88a1b Mar 25, 2026
42 checks passed
@danielashare danielashare deleted the danielashare/browser-mfa-validate-browser-mfa-chal branch March 25, 2026 17:33
@backport-bot-workflows
Copy link
Copy Markdown
Contributor

@danielashare See the table below for backport results.

Branch Result
branch/v18 Failed

danielashare added a commit that referenced this pull request May 6, 2026
[Browser MFA] Add protobuf and config (#63831)

[Browser MFA] Add proto for Browser MFA feature (#64048)

[Browser MFA] Add CompleteBrowserMFAChallenge gRPC (#63873)

[Browser MFA] Rename browser mfa config name (#64980)

[Browser MFA] Add BrowserMFARequestID to CreateAuthenticateChallenge (#63945)

[Browser MFA] Add Browser MFA to challenge request flow (#63936)

[Browser MFA] Add initial requests for browser MFA process to client tools (#64301)

[Browser MFA] Add tsh callback handling for webauthn response (#64461)

[Browser MFA] Add Browser MFA to presence checks (#65052)

[Browser MFA] Add browser MFA path to MFA finish flow (#64523)

[Browser MFA] Add Browser MFA to Connect (#64887)

[Browser MFA] Add Browser MFA UI (#64692)

[Browser MFA] Fix formatting in moderated sessions (#65236)

[Browser MFA] Add Browser MFA ceremony tests
ivan-bax pushed a commit to ivan-bax/teleport that referenced this pull request May 22, 2026
[Browser MFA] Add protobuf and config (gravitational#63831)

[Browser MFA] Add proto for Browser MFA feature (gravitational#64048)

[Browser MFA] Add CompleteBrowserMFAChallenge gRPC (gravitational#63873)

[Browser MFA] Rename browser mfa config name (gravitational#64980)

[Browser MFA] Add BrowserMFARequestID to CreateAuthenticateChallenge (gravitational#63945)

[Browser MFA] Add Browser MFA to challenge request flow (gravitational#63936)

[Browser MFA] Add initial requests for browser MFA process to client tools (gravitational#64301)

[Browser MFA] Add tsh callback handling for webauthn response (gravitational#64461)

[Browser MFA] Add Browser MFA to presence checks (gravitational#65052)

[Browser MFA] Add browser MFA path to MFA finish flow (gravitational#64523)

[Browser MFA] Add Browser MFA to Connect (gravitational#64887)

[Browser MFA] Add Browser MFA UI (gravitational#64692)

[Browser MFA] Fix formatting in moderated sessions (gravitational#65236)

[Browser MFA] Add Browser MFA ceremony tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport/branch/v18 no-changelog Indicates that a PR does not require a changelog entry size/lg

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants