From 6e448795db4761fb8a2bb52287146145ea9a74fd Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Mon, 18 May 2026 17:49:55 +0530 Subject: [PATCH 01/11] feat(apps): add support for third-party security mode and redirection policy - Introduced new flags for third-party applications: - `third-party-security-mode` to specify 'strict' or 'permissive'. - `redirection-policy` to control Auth0's behavior on authentication errors. - Updated `createAppCmd` and `updateAppCmd` functions to handle new inputs. - Enhanced `applicationView` to display third-party security mode and redirection policy. - Ensured backward compatibility by integrating new features without affecting existing functionality. --- internal/cli/apps.go | 84 ++++++++++++++++++++++++++++++---------- internal/display/apps.go | 12 ++++++ 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/internal/cli/apps.go b/internal/cli/apps.go index f7ffc716c..3b7f108dc 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -176,6 +176,18 @@ var ( ShortForm: "p", Help: "Comma-separated list of enabled token exchange types for this client. Possible values: custom_authentication, on_behalf_of_token_exchange.", } + appThirdPartySecurityMode = Flag{ + Name: "Third Party Security Mode", + LongForm: "third-party-security-mode", + ShortForm: "s", + Help: "Security mode for third-party clients: 'strict' or 'permissive'.", + } + appRedirectionPolicy = Flag{ + Name: "Redirection Policy", + LongForm: "redirection-policy", + ShortForm: "y", + Help: "Controls whether Auth0 redirects users to the application's callback URL on authentication errors or in email verification flows: 'allow_always' or 'open_redirect_protection'.", + } ) func appsCmd(cli *cli) *cobra.Command { @@ -434,6 +446,8 @@ func createAppCmd(cli *cli) *cobra.Command { RefreshToken string ResourceServerIdentifier string AllowAnyProfileOfType []string + ThirdPartySecurityMode string + RedirectionPolicy string } var oidcConformant = true var algorithm = "RS256" @@ -456,7 +470,8 @@ func createAppCmd(cli *cli) *cobra.Command { auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json --metadata "foo=bar" --metadata "bazz=buzz" auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json --metadata "foo=bar,bazz=buzz" auth0 apps create --name "My API Client" --type resource_server --resource-server-identifier "https://api.example.com" - auth0 apps create --name myapp --type resource_server --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange`, + auth0 apps create --name myapp --type resource_server --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange + auth0 apps create --name "My 3P App" --type regular --third-party-security-mode strict --redirection-policy open_redirect_protection`, RunE: func(cmd *cobra.Command, args []string) error { if err := appName.Ask(cmd, &inputs.Name, nil); err != nil { return err @@ -474,6 +489,7 @@ func createAppCmd(cli *cli) *cobra.Command { appIsNative := apiTypeFor(inputs.Type) == appTypeNative appIsSPA := apiTypeFor(inputs.Type) == appTypeSPA appIsResourceServer := apiTypeFor(inputs.Type) == appTypeResourceServer + isThirdPartyApp := inputs.ThirdPartySecurityMode != "" || inputs.RedirectionPolicy != "" // Prompt for callback URLs if app is not m2m and not resource_server. if !appIsM2M && !appIsResourceServer { @@ -488,8 +504,8 @@ func createAppCmd(cli *cli) *cobra.Command { } } - // Prompt for logout URLs if app is not m2m and not resource_server. - if !appIsM2M && !appIsResourceServer { + // Prompt for logout URLs if app is not m2m and not resource_server and not a third-party app. + if !appIsM2M && !appIsResourceServer && !isThirdPartyApp { var defaultValue string if !appIsNative { @@ -593,11 +609,21 @@ func createAppCmd(cli *cli) *cobra.Command { a.TokenEndpointAuthMethod = apiAuthMethodFor(inputs.AuthMethod) } + if inputs.ThirdPartySecurityMode != "" { + a.ThirdPartySecurityMode = &inputs.ThirdPartySecurityMode + } + if inputs.RedirectionPolicy != "" { + a.RedirectionPolicy = &inputs.RedirectionPolicy + } + if isThirdPartyApp { + a.IsFirstParty = auth0.Bool(false) + } + // Set grants. - if len(inputs.Grants) == 0 { - a.GrantTypes = apiDefaultGrantsFor(inputs.Type) - } else { + if len(inputs.Grants) > 0 { a.GrantTypes = apiGrantsFor(inputs.Grants) + } else if !isThirdPartyApp { + a.GrantTypes = apiDefaultGrantsFor(inputs.Type) } // Create app. @@ -633,26 +659,30 @@ func createAppCmd(cli *cli) *cobra.Command { appTEAllowAnyProfileOfType.RegisterStringSlice(cmd, &inputs.AllowAnyProfileOfType, nil) revealSecrets.RegisterBool(cmd, &inputs.RevealSecrets, false) refreshToken.RegisterString(cmd, &inputs.RefreshToken, "") + appThirdPartySecurityMode.RegisterString(cmd, &inputs.ThirdPartySecurityMode, "") + appRedirectionPolicy.RegisterString(cmd, &inputs.RedirectionPolicy, "") return cmd } func updateAppCmd(cli *cli) *cobra.Command { var inputs struct { - ID string - Name string - Type string - Description string - Callbacks []string - AllowedOrigins []string - AllowedWebOrigins []string - AllowedLogoutURLs []string - AuthMethod string - Grants []string - RevealSecrets bool - Metadata map[string]string - RefreshToken string - AllowAnyProfileOfType []string + ID string + Name string + Type string + Description string + Callbacks []string + AllowedOrigins []string + AllowedWebOrigins []string + AllowedLogoutURLs []string + AuthMethod string + Grants []string + RevealSecrets bool + Metadata map[string]string + RefreshToken string + AllowAnyProfileOfType []string + ThirdPartySecurityMode string + RedirectionPolicy string } cmd := &cobra.Command{ @@ -673,7 +703,9 @@ func updateAppCmd(cli *cli) *cobra.Command { auth0 apps update -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" auth0 apps update -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" --metadata "bazz=buzz" auth0 apps update -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar,bazz=buzz" - auth0 apps update --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange`, + auth0 apps update --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange + auth0 apps update --redirection-policy allow_always + auth0 apps update --third-party-security-mode strict --redirection-policy open_redirect_protection`, RunE: func(cmd *cobra.Command, args []string) error { var current *management.Client @@ -847,6 +879,14 @@ func updateAppCmd(cli *cli) *cobra.Command { } } + if appThirdPartySecurityMode.IsSet(cmd) { + a.ThirdPartySecurityMode = &inputs.ThirdPartySecurityMode + } + + if appRedirectionPolicy.IsSet(cmd) { + a.RedirectionPolicy = &inputs.RedirectionPolicy + } + if err := ansi.Waiting(func() error { return cli.api.Client.Update(cmd.Context(), inputs.ID, a) }); err != nil { @@ -874,6 +914,8 @@ func updateAppCmd(cli *cli) *cobra.Command { appTEAllowAnyProfileOfType.RegisterStringSliceU(cmd, &inputs.AllowAnyProfileOfType, nil) revealSecrets.RegisterBool(cmd, &inputs.RevealSecrets, false) refreshToken.RegisterString(cmd, &inputs.RefreshToken, "") + appThirdPartySecurityMode.RegisterStringU(cmd, &inputs.ThirdPartySecurityMode, "") + appRedirectionPolicy.RegisterStringU(cmd, &inputs.RedirectionPolicy, "") return cmd } diff --git a/internal/display/apps.go b/internal/display/apps.go index 853468834..bbcf7c1dd 100644 --- a/internal/display/apps.go +++ b/internal/display/apps.go @@ -40,6 +40,8 @@ type applicationView struct { RefreshToken string ResourceServerIdentifier string AllowAnyProfileOfType []string + ThirdPartySecurityMode string + RedirectionPolicy string revealSecret bool raw interface{} @@ -128,6 +130,14 @@ func (v *applicationView) KeyValues() [][]string { keyValues = append(keyValues, []string{"TOKEN EXCHANGE TYPES", strings.Join(v.AllowAnyProfileOfType, ", ")}) } + if v.ThirdPartySecurityMode != "" { + keyValues = append(keyValues, []string{"THIRD PARTY SECURITY MODE", v.ThirdPartySecurityMode}) + } + + if v.RedirectionPolicy != "" { + keyValues = append(keyValues, []string{"REDIRECTION POLICY", v.RedirectionPolicy}) + } + return keyValues } @@ -213,6 +223,8 @@ func makeApplicationView(client *management.Client, revealSecrets bool) *applica Metadata: mapPointerToArray(client.ClientMetadata), ResourceServerIdentifier: client.GetResourceServerIdentifier(), AllowAnyProfileOfType: client.GetTokenExchange().GetAllowAnyProfileOfType(), + ThirdPartySecurityMode: client.GetThirdPartySecurityMode(), + RedirectionPolicy: client.GetRedirectionPolicy(), raw: client, RefreshToken: string(jsonRefreshToken), } From 2a3eda6270bb07299cb4c9633d9fdbaadd096a0c Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Mon, 18 May 2026 17:59:18 +0530 Subject: [PATCH 02/11] feat(cli): enhance client grant resource fetching with default_for support - Updated the FetchData method in clientGrantResourceFetcher to handle grants marked as default_for, allowing for more accurate resource naming. - Introduced a new test case to validate the handling of default_for grants in TestClientGrantResourceFetcher_FetchData, ensuring expected behavior when fetching client grants with different audiences. --- internal/cli/terraform_fetcher.go | 8 +++- internal/cli/terraform_fetcher_test.go | 61 ++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/internal/cli/terraform_fetcher.go b/internal/cli/terraform_fetcher.go index d0106905c..d3df097c5 100644 --- a/internal/cli/terraform_fetcher.go +++ b/internal/cli/terraform_fetcher.go @@ -274,8 +274,14 @@ func (f *clientGrantResourceFetcher) FetchData(ctx context.Context) (importDataL } for _, grant := range grants.ClientGrants { + var resourceName string + if grant.GetDefaultFor() != "" { + resourceName = "auth0_client_grant." + sanitizeResourceName("default_for_"+grant.GetDefaultFor()+"_"+grant.GetAudience()) + } else { + resourceName = "auth0_client_grant." + sanitizeResourceName(grant.GetClientID()+"_"+grant.GetAudience()) + } data = append(data, importDataItem{ - ResourceName: "auth0_client_grant." + sanitizeResourceName(grant.GetClientID()+"_"+grant.GetAudience()), + ResourceName: resourceName, ImportID: grant.GetID(), }) } diff --git a/internal/cli/terraform_fetcher_test.go b/internal/cli/terraform_fetcher_test.go index 4cf7c7d72..b733dd1be 100644 --- a/internal/cli/terraform_fetcher_test.go +++ b/internal/cli/terraform_fetcher_test.go @@ -723,6 +723,67 @@ func TestClientGrantResourceFetcher_FetchData(t *testing.T) { _, err := fetcher.FetchData(context.Background()) assert.EqualError(t, err, "failed to list clients") }) + + t.Run("it handles default_for grants correctly", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + clientGrantAPI := mock.NewMockClientGrantAPI(ctrl) + clientGrantAPI.EXPECT(). + List(gomock.Any(), gomock.Any()). + Return( + &management.ClientGrantList{ + List: management.List{ + Start: 0, + Limit: 3, + Total: 3, + }, + ClientGrants: []*management.ClientGrant{ + { + ID: auth0.String("cgr_1"), + ClientID: auth0.String("client-id-1"), + Audience: auth0.String("https://travel0.com/api"), + }, + { + ID: auth0.String("cgr_2"), + DefaultFor: auth0.String("third_party_clients"), + Audience: auth0.String("https://travel0.com/api"), + }, + { + ID: auth0.String("cgr_3"), + DefaultFor: auth0.String("third_party_clients"), + Audience: auth0.String("https://partner-api.example.com"), + }, + }, + }, + nil, + ) + + fetcher := clientGrantResourceFetcher{ + api: &auth0.API{ + ClientGrant: clientGrantAPI, + }, + } + + expectedData := importDataList{ + { + ResourceName: "auth0_client_grant.client_id_1_https_travel0_com_api", + ImportID: "cgr_1", + }, + { + ResourceName: "auth0_client_grant.default_for_third_party_clients_https_travel0_com_api", + ImportID: "cgr_2", + }, + { + ResourceName: "auth0_client_grant.default_for_third_party_clients_https_partner_api_example_com", + ImportID: "cgr_3", + }, + } + + data, err := fetcher.FetchData(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, data) + }) } func TestConnectionResourceFetcher_FetchData(t *testing.T) { From ca3caf439fad16846ad05574b6104fc55f7a6496 Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Mon, 18 May 2026 18:00:32 +0530 Subject: [PATCH 03/11] feat(docs): update application creation and update examples with new flags - Added examples for `auth0 apps create` and `auth0 apps update` commands to demonstrate the usage of `--third-party-security-mode` and `--redirection-policy` flags. - Updated documentation to reflect the new security features for third-party applications, enhancing clarity for users. --- docs/auth0_apps_create.md | 3 +++ docs/auth0_apps_update.md | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/docs/auth0_apps_create.md b/docs/auth0_apps_create.md index 011038122..a6cb7ed37 100644 --- a/docs/auth0_apps_create.md +++ b/docs/auth0_apps_create.md @@ -31,6 +31,7 @@ auth0 apps create [flags] auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json --metadata "foo=bar,bazz=buzz" auth0 apps create --name "My API Client" --type resource_server --resource-server-identifier "https://api.example.com" auth0 apps create --name myapp --type resource_server --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange + auth0 apps create --name "My 3P App" --type regular --third-party-security-mode strict --redirection-policy open_redirect_protection ``` @@ -48,9 +49,11 @@ auth0 apps create [flags] --metadata stringToString Arbitrary keys-value pairs (max 255 characters each), that can be assigned to each application. More about application metadata: https://auth0.com/docs/get-started/applications/configure-application-metadata (default []) -n, --name string Name of the application. -o, --origins strings Comma-separated list of URLs allowed to make requests from JavaScript to Auth0 API (typically used with CORS). By default, all your callback URLs will be allowed. This field allows you to enter other origins if necessary. You can also use wildcards at the subdomain level (e.g., https://*.contoso.com). Query strings and hash information are not taken into account when validating these URLs. + -y, --redirection-policy string Controls whether Auth0 redirects users to the application's callback URL on authentication errors or in email verification flows: 'allow_always' or 'open_redirect_protection'. -z, --refresh-token string Refresh Token Config for the application, formatted as JSON. --resource-server-identifier string The identifier of the resource server that this client is associated with. This property can only be sent when app_type=resource_server and cannot be changed once the client is created. -r, --reveal-secrets Display the application secrets ('signing_keys', 'client_secret') as part of the command output. + -s, --third-party-security-mode string Security mode for third-party clients: 'strict' or 'permissive'. -t, --type string Type of application: - native: mobile, desktop, CLI and smart device apps running natively. - spa (single page application): a JavaScript front-end app that uses an API. diff --git a/docs/auth0_apps_update.md b/docs/auth0_apps_update.md index b9b5fdd23..5429c8606 100644 --- a/docs/auth0_apps_update.md +++ b/docs/auth0_apps_update.md @@ -30,6 +30,8 @@ auth0 apps update [flags] auth0 apps update -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" --metadata "bazz=buzz" auth0 apps update -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar,bazz=buzz" auth0 apps update --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange + auth0 apps update --redirection-policy allow_always + auth0 apps update --third-party-security-mode strict --redirection-policy open_redirect_protection ``` @@ -47,8 +49,10 @@ auth0 apps update [flags] --metadata stringToString Arbitrary keys-value pairs (max 255 characters each), that can be assigned to each application. More about application metadata: https://auth0.com/docs/get-started/applications/configure-application-metadata (default []) -n, --name string Name of the application. -o, --origins strings Comma-separated list of URLs allowed to make requests from JavaScript to Auth0 API (typically used with CORS). By default, all your callback URLs will be allowed. This field allows you to enter other origins if necessary. You can also use wildcards at the subdomain level (e.g., https://*.contoso.com). Query strings and hash information are not taken into account when validating these URLs. + -y, --redirection-policy string Controls whether Auth0 redirects users to the application's callback URL on authentication errors or in email verification flows: 'allow_always' or 'open_redirect_protection'. -z, --refresh-token string Refresh Token Config for the application, formatted as JSON. -r, --reveal-secrets Display the application secrets ('signing_keys', 'client_secret') as part of the command output. + -s, --third-party-security-mode string Security mode for third-party clients: 'strict' or 'permissive'. -t, --type string Type of application: - native: mobile, desktop, CLI and smart device apps running natively. - spa (single page application): a JavaScript front-end app that uses an API. From f48d204c1dbe3a0489ab206ed273bb6177823ada Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Mon, 18 May 2026 18:03:33 +0530 Subject: [PATCH 04/11] test(apps): add test case for creating regular app with third-party security mode - Added a new test case to validate the creation of a regular app with third-party security mode set to strict and redirection policy set to open_redirect_protection. - The test ensures that the app is created successfully and outputs the expected JSON response. --- test/integration/apps-test-cases.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/integration/apps-test-cases.yaml b/test/integration/apps-test-cases.yaml index cc88d9c0b..c79912521 100644 --- a/test/integration/apps-test-cases.yaml +++ b/test/integration/apps-test-cases.yaml @@ -376,3 +376,13 @@ tests: 050 - given a resource server app, it successfully deletes the app: command: auth0 apps delete $(./test/integration/scripts/get-resource-server-app-id.sh) --force exit-code: 0 + + 051 - it successfully creates a regular app with third-party-security-mode and redirection-policy and outputs in json: + command: auth0 apps create --name integration-test-app-3p-strict --type regular --description 3PApp1 --third-party-security-mode strict --redirection-policy open_redirect_protection --json + exit-code: 0 + stdout: + json: + name: integration-test-app-3p-strict + app_type: regular_web + third_party_security_mode: strict + redirection_policy: open_redirect_protection From 985b0fe78d0647eacef8e10acc155f129776df74 Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Mon, 18 May 2026 18:12:03 +0530 Subject: [PATCH 05/11] chore(terraform): lint fix --- internal/cli/terraform_fetcher_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/cli/terraform_fetcher_test.go b/internal/cli/terraform_fetcher_test.go index b733dd1be..e7fc03f92 100644 --- a/internal/cli/terraform_fetcher_test.go +++ b/internal/cli/terraform_fetcher_test.go @@ -745,14 +745,14 @@ func TestClientGrantResourceFetcher_FetchData(t *testing.T) { Audience: auth0.String("https://travel0.com/api"), }, { - ID: auth0.String("cgr_2"), + ID: auth0.String("cgr_2"), DefaultFor: auth0.String("third_party_clients"), - Audience: auth0.String("https://travel0.com/api"), + Audience: auth0.String("https://travel0.com/api"), }, { - ID: auth0.String("cgr_3"), + ID: auth0.String("cgr_3"), DefaultFor: auth0.String("third_party_clients"), - Audience: auth0.String("https://partner-api.example.com"), + Audience: auth0.String("https://partner-api.example.com"), }, }, }, From 1688e91e9adcbcdd9ff09c8ec2841424ec4213f4 Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Wed, 20 May 2026 18:46:25 +0530 Subject: [PATCH 06/11] feat(apps): add is-first-party flag for application creation and update - Introduced a new flag `--is-first-party` to differentiate between first-party and third-party applications. - Updated the command examples in `auth0_apps_create.md` and `auth0_apps_update.md` to reflect the new flag usage. - Modified the `createAppCmd` and `updateAppCmd` functions in `apps.go` to handle the new flag. - Enhanced the `applicationView` struct in `display/apps.go` to include the `IsFirstParty` field for display purposes. --- docs/auth0_apps_create.md | 3 ++- docs/auth0_apps_update.md | 2 +- internal/cli/apps.go | 30 +++++++++++++++++++++++------- internal/display/apps.go | 6 ++++++ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/docs/auth0_apps_create.md b/docs/auth0_apps_create.md index a6cb7ed37..5bdebd473 100644 --- a/docs/auth0_apps_create.md +++ b/docs/auth0_apps_create.md @@ -31,7 +31,7 @@ auth0 apps create [flags] auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json --metadata "foo=bar,bazz=buzz" auth0 apps create --name "My API Client" --type resource_server --resource-server-identifier "https://api.example.com" auth0 apps create --name myapp --type resource_server --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange - auth0 apps create --name "My 3P App" --type regular --third-party-security-mode strict --redirection-policy open_redirect_protection + auth0 apps create --name "My 3P App" --type regular --is-first-party=false --third-party-security-mode strict --redirection-policy open_redirect_protection ``` @@ -43,6 +43,7 @@ auth0 apps create [flags] -c, --callbacks strings After the user authenticates we will only call back to any of these URLs. You can specify multiple valid URLs by comma-separating them (typically to handle different environments like QA or testing). Make sure to specify the protocol (https://) otherwise the callback may fail in some cases. With the exception of custom URI schemes for native apps, all callbacks should use protocol https://. -d, --description string Description of the application. Max character count is 140. -g, --grants strings List of grant types supported for this application. Can include code, implicit, refresh-token, credentials, password, password-realm, mfa-oob, mfa-otp, mfa-recovery-code, and device-code. + -f, --is-first-party Whether the application is a first-party client (true) or third-party client (false). (default true) --json Output in json format. --json-compact Output in compact json format. -l, --logout-urls strings Comma-separated list of URLs that are valid to redirect to after logout from Auth0. Wildcards are allowed for subdomains. diff --git a/docs/auth0_apps_update.md b/docs/auth0_apps_update.md index 5429c8606..8ac4cd615 100644 --- a/docs/auth0_apps_update.md +++ b/docs/auth0_apps_update.md @@ -31,7 +31,6 @@ auth0 apps update [flags] auth0 apps update -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar,bazz=buzz" auth0 apps update --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange auth0 apps update --redirection-policy allow_always - auth0 apps update --third-party-security-mode strict --redirection-policy open_redirect_protection ``` @@ -43,6 +42,7 @@ auth0 apps update [flags] -c, --callbacks strings After the user authenticates we will only call back to any of these URLs. You can specify multiple valid URLs by comma-separating them (typically to handle different environments like QA or testing). Make sure to specify the protocol (https://) otherwise the callback may fail in some cases. With the exception of custom URI schemes for native apps, all callbacks should use protocol https://. -d, --description string Description of the application. Max character count is 140. -g, --grants strings List of grant types supported for this application. Can include code, implicit, refresh-token, credentials, password, password-realm, mfa-oob, mfa-otp, mfa-recovery-code, and device-code. + -f, --is-first-party Whether the application is a first-party client (true) or third-party client (false). (default true) --json Output in json format. --json-compact Output in compact json format. -l, --logout-urls strings Comma-separated list of URLs that are valid to redirect to after logout from Auth0. Wildcards are allowed for subdomains. diff --git a/internal/cli/apps.go b/internal/cli/apps.go index 3b7f108dc..fcdf69d1a 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -176,6 +176,12 @@ var ( ShortForm: "p", Help: "Comma-separated list of enabled token exchange types for this client. Possible values: custom_authentication, on_behalf_of_token_exchange.", } + appIsFirstParty = Flag{ + Name: "Is First Party", + LongForm: "is-first-party", + ShortForm: "f", + Help: "Whether the application is a first-party client (true) or third-party client (false).", + } appThirdPartySecurityMode = Flag{ Name: "Third Party Security Mode", LongForm: "third-party-security-mode", @@ -446,6 +452,7 @@ func createAppCmd(cli *cli) *cobra.Command { RefreshToken string ResourceServerIdentifier string AllowAnyProfileOfType []string + IsFirstParty bool ThirdPartySecurityMode string RedirectionPolicy string } @@ -471,7 +478,7 @@ func createAppCmd(cli *cli) *cobra.Command { auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json --metadata "foo=bar,bazz=buzz" auth0 apps create --name "My API Client" --type resource_server --resource-server-identifier "https://api.example.com" auth0 apps create --name myapp --type resource_server --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange - auth0 apps create --name "My 3P App" --type regular --third-party-security-mode strict --redirection-policy open_redirect_protection`, + auth0 apps create --name "My 3P App" --type regular --is-first-party=false --third-party-security-mode strict --redirection-policy open_redirect_protection`, RunE: func(cmd *cobra.Command, args []string) error { if err := appName.Ask(cmd, &inputs.Name, nil); err != nil { return err @@ -489,7 +496,9 @@ func createAppCmd(cli *cli) *cobra.Command { appIsNative := apiTypeFor(inputs.Type) == appTypeNative appIsSPA := apiTypeFor(inputs.Type) == appTypeSPA appIsResourceServer := apiTypeFor(inputs.Type) == appTypeResourceServer - isThirdPartyApp := inputs.ThirdPartySecurityMode != "" || inputs.RedirectionPolicy != "" + + // IsFirstParty flag is explisitly set to false + isThirdPartyApp := appIsFirstParty.IsSet(cmd) && !inputs.IsFirstParty // Prompt for callback URLs if app is not m2m and not resource_server. if !appIsM2M && !appIsResourceServer { @@ -609,15 +618,16 @@ func createAppCmd(cli *cli) *cobra.Command { a.TokenEndpointAuthMethod = apiAuthMethodFor(inputs.AuthMethod) } + // Set first and third party fields. + if appIsFirstParty.IsSet(cmd) { + a.IsFirstParty = auth0.Bool(inputs.IsFirstParty) + } if inputs.ThirdPartySecurityMode != "" { a.ThirdPartySecurityMode = &inputs.ThirdPartySecurityMode } if inputs.RedirectionPolicy != "" { a.RedirectionPolicy = &inputs.RedirectionPolicy } - if isThirdPartyApp { - a.IsFirstParty = auth0.Bool(false) - } // Set grants. if len(inputs.Grants) > 0 { @@ -659,6 +669,7 @@ func createAppCmd(cli *cli) *cobra.Command { appTEAllowAnyProfileOfType.RegisterStringSlice(cmd, &inputs.AllowAnyProfileOfType, nil) revealSecrets.RegisterBool(cmd, &inputs.RevealSecrets, false) refreshToken.RegisterString(cmd, &inputs.RefreshToken, "") + appIsFirstParty.RegisterBool(cmd, &inputs.IsFirstParty, true) appThirdPartySecurityMode.RegisterString(cmd, &inputs.ThirdPartySecurityMode, "") appRedirectionPolicy.RegisterString(cmd, &inputs.RedirectionPolicy, "") @@ -681,6 +692,7 @@ func updateAppCmd(cli *cli) *cobra.Command { Metadata map[string]string RefreshToken string AllowAnyProfileOfType []string + IsFirstParty bool ThirdPartySecurityMode string RedirectionPolicy string } @@ -704,8 +716,7 @@ func updateAppCmd(cli *cli) *cobra.Command { auth0 apps update -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" --metadata "bazz=buzz" auth0 apps update -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar,bazz=buzz" auth0 apps update --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange - auth0 apps update --redirection-policy allow_always - auth0 apps update --third-party-security-mode strict --redirection-policy open_redirect_protection`, + auth0 apps update --redirection-policy allow_always`, RunE: func(cmd *cobra.Command, args []string) error { var current *management.Client @@ -879,6 +890,10 @@ func updateAppCmd(cli *cli) *cobra.Command { } } + if appIsFirstParty.IsSet(cmd) { + a.IsFirstParty = auth0.Bool(inputs.IsFirstParty) + } + if appThirdPartySecurityMode.IsSet(cmd) { a.ThirdPartySecurityMode = &inputs.ThirdPartySecurityMode } @@ -914,6 +929,7 @@ func updateAppCmd(cli *cli) *cobra.Command { appTEAllowAnyProfileOfType.RegisterStringSliceU(cmd, &inputs.AllowAnyProfileOfType, nil) revealSecrets.RegisterBool(cmd, &inputs.RevealSecrets, false) refreshToken.RegisterString(cmd, &inputs.RefreshToken, "") + appIsFirstParty.RegisterBoolU(cmd, &inputs.IsFirstParty, true) appThirdPartySecurityMode.RegisterStringU(cmd, &inputs.ThirdPartySecurityMode, "") appRedirectionPolicy.RegisterStringU(cmd, &inputs.RedirectionPolicy, "") diff --git a/internal/display/apps.go b/internal/display/apps.go index bbcf7c1dd..8049a3a54 100644 --- a/internal/display/apps.go +++ b/internal/display/apps.go @@ -40,6 +40,7 @@ type applicationView struct { RefreshToken string ResourceServerIdentifier string AllowAnyProfileOfType []string + IsFirstParty *bool ThirdPartySecurityMode string RedirectionPolicy string revealSecret bool @@ -130,6 +131,10 @@ func (v *applicationView) KeyValues() [][]string { keyValues = append(keyValues, []string{"TOKEN EXCHANGE TYPES", strings.Join(v.AllowAnyProfileOfType, ", ")}) } + if v.IsFirstParty != nil { + keyValues = append(keyValues, []string{"IS FIRST PARTY", boolean(*v.IsFirstParty)}) + } + if v.ThirdPartySecurityMode != "" { keyValues = append(keyValues, []string{"THIRD PARTY SECURITY MODE", v.ThirdPartySecurityMode}) } @@ -223,6 +228,7 @@ func makeApplicationView(client *management.Client, revealSecrets bool) *applica Metadata: mapPointerToArray(client.ClientMetadata), ResourceServerIdentifier: client.GetResourceServerIdentifier(), AllowAnyProfileOfType: client.GetTokenExchange().GetAllowAnyProfileOfType(), + IsFirstParty: client.IsFirstParty, ThirdPartySecurityMode: client.GetThirdPartySecurityMode(), RedirectionPolicy: client.GetRedirectionPolicy(), raw: client, From 56aa4c8fbefc228ca3c4ca50ed48fef3feace61e Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Wed, 20 May 2026 18:47:27 +0530 Subject: [PATCH 07/11] chore(terraform_generate): add comment to client grant resource naming for default_for grants --- internal/cli/terraform_fetcher.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/cli/terraform_fetcher.go b/internal/cli/terraform_fetcher.go index d3df097c5..f531e9fd2 100644 --- a/internal/cli/terraform_fetcher.go +++ b/internal/cli/terraform_fetcher.go @@ -275,6 +275,7 @@ func (f *clientGrantResourceFetcher) FetchData(ctx context.Context) (importDataL for _, grant := range grants.ClientGrants { var resourceName string + // Grants with default_for have no client_id; use the default_for value as prefix instead. if grant.GetDefaultFor() != "" { resourceName = "auth0_client_grant." + sanitizeResourceName("default_for_"+grant.GetDefaultFor()+"_"+grant.GetAudience()) } else { From 94b8efdc07b77125ad1915f6f0f86a55046d623c Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Wed, 20 May 2026 18:48:03 +0530 Subject: [PATCH 08/11] test(apps): add tests for third-party app creation and management - Added integration tests for creating, showing, updating, and deleting a third-party app. - Created a new script `get-3p-app-id.sh` to handle the app ID retrieval for testing. - Updated existing test cases to reflect the new structure and ensure proper validation of third-party app properties. --- test/integration/apps-test-cases.yaml | 20 ++++++++++++++++++-- test/integration/scripts/get-3p-app-id.sh | 13 +++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100755 test/integration/scripts/get-3p-app-id.sh diff --git a/test/integration/apps-test-cases.yaml b/test/integration/apps-test-cases.yaml index c79912521..ebad6713e 100644 --- a/test/integration/apps-test-cases.yaml +++ b/test/integration/apps-test-cases.yaml @@ -377,12 +377,28 @@ tests: command: auth0 apps delete $(./test/integration/scripts/get-resource-server-app-id.sh) --force exit-code: 0 - 051 - it successfully creates a regular app with third-party-security-mode and redirection-policy and outputs in json: - command: auth0 apps create --name integration-test-app-3p-strict --type regular --description 3PApp1 --third-party-security-mode strict --redirection-policy open_redirect_protection --json + 051 - it successfully creates a third-party app with strict security mode: + command: ./test/integration/scripts/get-3p-app-id.sh + exit-code: 0 + + 052 - it successfully shows a third-party app with security mode and redirection policy in json: + command: auth0 apps show $(./test/integration/scripts/get-3p-app-id.sh) --json exit-code: 0 stdout: json: name: integration-test-app-3p-strict app_type: regular_web + is_first_party: "false" third_party_security_mode: strict redirection_policy: open_redirect_protection + + 053 - it successfully updates the redirection-policy of a third-party app and outputs in json: + command: auth0 apps update $(./test/integration/scripts/get-3p-app-id.sh) --redirection-policy allow_always --json + exit-code: 0 + stdout: + json: + redirection_policy: allow_always + + 054 - given a third-party app, it successfully deletes the app: + command: auth0 apps delete $(./test/integration/scripts/get-3p-app-id.sh) --force + exit-code: 0 diff --git a/test/integration/scripts/get-3p-app-id.sh b/test/integration/scripts/get-3p-app-id.sh new file mode 100755 index 000000000..23918bf3a --- /dev/null +++ b/test/integration/scripts/get-3p-app-id.sh @@ -0,0 +1,13 @@ +#! /bin/bash + +FILE=./test/integration/identifiers/3p-app-id +if [ -f "$FILE" ]; then + cat $FILE + exit 0 +fi + +app=$( auth0 apps create -n integration-test-app-3p-strict -t regular --description 3PApp1 --is-first-party=false --third-party-security-mode strict --redirection-policy open_redirect_protection --json --no-input ) + +mkdir -p ./test/integration/identifiers +echo "$app" | jq -r '.["client_id"]' > $FILE +cat $FILE From 78afb056ba0661d3e5f5001f73d1900b838edb2a Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Wed, 20 May 2026 19:06:00 +0530 Subject: [PATCH 09/11] chore(apps): lint fix --- internal/cli/apps.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/cli/apps.go b/internal/cli/apps.go index fcdf69d1a..c31c6c7b6 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -497,7 +497,7 @@ func createAppCmd(cli *cli) *cobra.Command { appIsSPA := apiTypeFor(inputs.Type) == appTypeSPA appIsResourceServer := apiTypeFor(inputs.Type) == appTypeResourceServer - // IsFirstParty flag is explisitly set to false + // IsFirstParty flag is explisitly set to false. isThirdPartyApp := appIsFirstParty.IsSet(cmd) && !inputs.IsFirstParty // Prompt for callback URLs if app is not m2m and not resource_server. From c554cb98bd8e32c60c313f17616e606c715d2dc7 Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Thu, 21 May 2026 12:18:23 +0530 Subject: [PATCH 10/11] docs(apps): require --is-first-party=false for redirection policy and security mode - Updated documentation for `auth0 apps create` and `auth0 apps update` commands to specify that the `--is-first-party=false` flag is required when using the `--redirection-policy` and `--third-party-security-mode` options. - Enhanced user clarity on the usage of these flags to prevent misconfiguration. --- docs/auth0_apps_create.md | 4 ++-- docs/auth0_apps_update.md | 4 ++-- internal/cli/apps.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/auth0_apps_create.md b/docs/auth0_apps_create.md index 5bdebd473..82670d1e6 100644 --- a/docs/auth0_apps_create.md +++ b/docs/auth0_apps_create.md @@ -50,11 +50,11 @@ auth0 apps create [flags] --metadata stringToString Arbitrary keys-value pairs (max 255 characters each), that can be assigned to each application. More about application metadata: https://auth0.com/docs/get-started/applications/configure-application-metadata (default []) -n, --name string Name of the application. -o, --origins strings Comma-separated list of URLs allowed to make requests from JavaScript to Auth0 API (typically used with CORS). By default, all your callback URLs will be allowed. This field allows you to enter other origins if necessary. You can also use wildcards at the subdomain level (e.g., https://*.contoso.com). Query strings and hash information are not taken into account when validating these URLs. - -y, --redirection-policy string Controls whether Auth0 redirects users to the application's callback URL on authentication errors or in email verification flows: 'allow_always' or 'open_redirect_protection'. + -y, --redirection-policy string Controls whether Auth0 redirects users to the application's callback URL on authentication errors or in email verification flows: 'allow_always' or 'open_redirect_protection'. Require --is-first-party=false -z, --refresh-token string Refresh Token Config for the application, formatted as JSON. --resource-server-identifier string The identifier of the resource server that this client is associated with. This property can only be sent when app_type=resource_server and cannot be changed once the client is created. -r, --reveal-secrets Display the application secrets ('signing_keys', 'client_secret') as part of the command output. - -s, --third-party-security-mode string Security mode for third-party clients: 'strict' or 'permissive'. + -s, --third-party-security-mode string Security mode for third-party clients: 'strict' or 'permissive'. Require --is-first-party=false -t, --type string Type of application: - native: mobile, desktop, CLI and smart device apps running natively. - spa (single page application): a JavaScript front-end app that uses an API. diff --git a/docs/auth0_apps_update.md b/docs/auth0_apps_update.md index 8ac4cd615..b4bfb1cf9 100644 --- a/docs/auth0_apps_update.md +++ b/docs/auth0_apps_update.md @@ -49,10 +49,10 @@ auth0 apps update [flags] --metadata stringToString Arbitrary keys-value pairs (max 255 characters each), that can be assigned to each application. More about application metadata: https://auth0.com/docs/get-started/applications/configure-application-metadata (default []) -n, --name string Name of the application. -o, --origins strings Comma-separated list of URLs allowed to make requests from JavaScript to Auth0 API (typically used with CORS). By default, all your callback URLs will be allowed. This field allows you to enter other origins if necessary. You can also use wildcards at the subdomain level (e.g., https://*.contoso.com). Query strings and hash information are not taken into account when validating these URLs. - -y, --redirection-policy string Controls whether Auth0 redirects users to the application's callback URL on authentication errors or in email verification flows: 'allow_always' or 'open_redirect_protection'. + -y, --redirection-policy string Controls whether Auth0 redirects users to the application's callback URL on authentication errors or in email verification flows: 'allow_always' or 'open_redirect_protection'. Require --is-first-party=false -z, --refresh-token string Refresh Token Config for the application, formatted as JSON. -r, --reveal-secrets Display the application secrets ('signing_keys', 'client_secret') as part of the command output. - -s, --third-party-security-mode string Security mode for third-party clients: 'strict' or 'permissive'. + -s, --third-party-security-mode string Security mode for third-party clients: 'strict' or 'permissive'. Require --is-first-party=false -t, --type string Type of application: - native: mobile, desktop, CLI and smart device apps running natively. - spa (single page application): a JavaScript front-end app that uses an API. diff --git a/internal/cli/apps.go b/internal/cli/apps.go index c31c6c7b6..82481ac8d 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -186,13 +186,13 @@ var ( Name: "Third Party Security Mode", LongForm: "third-party-security-mode", ShortForm: "s", - Help: "Security mode for third-party clients: 'strict' or 'permissive'.", + Help: "Security mode for third-party clients: 'strict' or 'permissive'. Require --is-first-party=false", } appRedirectionPolicy = Flag{ Name: "Redirection Policy", LongForm: "redirection-policy", ShortForm: "y", - Help: "Controls whether Auth0 redirects users to the application's callback URL on authentication errors or in email verification flows: 'allow_always' or 'open_redirect_protection'.", + Help: "Controls whether Auth0 redirects users to the application's callback URL on authentication errors or in email verification flows: 'allow_always' or 'open_redirect_protection'. Require --is-first-party=false", } ) From fb276b22cae8838ef7e1e392c26c745dd0f388de Mon Sep 17 00:00:00 2001 From: KIRAN KUMAR B Date: Thu, 21 May 2026 12:19:04 +0530 Subject: [PATCH 11/11] fix(cli): update resource naming for client grants - Refactored the logic for generating resource names in the FetchData method of clientGrantResourceFetcher. - The resource name now uses the client ID or default_for value, ensuring consistency in naming. - Updated test cases to reflect the new naming convention for third-party client grants. --- internal/cli/terraform_fetcher.go | 11 ++++------- internal/cli/terraform_fetcher_test.go | 4 ++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/internal/cli/terraform_fetcher.go b/internal/cli/terraform_fetcher.go index f531e9fd2..632c3a983 100644 --- a/internal/cli/terraform_fetcher.go +++ b/internal/cli/terraform_fetcher.go @@ -274,15 +274,12 @@ func (f *clientGrantResourceFetcher) FetchData(ctx context.Context) (importDataL } for _, grant := range grants.ClientGrants { - var resourceName string - // Grants with default_for have no client_id; use the default_for value as prefix instead. - if grant.GetDefaultFor() != "" { - resourceName = "auth0_client_grant." + sanitizeResourceName("default_for_"+grant.GetDefaultFor()+"_"+grant.GetAudience()) - } else { - resourceName = "auth0_client_grant." + sanitizeResourceName(grant.GetClientID()+"_"+grant.GetAudience()) + identifier := grant.GetClientID() + if identifier == "" { + identifier = grant.GetDefaultFor() } data = append(data, importDataItem{ - ResourceName: resourceName, + ResourceName: "auth0_client_grant." + sanitizeResourceName(identifier+"_"+grant.GetAudience()), ImportID: grant.GetID(), }) } diff --git a/internal/cli/terraform_fetcher_test.go b/internal/cli/terraform_fetcher_test.go index e7fc03f92..af3b7cb00 100644 --- a/internal/cli/terraform_fetcher_test.go +++ b/internal/cli/terraform_fetcher_test.go @@ -771,11 +771,11 @@ func TestClientGrantResourceFetcher_FetchData(t *testing.T) { ImportID: "cgr_1", }, { - ResourceName: "auth0_client_grant.default_for_third_party_clients_https_travel0_com_api", + ResourceName: "auth0_client_grant.third_party_clients_https_travel0_com_api", ImportID: "cgr_2", }, { - ResourceName: "auth0_client_grant.default_for_third_party_clients_https_partner_api_example_com", + ResourceName: "auth0_client_grant.third_party_clients_https_partner_api_example_com", ImportID: "cgr_3", }, }