From 61dd3c2765ebe8a98d7386e3e5677848e6c779a2 Mon Sep 17 00:00:00 2001 From: tmesgong Date: Mon, 3 Jun 2024 11:35:22 +0000 Subject: [PATCH 1/4] add okta email mfa support --- pkg/provider/okta/okta.go | 4 +++- saml2aws.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/provider/okta/okta.go b/pkg/provider/okta/okta.go index 65978ca50..f073463fe 100644 --- a/pkg/provider/okta/okta.go +++ b/pkg/provider/okta/okta.go @@ -36,6 +36,7 @@ import ( const ( IdentifierDuoMfa = "DUO WEB" IdentifierSmsMfa = "OKTA SMS" + IdentifierEMailMfa = "OKTA EMAIL" IdentifierPushMfa = "OKTA PUSH" IdentifierTotpMfa = "GOOGLE TOKEN:SOFTWARE:TOTP" IdentifierOktaTotpMfa = "OKTA TOKEN:SOFTWARE:TOTP" @@ -50,6 +51,7 @@ var ( supportedMfaOptions = map[string]string{ IdentifierDuoMfa: "DUO MFA authentication", IdentifierSmsMfa: "SMS MFA authentication", + IdentifierEMailMfa: "Email MFA authentication", IdentifierPushMfa: "PUSH MFA authentication", IdentifierTotpMfa: "TOTP MFA authentication", IdentifierOktaTotpMfa: "Okta MFA authentication", @@ -811,7 +813,7 @@ func verifyMfa(oc *Client, oktaOrgHost string, loginDetails *creds.LoginDetails, switch mfa := challengeContext.mfaIdentifer; mfa { case IdentifierYubiMfa: return gjson.Get(challengeContext.challengeResponseBody, "sessionToken").String(), nil - case IdentifierSmsMfa, IdentifierTotpMfa, IdentifierOktaTotpMfa, IdentifierSymantecTotpMfa: + case IdentifierSmsMfa, IdentifierEMailMfa, IdentifierTotpMfa, IdentifierOktaTotpMfa, IdentifierSymantecTotpMfa: var verifyCode = loginDetails.MFAToken if verifyCode == "" { verifyCode = prompter.RequestSecurityCode("000000") diff --git a/saml2aws.go b/saml2aws.go index 670e79f5d..fbef27985 100644 --- a/saml2aws.go +++ b/saml2aws.go @@ -40,7 +40,7 @@ var MFAsByProvider = ProviderList{ "PingNTLM": []string{"Auto"}, // automatically detects PingID "PingOne": []string{"Auto"}, // automatically detects PingID "JumpCloud": []string{"Auto", "TOTP", "WEBAUTHN", "DUO", "PUSH"}, - "Okta": []string{"Auto", "PUSH", "DUO", "SMS", "TOTP", "OKTA", "FIDO", "YUBICO TOKEN:HARDWARE", "SYMANTEC"}, // automatically detects DUO, SMS, ToTP, and FIDO + "Okta": []string{"Auto", "PUSH", "DUO", "SMS", "EMAIL", "TOTP", "OKTA", "FIDO", "YUBICO TOKEN:HARDWARE", "SYMANTEC"}, // automatically detects DUO, SMS, ToTP, and FIDO "OneLogin": []string{"Auto", "OLP", "SMS", "TOTP", "YUBIKEY", "DUO TOTP"}, // automatically detects OneLogin Protect, SMS and ToTP "Authentik": []string{"Auto"}, "KeyCloak": []string{"Auto"}, // automatically detects ToTP From 51cb6bc827c7aba2c1141a1f65b606d6f8cf5a4d Mon Sep 17 00:00:00 2001 From: tmesgong Date: Tue, 4 Jun 2024 02:18:53 +0000 Subject: [PATCH 2/4] lint fix --- saml2aws.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saml2aws.go b/saml2aws.go index fbef27985..e3b30b9fd 100644 --- a/saml2aws.go +++ b/saml2aws.go @@ -41,7 +41,7 @@ var MFAsByProvider = ProviderList{ "PingOne": []string{"Auto"}, // automatically detects PingID "JumpCloud": []string{"Auto", "TOTP", "WEBAUTHN", "DUO", "PUSH"}, "Okta": []string{"Auto", "PUSH", "DUO", "SMS", "EMAIL", "TOTP", "OKTA", "FIDO", "YUBICO TOKEN:HARDWARE", "SYMANTEC"}, // automatically detects DUO, SMS, ToTP, and FIDO - "OneLogin": []string{"Auto", "OLP", "SMS", "TOTP", "YUBIKEY", "DUO TOTP"}, // automatically detects OneLogin Protect, SMS and ToTP + "OneLogin": []string{"Auto", "OLP", "SMS", "TOTP", "YUBIKEY", "DUO TOTP"}, // automatically detects OneLogin Protect, SMS and ToTP "Authentik": []string{"Auto"}, "KeyCloak": []string{"Auto"}, // automatically detects ToTP "GoogleApps": []string{"Auto"}, // automatically detects ToTP From cb95570e83c540968a7680a8994bd26fcde4512c Mon Sep 17 00:00:00 2001 From: tmesgong Date: Wed, 5 Jun 2024 10:55:10 +0000 Subject: [PATCH 3/4] fix some name casing issue --- pkg/provider/okta/okta.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/provider/okta/okta.go b/pkg/provider/okta/okta.go index f073463fe..52690b2f3 100644 --- a/pkg/provider/okta/okta.go +++ b/pkg/provider/okta/okta.go @@ -36,7 +36,7 @@ import ( const ( IdentifierDuoMfa = "DUO WEB" IdentifierSmsMfa = "OKTA SMS" - IdentifierEMailMfa = "OKTA EMAIL" + IdentifierEmailMfa = "OKTA EMAIL" IdentifierPushMfa = "OKTA PUSH" IdentifierTotpMfa = "GOOGLE TOKEN:SOFTWARE:TOTP" IdentifierOktaTotpMfa = "OKTA TOKEN:SOFTWARE:TOTP" @@ -51,7 +51,7 @@ var ( supportedMfaOptions = map[string]string{ IdentifierDuoMfa: "DUO MFA authentication", IdentifierSmsMfa: "SMS MFA authentication", - IdentifierEMailMfa: "Email MFA authentication", + IdentifierEmailMfa: "EMAIL MFA authentication", IdentifierPushMfa: "PUSH MFA authentication", IdentifierTotpMfa: "TOTP MFA authentication", IdentifierOktaTotpMfa: "Okta MFA authentication", @@ -813,7 +813,7 @@ func verifyMfa(oc *Client, oktaOrgHost string, loginDetails *creds.LoginDetails, switch mfa := challengeContext.mfaIdentifer; mfa { case IdentifierYubiMfa: return gjson.Get(challengeContext.challengeResponseBody, "sessionToken").String(), nil - case IdentifierSmsMfa, IdentifierEMailMfa, IdentifierTotpMfa, IdentifierOktaTotpMfa, IdentifierSymantecTotpMfa: + case IdentifierSmsMfa, IdentifierEmailMfa, IdentifierTotpMfa, IdentifierOktaTotpMfa, IdentifierSymantecTotpMfa: var verifyCode = loginDetails.MFAToken if verifyCode == "" { verifyCode = prompter.RequestSecurityCode("000000") From 37f0b631f4f2f43215a068604ad99eb6ba0de2b9 Mon Sep 17 00:00:00 2001 From: tmesgong Date: Wed, 5 Jun 2024 13:17:24 +0000 Subject: [PATCH 4/4] add okta mfa email test --- pkg/provider/okta/okta_test.go | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/pkg/provider/okta/okta_test.go b/pkg/provider/okta/okta_test.go index c55499f61..06e8cd4f7 100644 --- a/pkg/provider/okta/okta_test.go +++ b/pkg/provider/okta/okta_test.go @@ -267,6 +267,54 @@ func TestVerifyMfa(t *testing.T) { }) } +func TestVerifyMfa_Email(t *testing.T) { + + ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/verify": + _, err := w.Write([]byte(`{ + "sessionToken": "TOKEN_3", + "status": "SUCCESS" + }`)) + assert.Nil(t, err) + + default: + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + } + })) + defer ts.Close() + + t.Run("Email", func(t *testing.T) { + oc, loginDetails := setupTestClient(t, ts, "EMAIL") + + err := oc.setDeviceTokenCookie(loginDetails) + assert.Nil(t, err) + + var out bytes.Buffer + log.SetOutput(&out) + context, err := verifyMfa(oc, "", &creds.LoginDetails{ + MFAToken: "123456", + }, fmt.Sprintf(`{ + "stateToken": "TOKEN_1", + "_embedded": { + "factors": [ + { + "id": "EMAIL", + "provider": "OKTA", + "factorType": "EMAIL", + "_links": { + "verify": { "href": "%s/verify" } + } + } + ] + } + }`, ts.URL)) + log.SetOutput(os.Stderr) + assert.Nil(t, err) + assert.Equal(t, context, "TOKEN_3") + }) +} + func TestVerifyMfa_Duo(t *testing.T) { t.Run("Duo Push", func(t *testing.T) { ts := setupTestDuoHttpServer(t, "Duo Push")