Skip to content

Commit

Permalink
[v17] feat: SSO MFA - Teleport Connect (#48629)
Browse files Browse the repository at this point in the history
* Add SSO prompt to Teleport Connect.

* Add SSO to Connect MFA Modal WIP

* Let connect open redirect URL.

* Remove login success timeout change.

* Add SSO story.

* Address comments.

* Fix prompt when SSO is the only/default method.

* Address comments.

* Fix double prompt.

* Add dep list to useEffect in ReAuthenticate

* Resolve comments.

---------

Co-authored-by: Rafał Cieślak <[email protected]>
  • Loading branch information
Joerger and ravicious authored Nov 12, 2024
1 parent ea83cea commit e5db36c
Show file tree
Hide file tree
Showing 18 changed files with 699 additions and 346 deletions.
579 changes: 336 additions & 243 deletions gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service.pb.go

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

107 changes: 106 additions & 1 deletion gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions lib/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,9 @@ type Config struct {
// MFAPromptConstructor is a custom MFA prompt constructor to use when prompting for MFA.
MFAPromptConstructor func(cfg *libmfa.PromptConfig) mfa.Prompt

// SSOMFACeremonyConstructor is a custom SSO MFA ceremony constructor.
SSOMFACeremonyConstructor func(rd *sso.Redirector) mfa.SSOMFACeremony

// CustomHardwareKeyPrompt is a custom hardware key prompt to use when asking
// for a hardware key PIN, touch, etc.
// If empty, a default CLI prompt is used.
Expand Down
4 changes: 4 additions & 0 deletions lib/client/mfa.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,9 @@ func (tc *TeleportClient) NewSSOMFACeremony(ctx context.Context) (mfa.SSOMFACere
return nil, trace.Wrap(err, "failed to create a redirector for SSO MFA")
}

if tc.SSOMFACeremonyConstructor != nil {
return tc.SSOMFACeremonyConstructor(rd), nil
}

return sso.NewCLIMFACeremony(rd), nil
}
25 changes: 25 additions & 0 deletions lib/client/sso/ceremony.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/gravitational/trace"

"github.com/gravitational/teleport/api/client/proto"
"github.com/gravitational/teleport/api/mfa"
"github.com/gravitational/teleport/lib/auth/authclient"
)

Expand Down Expand Up @@ -125,3 +126,27 @@ func NewCLIMFACeremony(rd *Redirector) *MFACeremony {
},
}
}

// NewConnectMFACeremony creates a new Teleport Connect SSO ceremony from the given redirector.
func NewConnectMFACeremony(rd *Redirector) mfa.SSOMFACeremony {
return &MFACeremony{
close: rd.Close,
ClientCallbackURL: rd.ClientCallbackURL,
HandleRedirect: func(ctx context.Context, redirectURL string) error {
// Connect handles redirect on the Electron side.
return nil
},
GetCallbackMFAToken: func(ctx context.Context) (string, error) {
loginResp, err := rd.WaitForResponse(ctx)
if err != nil {
return "", trace.Wrap(err)
}

if loginResp.MFAToken == "" {
return "", trace.BadParameter("login response for SSO MFA flow missing MFA token")
}

return loginResp.MFAToken, nil
},
}
}
2 changes: 2 additions & 0 deletions lib/teleterm/clusters/cluster_gateways.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/gravitational/teleport/api/mfa"
"github.com/gravitational/teleport/lib/client"
libmfa "github.com/gravitational/teleport/lib/client/mfa"
"github.com/gravitational/teleport/lib/client/sso"
"github.com/gravitational/teleport/lib/teleterm/api/uri"
"github.com/gravitational/teleport/lib/teleterm/gateway"
"github.com/gravitational/teleport/lib/tlsca"
Expand All @@ -52,6 +53,7 @@ type CreateGatewayParams struct {
// CreateGateway creates a gateway
func (c *Cluster) CreateGateway(ctx context.Context, params CreateGatewayParams) (gateway.Gateway, error) {
c.clusterClient.MFAPromptConstructor = params.MFAPromptConstructor
c.clusterClient.SSOMFACeremonyConstructor = sso.NewConnectMFACeremony

switch {
case params.TargetURI.IsDB():
Expand Down
4 changes: 3 additions & 1 deletion lib/teleterm/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
api "github.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1"
"github.com/gravitational/teleport/lib/auth/authclient"
"github.com/gravitational/teleport/lib/client"
"github.com/gravitational/teleport/lib/client/sso"
dtauthn "github.com/gravitational/teleport/lib/devicetrust/authn"
"github.com/gravitational/teleport/lib/teleterm/api/uri"
"github.com/gravitational/teleport/lib/teleterm/clusters"
Expand Down Expand Up @@ -265,6 +266,8 @@ func (s *Service) ResolveClusterURI(uri uri.ResourceURI) (*clusters.Cluster, *cl
// Custom MFAPromptConstructor gets removed during the calls to Login and LoginPasswordless RPCs.
// Those RPCs assume that the default CLI prompt is in use.
clusterClient.MFAPromptConstructor = s.NewMFAPromptConstructor(cluster.URI)
clusterClient.SSOMFACeremonyConstructor = sso.NewConnectMFACeremony

return cluster, clusterClient, nil
}

Expand Down Expand Up @@ -1081,7 +1084,6 @@ func (s *Service) GetUserPreferences(ctx context.Context, clusterURI uri.Resourc
preferences, err = userpreferences.Get(ctx, rootAuthClient, leafAuthClient)
return trace.Wrap(err)
})

if err != nil {
return nil, trace.Wrap(err)
}
Expand Down
Loading

0 comments on commit e5db36c

Please sign in to comment.