diff --git a/lib/auth/mfatypes/types.go b/lib/auth/mfatypes/types.go new file mode 100644 index 0000000000000..dd81db37e0720 --- /dev/null +++ b/lib/auth/mfatypes/types.go @@ -0,0 +1,28 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package mfatypes + +import mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" + +// ChallengeExtensions is a json struct for [mfav1.ChallengeExtensions]. +type ChallengeExtensions struct { + Scope mfav1.ChallengeScope `json:"scope"` + AllowReuse mfav1.ChallengeAllowReuse `json:"allow_reuse,omitempty"` + UserVerificationRequirement string `json:"user_verification_requirement,omitempty"` +} diff --git a/lib/auth/sso_mfa.go b/lib/auth/sso_mfa.go index d53659f9d3ba9..9441e667df8b9 100644 --- a/lib/auth/sso_mfa.go +++ b/lib/auth/sso_mfa.go @@ -26,6 +26,7 @@ import ( "github.com/gravitational/teleport/api/constants" mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/auth/mfatypes" "github.com/gravitational/teleport/lib/authz" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/services" @@ -137,11 +138,14 @@ func (a *Server) verifySSOMFASession(ctx context.Context, username, sessionID, t // sessionID, connector details, and challenge extensions. func (a *Server) upsertSSOMFASession(ctx context.Context, user string, sessionID string, connectorID string, connectorType string, ext *mfav1.ChallengeExtensions) error { err := a.UpsertSSOMFASessionData(ctx, &services.SSOMFASessionData{ - Username: user, - RequestID: sessionID, - ConnectorID: connectorID, - ConnectorType: connectorType, - ChallengeExtensions: ext, + Username: user, + RequestID: sessionID, + ConnectorID: connectorID, + ConnectorType: connectorType, + ChallengeExtensions: &mfatypes.ChallengeExtensions{ + Scope: ext.Scope, + AllowReuse: ext.AllowReuse, + }, }) return trace.Wrap(err) } diff --git a/lib/auth/sso_mfa_test.go b/lib/auth/sso_mfa_test.go index 081ffaa0ef13e..831cbf5f26d94 100644 --- a/lib/auth/sso_mfa_test.go +++ b/lib/auth/sso_mfa_test.go @@ -34,6 +34,7 @@ import ( mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/auth/authclient" + "github.com/gravitational/teleport/lib/auth/mfatypes" "github.com/gravitational/teleport/lib/authz" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/services" @@ -275,7 +276,7 @@ func TestSSOMFAChallenge_Creation(t *testing.T) { Username: samlUser.GetName(), ConnectorID: samlConnector.GetName(), ConnectorType: samlConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, }, }, sd) @@ -314,7 +315,7 @@ func TestSSOMFAChallenge_Creation(t *testing.T) { Username: oidcUser.GetName(), ConnectorID: oidcConnector.GetName(), ConnectorType: oidcConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, }, }, sd) @@ -480,7 +481,7 @@ func TestSSOMFAChallenge_Validation(t *testing.T) { Username: "wrong-user", ConnectorID: samlConnector.GetName(), ConnectorType: samlConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, }, Token: "token", @@ -504,7 +505,7 @@ func TestSSOMFAChallenge_Validation(t *testing.T) { Username: samlUser.GetName(), ConnectorID: samlConnector.GetName(), ConnectorType: samlConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, }, Token: "token", @@ -528,7 +529,7 @@ func TestSSOMFAChallenge_Validation(t *testing.T) { Username: samlUser.GetName(), ConnectorID: samlConnector.GetName(), ConnectorType: samlConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, }, }, @@ -551,7 +552,7 @@ func TestSSOMFAChallenge_Validation(t *testing.T) { Username: samlUser.GetName(), ConnectorID: samlConnector.GetName(), ConnectorType: samlConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, }, Token: "token", @@ -575,7 +576,7 @@ func TestSSOMFAChallenge_Validation(t *testing.T) { Username: samlUser.GetName(), ConnectorID: samlConnector.GetName(), ConnectorType: samlConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, AllowReuse: mfav1.ChallengeAllowReuse_CHALLENGE_ALLOW_REUSE_YES, }, @@ -601,7 +602,7 @@ func TestSSOMFAChallenge_Validation(t *testing.T) { Username: noMFASAMLUser.GetName(), ConnectorID: noMFASAMLConnector.GetName(), ConnectorType: noMFASAMLConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, }, Token: "token", @@ -625,7 +626,7 @@ func TestSSOMFAChallenge_Validation(t *testing.T) { Username: standardUser.GetName(), ConnectorID: samlConnector.GetName(), ConnectorType: samlConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, }, Token: "token", @@ -649,7 +650,7 @@ func TestSSOMFAChallenge_Validation(t *testing.T) { Username: samlUser.GetName(), ConnectorID: samlConnector.GetName(), ConnectorType: samlConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, AllowReuse: mfav1.ChallengeAllowReuse_CHALLENGE_ALLOW_REUSE_NO, }, @@ -679,7 +680,7 @@ func TestSSOMFAChallenge_Validation(t *testing.T) { Username: samlUser.GetName(), ConnectorID: samlConnector.GetName(), ConnectorType: samlConnector.GetKind(), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_LOGIN, AllowReuse: mfav1.ChallengeAllowReuse_CHALLENGE_ALLOW_REUSE_YES, }, diff --git a/lib/auth/webauthn/login.go b/lib/auth/webauthn/login.go index 7f668bf974483..2ed9f085155a6 100644 --- a/lib/auth/webauthn/login.go +++ b/lib/auth/webauthn/login.go @@ -35,6 +35,7 @@ import ( mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/auth/mfatypes" wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes" ) @@ -190,7 +191,11 @@ func (f *loginFlow) begin(ctx context.Context, user string, challengeExtensions if err != nil { return nil, trace.Wrap(err) } - sd.ChallengeExtensions = challengeExtensions + sd.ChallengeExtensions = &mfatypes.ChallengeExtensions{ + Scope: challengeExtensions.Scope, + AllowReuse: challengeExtensions.AllowReuse, + UserVerificationRequirement: challengeExtensions.UserVerificationRequirement, + } if err := f.sessionData.Upsert(ctx, user, sd); err != nil { return nil, trace.Wrap(err) diff --git a/lib/auth/webauthn/login_test.go b/lib/auth/webauthn/login_test.go index 0d88e6c016948..9995d87930fe5 100644 --- a/lib/auth/webauthn/login_test.go +++ b/lib/auth/webauthn/login_test.go @@ -34,6 +34,7 @@ import ( mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/auth/mfatypes" "github.com/gravitational/teleport/lib/auth/mocku2f" wanlib "github.com/gravitational/teleport/lib/auth/webauthn" wantypes "github.com/gravitational/teleport/lib/auth/webauthntypes" @@ -441,7 +442,7 @@ func TestPasswordlessFlow_BeginAndFinish(t *testing.T) { AllowCredentials: [][]uint8{}, // aka unset ResidentKey: false, // irrelevant for login UserVerification: string(protocol.VerificationRequired), - ChallengeExtensions: &mfav1.ChallengeExtensions{ + ChallengeExtensions: &mfatypes.ChallengeExtensions{ Scope: mfav1.ChallengeScope_CHALLENGE_SCOPE_PASSWORDLESS_LOGIN, AllowReuse: mfav1.ChallengeAllowReuse_CHALLENGE_ALLOW_REUSE_NO, }, diff --git a/lib/auth/webauthntypes/webauthn.go b/lib/auth/webauthntypes/webauthn.go index 9931732a84be6..2ae1b318a0ad0 100644 --- a/lib/auth/webauthntypes/webauthn.go +++ b/lib/auth/webauthntypes/webauthn.go @@ -27,7 +27,7 @@ import ( "github.com/go-webauthn/webauthn/webauthn" "github.com/gravitational/trace" - mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" + "github.com/gravitational/teleport/lib/auth/mfatypes" ) // CredentialAssertion is the payload sent to authenticators to initiate login. @@ -405,7 +405,7 @@ type SessionData struct { // An empty value is treated equivalently to "discouraged". UserVerification string `json:"userVerification,omitempty"` // ChallengeExtensions are Teleport extensions that apply to this webauthn session. - ChallengeExtensions *mfav1.ChallengeExtensions `json:"challenge_extensions,omitempty"` + ChallengeExtensions *mfatypes.ChallengeExtensions `json:"challenge_extensions,omitempty"` } // SessionDataFromProtocol converts a [webauthn.SessionData] struct to an diff --git a/lib/services/sso_mfa.go b/lib/services/sso_mfa.go index da877be2fd50c..a43e557fb38f6 100644 --- a/lib/services/sso_mfa.go +++ b/lib/services/sso_mfa.go @@ -18,7 +18,7 @@ package services -import mfav1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" +import "github.com/gravitational/teleport/lib/auth/mfatypes" // SSOMFASessionData SSO MFA Session data. type SSOMFASessionData struct { @@ -34,5 +34,5 @@ type SSOMFASessionData struct { // ConnectorType is SSO type of the corresponding Auth connector (SAML, OIDC). ConnectorType string `json:"connector_type,omitempty"` // ChallengeExtensions are Teleport extensions that apply to this SSO MFA session. - ChallengeExtensions *mfav1.ChallengeExtensions `json:"challenge_extensions,omitempty"` + ChallengeExtensions *mfatypes.ChallengeExtensions `json:"challenge_extensions"` }