Skip to content

Commit a34d766

Browse files
ramya18101nelsonmaia
authored andcommitted
Merge branch 'main' into feature/session-transfer-allow-refresh-token
2 parents ff8eff8 + 241abd0 commit a34d766

File tree

8 files changed

+206
-17
lines changed

8 files changed

+206
-17
lines changed

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ better alternative.
3737

3838
- `api_token` (String) Your Auth0 [management api access token](https://auth0.com/docs/security/tokens/access-tokens/management-api-access-tokens). It can also be sourced from the `AUTH0_API_TOKEN` environment variable. It can be used instead of `client_id` + `client_secret`. If both are specified, `api_token` will be used over `client_id` + `client_secret` fields.
3939
- `audience` (String) Your Auth0 audience when using a custom domain. It can also be sourced from the `AUTH0_AUDIENCE` environment variable.
40+
- `cli_login` (Boolean) While toggled on, the API token gets fetched from the keyring for the given domain
4041
- `client_id` (String) Your Auth0 client ID. It can also be sourced from the `AUTH0_CLIENT_ID` environment variable.
4142
- `client_secret` (String) Your Auth0 client secret. It can also be sourced from the `AUTH0_CLIENT_SECRET` environment variable.
4243
- `debug` (Boolean) Enables HTTP request and response logging when TF_LOG=DEBUG is set. It can also be sourced from the `AUTH0_DEBUG` environment variable.

docs/resources/prompt_screen_renderer.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ resource "auth0_prompt_screen_renderer" "prompt_screen_renderer" {
5656

5757
### Required
5858

59-
- `prompt_type` (String) The prompt that you are configuring settings for. Options are: `signup-id`, `signup-password`, `login-id`, `login-password`, `login-passwordless`, `phone-identifier-enrollment`, `phone-identifier-challenge`, `email-identifier-challenge`, `passkeys`, `captcha`, `login`, `signup`, `reset-password`, `mfa`, `mfa-sms`, `mfa-email`, `mfa-push`, `invitation`, `organizations`, `mfa-otp`, `device-flow`, `mfa-phone`, `mfa-voice`, `mfa-recovery-code`, `common`.
60-
- `screen_name` (String) The screen that you are configuring settings for. Options are: `signup-id`, `signup-password`, `login-id`, `login-password`, `login-passwordless-sms-otp`, `login-passwordless-email-code`, `phone-identifier-enrollment`, `phone-identifier-challenge`, `email-identifier-challenge`, `passkey-enrollment`, `passkey-enrollment-local`, `interstitial-captcha`, `login`, `signup`, `reset-password-request`, `reset-password-email`, `reset-password`, `reset-password-success`, `reset-password-error`, `reset-password-mfa-email-challenge`, `reset-password-mfa-otp-challenge`, `reset-password-mfa-push-challenge-push`, `reset-password-mfa-sms-challenge`, `mfa-detect-browser-capabilities`, `mfa-enroll-result`, `mfa-begin-enroll-options`, `mfa-login-options`, `mfa-country-codes`, `mfa-sms-challenge`, `mfa-sms-enrollment`, `mfa-sms-list`, `mfa-email-challenge`, `mfa-email-list`, `mfa-push-challenge-push`, `mfa-push-enrollment-qr`, `mfa-push-list`, `mfa-push-welcome`, `accept-invitation`, `organization-selection`, `organization-picker`, `mfa-otp-challenge`, `mfa-otp-enrollment-code`, `mfa-otp-enrollment-qr`, `device-code-activation`, `device-code-activation-allowed`, `device-code-activation-denied`, `device-code-confirmation`, `mfa-phone-challenge`, `mfa-phone-enrollment`, `mfa-voice-challenge`, `mfa-voice-enrollment`, `reset-password-mfa-phone-challenge`, `reset-password-mfa-voice-challenge`, `mfa-recovery-code-challenge`, `mfa-recovery-code-enrollment`, `reset-password-mfa-recovery-code-challenge`, `redeem-ticket`.
59+
- `prompt_type` (String) The prompt that you are configuring settings for. Options are: `signup-id`, `signup-password`, `login-id`, `login-password`, `login-passwordless`, `phone-identifier-enrollment`, `phone-identifier-challenge`, `email-identifier-challenge`, `passkeys`, `captcha`, `login`, `signup`, `reset-password`, `mfa`, `mfa-sms`, `mfa-email`, `mfa-push`, `invitation`, `organizations`, `mfa-otp`, `device-flow`, `mfa-phone`, `mfa-voice`, `mfa-recovery-code`, `common`, `consent`, `customized-consent`, `email-otp-challenge`, `email-verification`, `login-email-verification`, `logout`, `mfa-webauthn`, `brute-force-protection`.
60+
- `screen_name` (String) The screen that you are configuring settings for. Options are: `signup-id`, `signup-password`, `login-id`, `login-password`, `login-passwordless-sms-otp`, `login-passwordless-email-code`, `phone-identifier-enrollment`, `phone-identifier-challenge`, `email-identifier-challenge`, `passkey-enrollment`, `passkey-enrollment-local`, `interstitial-captcha`, `login`, `signup`, `reset-password-request`, `reset-password-email`, `reset-password`, `reset-password-success`, `reset-password-error`, `reset-password-mfa-email-challenge`, `reset-password-mfa-otp-challenge`, `reset-password-mfa-push-challenge-push`, `reset-password-mfa-sms-challenge`, `mfa-detect-browser-capabilities`, `mfa-enroll-result`, `mfa-begin-enroll-options`, `mfa-login-options`, `mfa-country-codes`, `mfa-sms-challenge`, `mfa-sms-enrollment`, `mfa-sms-list`, `mfa-email-challenge`, `mfa-email-list`, `mfa-push-challenge-push`, `mfa-push-enrollment-qr`, `mfa-push-list`, `mfa-push-welcome`, `accept-invitation`, `organization-selection`, `organization-picker`, `mfa-otp-challenge`, `mfa-otp-enrollment-code`, `mfa-otp-enrollment-qr`, `device-code-activation`, `device-code-activation-allowed`, `device-code-activation-denied`, `device-code-confirmation`, `mfa-phone-challenge`, `mfa-phone-enrollment`, `mfa-voice-challenge`, `mfa-voice-enrollment`, `reset-password-mfa-phone-challenge`, `reset-password-mfa-voice-challenge`, `mfa-recovery-code-challenge`, `mfa-recovery-code-enrollment`, `reset-password-mfa-recovery-code-challenge`, `redeem-ticket`, `mfa-recovery-code-challenge-new-code`, `consent`, `customized-consent`, `email-otp-challenge`, `email-verification-result`, `login-email-verification`, `logout`, `logout-aborted`, `logout-complete`, `mfa-webauthn-change-key-nickname`, `mfa-webauthn-enrollment-success`, `mfa-webauthn-error`, `mfa-webauthn-not-available-error`, `mfa-webauthn-platform-challenge`, `mfa-webauthn-platform-enrollment`, `mfa-webauthn-roaming-challenge`, `mfa-webauthn-roaming-enrollment`, `reset-password-mfa-webauthn-platform-challenge`, `reset-password-mfa-webauthn-roaming-challenge`, `brute-force-protection-unblock`, `brute-force-protection-unblock-failure`, `brute-force-protection-unblock-success`.
6161

6262
### Optional
6363

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ require (
1414
github.com/hashicorp/terraform-plugin-sdk/v2 v2.36.1
1515
github.com/hashicorp/terraform-plugin-testing v1.12.0
1616
github.com/stretchr/testify v1.10.0
17+
github.com/zalando/go-keyring v0.2.6
1718
gopkg.in/dnaeon/go-vcr.v3 v3.2.0
1819
)
1920

2021
require (
22+
al.essio.dev/pkg/shellescape v1.5.1 // indirect
2123
github.com/BurntSushi/toml v1.4.0 // indirect
2224
github.com/Kunde21/markdownfmt/v3 v3.1.0 // indirect
2325
github.com/Masterminds/goutils v1.1.1 // indirect
@@ -30,10 +32,12 @@ require (
3032
github.com/bgentry/speakeasy v0.1.0 // indirect
3133
github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect
3234
github.com/cloudflare/circl v1.3.8 // indirect
35+
github.com/danieljoos/wincred v1.2.2 // indirect
3336
github.com/davecgh/go-spew v1.1.1 // indirect
3437
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
3538
github.com/fatih/color v1.17.0 // indirect
3639
github.com/goccy/go-json v0.10.5 // indirect
40+
github.com/godbus/dbus/v5 v5.1.0 // indirect
3741
github.com/golang/protobuf v1.5.4 // indirect
3842
github.com/google/uuid v1.6.0 // indirect
3943
github.com/hashicorp/cli v1.1.7 // indirect

go.sum

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXyho=
2+
al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890=
13
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
24
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
35
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
@@ -40,6 +42,8 @@ github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqw
4042
github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
4143
github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
4244
github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
45+
github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0=
46+
github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8=
4347
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4448
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4549
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -67,6 +71,8 @@ github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
6771
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
6872
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
6973
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
74+
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
75+
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
7076
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
7177
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
7278
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -78,6 +84,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
7884
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
7985
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
8086
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
87+
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
88+
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
8189
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
8290
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
8391
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -214,6 +222,8 @@ github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
214222
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
215223
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
216224
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
225+
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
226+
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
217227
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
218228
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
219229
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
@@ -237,6 +247,8 @@ github.com/yuin/goldmark v1.7.7 h1:5m9rrB1sW3JUMToKFQfb+FGt1U7r57IHu5GrYrG2nqU=
237247
github.com/yuin/goldmark v1.7.7/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
238248
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=
239249
github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0=
250+
github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s=
251+
github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI=
240252
github.com/zclconf/go-cty v1.16.2 h1:LAJSwc3v81IRBZyUVQDUdZ7hs3SYs9jv0eZJDWHD/70=
241253
github.com/zclconf/go-cty v1.16.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
242254
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=

internal/auth0/prompt/resource_screen_render.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ var (
4343
string(management.PromptMFAVoice),
4444
string(management.PromptMFARecoveryCode),
4545
string(management.PromptCommon),
46+
string(management.PromptConsent),
47+
string(management.PromptCustomizedConsent),
48+
string(management.PromptEmailOTPChallenge),
49+
string(management.PromptEmailVerification),
50+
string(management.PromptLoginEmailVerification),
51+
string(management.PromptLogout),
52+
string(management.PromptMFAWebAuthn),
53+
"brute-force-protection",
4654
}
4755
allowedScreensSettingsRenderer = []string{
4856
string(management.ScreenSignupID),
@@ -102,6 +110,28 @@ var (
102110
string(management.ScreenMFARecoveryCodeEnrollment),
103111
string(management.ScreenResetPasswordMFARecoveryCodeChallenge),
104112
string(management.ScreenRedeemTicket),
113+
"mfa-recovery-code-challenge-new-code",
114+
string(management.ScreenConsent),
115+
string(management.ScreenCustomizedConsent),
116+
string(management.ScreenEmailOTPChallenge),
117+
string(management.ScreenEmailVerificationResult),
118+
string(management.ScreenLoginEmailVerification),
119+
string(management.ScreenLogout),
120+
string(management.ScreenLogoutAborted),
121+
string(management.ScreenLogoutComplete),
122+
string(management.ScreenMFAWebAuthnChangeKeyNickname),
123+
string(management.ScreenMFAWebAuthnEnrollmentSuccess),
124+
string(management.ScreenMFAWebAuthnError),
125+
string(management.ScreenMFAWebAuthnNotAvailableError),
126+
string(management.ScreenMFAWebAuthnPlatformChallenge),
127+
string(management.ScreenMFAWebAuthnPlatformEnrollment),
128+
string(management.ScreenMFAWebAuthnRoamingChallenge),
129+
string(management.ScreenMFAWebAuthnRoamingEnrollment),
130+
string(management.ScreenResetPasswordMFAWebAuthnPlatformChallenge),
131+
string(management.ScreenResetPasswordMFAWebAuthnRoamingChallenge),
132+
"brute-force-protection-unblock",
133+
"brute-force-protection-unblock-failure",
134+
"brute-force-protection-unblock-success",
105135
}
106136

107137
supportedRenderingModes = []string{string(management.RenderingModeStandard), string(management.RenderingModeAdvanced)}

internal/config/config.go

Lines changed: 140 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ import (
44
"context"
55
"crypto/tls"
66
"crypto/x509"
7+
"encoding/base64"
8+
"encoding/json"
9+
"errors"
710
"fmt"
811
"net/http"
912
"net/url"
1013
"regexp"
1114
"strconv"
15+
"strings"
1216
"time"
1317

1418
"github.com/PuerkitoBio/rehttp"
@@ -17,11 +21,17 @@ import (
1721
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1822
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1923
"github.com/hashicorp/terraform-plugin-sdk/v2/meta"
24+
"github.com/zalando/go-keyring"
2025

2126
"github.com/auth0/terraform-provider-auth0/internal/mutex"
2227
)
2328

24-
const providerName = "Terraform-Provider-Auth0" // #nosec G101
29+
const providerName = "Terraform-Provider-Auth0" // #nosec G101
30+
const secretAccessToken = "Auth0 CLI Access Token" // #nosec G101
31+
32+
// Access tokens have no size limit, but should be smaller than (50*2048) bytes.
33+
// The max number of loops safeguards against infinite loops, however unlikely.
34+
const secretAccessTokenMaxChunks = 50
2535

2636
var version = "dev"
2737

@@ -55,23 +65,92 @@ func (c *Config) GetMutex() *mutex.KeyValue {
5565
// and passed into the subsequent resources as the meta parameter.
5666
func ConfigureProvider(terraformVersion *string) schema.ConfigureContextFunc {
5767
return func(_ context.Context, data *schema.ResourceData) (interface{}, diag.Diagnostics) {
68+
var apiToken string
5869
domain := data.Get("domain").(string)
5970
clientID := data.Get("client_id").(string)
6071
clientSecret := data.Get("client_secret").(string)
61-
apiToken := data.Get("api_token").(string)
72+
apiToken = data.Get("api_token").(string)
6273
audience := data.Get("audience").(string)
6374
debug := data.Get("debug").(bool)
6475
dynamicCredentials := data.Get("dynamic_credentials").(bool)
76+
cliLogin := data.Get("cli_login").(bool)
77+
78+
switch {
79+
case dynamicCredentials:
80+
if domain == "" {
81+
return nil, diag.Diagnostics{{
82+
Severity: diag.Error,
83+
Summary: "Missing required configuration",
84+
Detail: "The 'AUTH0_DOMAIN' must be specified along with the 'AUTH0_DYNAMIC_CREDENTIALS'.",
85+
}}
86+
}
87+
case cliLogin:
88+
// Ensure domain is present.
89+
if domain == "" {
90+
return nil, diag.Diagnostics{{
91+
Severity: diag.Error,
92+
Summary: "Missing required configuration",
93+
Detail: "The 'AUTH0_DOMAIN' must be specified along with the 'AUTH0_CLI_LOGIN'.",
94+
}}
95+
}
96+
97+
// Check for tempToken when cliLogin is enabled.
98+
var tempToken string
99+
for i := 0; i < secretAccessTokenMaxChunks; i++ {
100+
a, err := keyring.Get(fmt.Sprintf("%s %d", secretAccessToken, i), domain)
101+
if errors.Is(err, keyring.ErrNotFound) || err != nil {
102+
break
103+
}
104+
tempToken += a
105+
}
106+
107+
if tempToken == "" {
108+
return nil, diag.Diagnostics{{
109+
Severity: diag.Error,
110+
Summary: "Authentication required",
111+
Detail: "No CLI token found. Please log in using 'auth0 login' via auth0-cli or disable 'AUTH0_CLI_LOGIN'.",
112+
}}
113+
}
65114

66-
if !dynamicCredentials && apiToken == "" && (clientID == "" || clientSecret == "" || domain == "") {
67-
return nil, diag.Diagnostics{
68-
{
115+
// Check if the token is expired.
116+
if err := validateTokenExpiry(tempToken); err != nil {
117+
return nil, diag.Diagnostics{{
69118
Severity: diag.Error,
70-
Summary: "Missing environment variables",
71-
Detail: fmt.Sprintf("Either AUTH0_API_TOKEN or AUTH0_DOMAIN:AUTH0_CLIENT_ID:AUTH0_CLIENT_SECRET must be configured. " +
72-
"Ref: https://registry.terraform.io/providers/auth0/auth0/latest/docs"),
73-
},
119+
Summary: "Token validation failed",
120+
Detail: err.Error(),
121+
}}
74122
}
123+
124+
// Set the apiToken to the tempToken.
125+
apiToken = tempToken
126+
127+
case apiToken != "":
128+
// Ensure domain is present.
129+
if domain == "" {
130+
return nil, diag.Diagnostics{{
131+
Severity: diag.Error,
132+
Summary: "Missing required configuration",
133+
Detail: "The 'AUTH0_DOMAIN' must be specified along with the 'AUTH0_API_TOKEN'.",
134+
}}
135+
}
136+
137+
case clientID != "" && clientSecret != "":
138+
// Ensure domain is present.
139+
if domain == "" {
140+
return nil, diag.Diagnostics{{
141+
Severity: diag.Error,
142+
Summary: "Missing required configuration",
143+
Detail: "The 'AUTH0_DOMAIN' must be specified.",
144+
}}
145+
}
146+
147+
default:
148+
return nil, diag.Diagnostics{{
149+
Severity: diag.Error,
150+
Summary: "Missing environment variables",
151+
Detail: "AUTH0_DOMAIN is required. Then, configure either AUTH0_API_TOKEN, " +
152+
"or both AUTH0_CLIENT_ID and AUTH0_CLIENT_SECRET. Or enable CLI login with AUTH0_CLI_LOGIN=true",
153+
}}
75154
}
76155

77156
apiClient, err := management.New(domain,
@@ -82,6 +161,7 @@ func ConfigureProvider(terraformVersion *string) schema.ConfigureContextFunc {
82161
management.WithNoRetries(),
83162
management.WithClient(customClientWithRetries()),
84163
)
164+
85165
if err != nil {
86166
return nil, diag.FromErr(err)
87167
}
@@ -90,6 +170,57 @@ func ConfigureProvider(terraformVersion *string) schema.ConfigureContextFunc {
90170
}
91171
}
92172

173+
func decodeSegment(seg string) ([]byte, error) {
174+
// Add padding if necessary.
175+
if l := len(seg) % 4; l > 0 {
176+
seg += strings.Repeat("=", 4-l)
177+
}
178+
return base64.URLEncoding.DecodeString(seg)
179+
}
180+
181+
func decodeJWT(token string) (map[string]interface{}, map[string]interface{}, error) {
182+
parts := strings.Split(token, ".")
183+
if len(parts) != 3 {
184+
return nil, nil, fmt.Errorf("invalid JWT format")
185+
}
186+
187+
headerBytes, err := decodeSegment(parts[0])
188+
if err != nil {
189+
return nil, nil, fmt.Errorf("error decoding header: %w", err)
190+
}
191+
payloadBytes, err := decodeSegment(parts[1])
192+
if err != nil {
193+
return nil, nil, fmt.Errorf("error decoding payload: %w", err)
194+
}
195+
196+
var header, payload map[string]interface{}
197+
if err := json.Unmarshal(headerBytes, &header); err != nil {
198+
return nil, nil, fmt.Errorf("error unmarshalling header: %w", err)
199+
}
200+
if err := json.Unmarshal(payloadBytes, &payload); err != nil {
201+
return nil, nil, fmt.Errorf("error unmarshalling payload: %w", err)
202+
}
203+
204+
return header, payload, nil
205+
}
206+
207+
func validateTokenExpiry(tokenString string) error {
208+
_, payload, err := decodeJWT(tokenString)
209+
if err != nil {
210+
return err
211+
}
212+
213+
if exp, ok := payload["exp"].(float64); ok {
214+
if time.Now().Unix() > int64(exp) {
215+
return fmt.Errorf("expired token: the stored auth0-cli token has expired. Please log in again")
216+
}
217+
} else {
218+
return fmt.Errorf("missing expiration: the token does not contain an expiration claim")
219+
}
220+
221+
return nil
222+
}
223+
93224
// userAgent computes the desired User-Agent header for the *management.Management client.
94225
func userAgent(terraformVersion *string) string {
95226
sdkVersion := auth0.Version

0 commit comments

Comments
 (0)