Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/auth0_apps_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ auth0 apps create [flags]
auth0 apps create -n myapp -d <description> -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 --is-first-party=false --third-party-security-mode strict --redirection-policy open_redirect_protection
```


Expand All @@ -42,15 +43,18 @@ 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.
--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'. 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'. 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.
Expand Down
4 changes: 4 additions & 0 deletions docs/auth0_apps_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ auth0 apps update [flags]
auth0 apps update <app-id> -n myapp -d <description> -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" --metadata "bazz=buzz"
auth0 apps update <app-id> -n myapp -d <description> -t [native|spa|regular|m2m] -r --json --metadata "foo=bar,bazz=buzz"
auth0 apps update <app-id> --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange
auth0 apps update <app-id> --redirection-policy allow_always
```


Expand All @@ -41,14 +42,17 @@ 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.
--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'. 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'. 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.
Expand Down
100 changes: 79 additions & 21 deletions internal/cli/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,24 @@ 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",
ShortForm: "s",
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'. Require --is-first-party=false",
}
)

func appsCmd(cli *cli) *cobra.Command {
Expand Down Expand Up @@ -434,6 +452,9 @@ func createAppCmd(cli *cli) *cobra.Command {
RefreshToken string
ResourceServerIdentifier string
AllowAnyProfileOfType []string
IsFirstParty bool
ThirdPartySecurityMode string
RedirectionPolicy string
}
var oidcConformant = true
var algorithm = "RS256"
Expand All @@ -456,7 +477,8 @@ func createAppCmd(cli *cli) *cobra.Command {
auth0 apps create -n myapp -d <description> -t [native|spa|regular|m2m|resource_server] -r --json --metadata "foo=bar" --metadata "bazz=buzz"
auth0 apps create -n myapp -d <description> -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 --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
Expand All @@ -475,6 +497,9 @@ func createAppCmd(cli *cli) *cobra.Command {
appIsSPA := apiTypeFor(inputs.Type) == appTypeSPA
appIsResourceServer := apiTypeFor(inputs.Type) == appTypeResourceServer

// 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 {
var defaultValue string
Expand All @@ -488,8 +513,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 {
Expand Down Expand Up @@ -593,11 +618,22 @@ 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
}

// 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.
Expand Down Expand Up @@ -633,26 +669,32 @@ 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, "")

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
IsFirstParty bool
ThirdPartySecurityMode string
RedirectionPolicy string
}

cmd := &cobra.Command{
Expand All @@ -673,7 +715,8 @@ func updateAppCmd(cli *cli) *cobra.Command {
auth0 apps update <app-id> -n myapp -d <description> -t [native|spa|regular|m2m] -r --json --metadata "foo=bar"
auth0 apps update <app-id> -n myapp -d <description> -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" --metadata "bazz=buzz"
auth0 apps update <app-id> -n myapp -d <description> -t [native|spa|regular|m2m] -r --json --metadata "foo=bar,bazz=buzz"
auth0 apps update <app-id> --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange`,
auth0 apps update <app-id> --allow-any-profile-of-type custom_authentication,on_behalf_of_token_exchange
auth0 apps update <app-id> --redirection-policy allow_always`,
RunE: func(cmd *cobra.Command, args []string) error {
var current *management.Client

Expand Down Expand Up @@ -847,6 +890,18 @@ func updateAppCmd(cli *cli) *cobra.Command {
}
}

if appIsFirstParty.IsSet(cmd) {
a.IsFirstParty = auth0.Bool(inputs.IsFirstParty)
}

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 {
Expand Down Expand Up @@ -874,6 +929,9 @@ 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, "")

return cmd
}
Expand Down
6 changes: 5 additions & 1 deletion internal/cli/terraform_fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,12 @@ func (f *clientGrantResourceFetcher) FetchData(ctx context.Context) (importDataL
}

for _, grant := range grants.ClientGrants {
identifier := grant.GetClientID()
if identifier == "" {
identifier = grant.GetDefaultFor()
}
data = append(data, importDataItem{
ResourceName: "auth0_client_grant." + sanitizeResourceName(grant.GetClientID()+"_"+grant.GetAudience()),
ResourceName: "auth0_client_grant." + sanitizeResourceName(identifier+"_"+grant.GetAudience()),
ImportID: grant.GetID(),
})
}
Expand Down
61 changes: 61 additions & 0 deletions internal/cli/terraform_fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.third_party_clients_https_travel0_com_api",
ImportID: "cgr_2",
},
{
ResourceName: "auth0_client_grant.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) {
Expand Down
18 changes: 18 additions & 0 deletions internal/display/apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ type applicationView struct {
RefreshToken string
ResourceServerIdentifier string
AllowAnyProfileOfType []string
IsFirstParty *bool
ThirdPartySecurityMode string
RedirectionPolicy string
revealSecret bool

raw interface{}
Expand Down Expand Up @@ -128,6 +131,18 @@ 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})
}

if v.RedirectionPolicy != "" {
keyValues = append(keyValues, []string{"REDIRECTION POLICY", v.RedirectionPolicy})
}

return keyValues
}

Expand Down Expand Up @@ -213,6 +228,9 @@ 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,
RefreshToken: string(jsonRefreshToken),
}
Expand Down
26 changes: 26 additions & 0 deletions test/integration/apps-test-cases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -376,3 +376,29 @@ 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 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
Loading
Loading