diff --git a/docs/auth0_apps_create.md b/docs/auth0_apps_create.md index 521aa52df..ed9607024 100644 --- a/docs/auth0_apps_create.md +++ b/docs/auth0_apps_create.md @@ -22,37 +22,39 @@ auth0 apps create [flags] auth0 apps create auth0 apps create --name myapp auth0 apps create --name myapp --description - auth0 apps create --name myapp --description --type [native|spa|regular|m2m] - auth0 apps create --name myapp --description --type [native|spa|regular|m2m] --reveal-secrets - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json-compact - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" --metadata "bazz=buzz" - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar,bazz=buzz" + auth0 apps create --name myapp --description --type [native|spa|regular|m2m|resource_server] + auth0 apps create --name myapp --description --type [native|spa|regular|m2m|resource_server] --reveal-secrets + auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json + auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json-compact + auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json --metadata "foo=bar" + 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" ``` ## Flags ``` - -a, --auth-method string Defines the requested authentication method for the token endpoint. Possible values are 'None' (public application without a client secret), 'Post' (application uses HTTP POST parameters) or 'Basic' (application uses HTTP Basic). - -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. - --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. - -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. - -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. - - regular: Traditional web app using redirects. - - m2m (machine to machine): CLIs, daemons or services running on your backend. - -w, --web-origins strings Comma-separated list of allowed origins for use with Cross-Origin Authentication, Device Flow, and web message response mode. + -a, --auth-method string Defines the requested authentication method for the token endpoint. Possible values are 'None' (public application without a client secret), 'Post' (application uses HTTP POST parameters) or 'Basic' (application uses HTTP Basic). + -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. + --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. + -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. + -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. + - regular: Traditional web app using redirects. + - m2m (machine to machine): CLIs, daemons or services running on your backend. + -w, --web-origins strings Comma-separated list of allowed origins for use with Cross-Origin Authentication, Device Flow, and web message response mode. ``` diff --git a/internal/cli/apps.go b/internal/cli/apps.go index fbae53ddd..097f2bd23 100644 --- a/internal/cli/apps.go +++ b/internal/cli/apps.go @@ -25,6 +25,7 @@ const ( appTypeSPA = "spa" appTypeRegularWeb = "regular_web" appTypeNonInteractive = "non_interactive" + appTypeResourceServer = "resource_server" appDefaultURL = "http://localhost:3000" defaultPageSize = 100 ) @@ -63,6 +64,7 @@ var ( "Single Page Web Application", "Regular Web Application", "Machine to Machine", + "Resource Server", } appDescription = Flag{ Name: "Description", @@ -123,6 +125,12 @@ var ( Help: "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.", IsRequired: false, } + appResourceServerIdentifier = Flag{ + Name: "Resource Server Identifier", + LongForm: "resource-server-identifier", + Help: "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.", + IsRequired: false, + } revealSecrets = Flag{ Name: "Reveal", LongForm: "reveal-secrets", @@ -406,18 +414,19 @@ func deleteAppCmd(cli *cli) *cobra.Command { func createAppCmd(cli *cli) *cobra.Command { var inputs struct { - 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 + 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 + ResourceServerIdentifier string } var oidcConformant = true var algorithm = "RS256" @@ -432,13 +441,14 @@ func createAppCmd(cli *cli) *cobra.Command { Example: ` auth0 apps create auth0 apps create --name myapp auth0 apps create --name myapp --description - auth0 apps create --name myapp --description --type [native|spa|regular|m2m] - auth0 apps create --name myapp --description --type [native|spa|regular|m2m] --reveal-secrets - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json-compact - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar" --metadata "bazz=buzz" - auth0 apps create -n myapp -d -t [native|spa|regular|m2m] -r --json --metadata "foo=bar,bazz=buzz"`, + auth0 apps create --name myapp --description --type [native|spa|regular|m2m|resource_server] + auth0 apps create --name myapp --description --type [native|spa|regular|m2m|resource_server] --reveal-secrets + auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json + auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json-compact + auth0 apps create -n myapp -d -t [native|spa|regular|m2m|resource_server] -r --json --metadata "foo=bar" + 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"`, RunE: func(cmd *cobra.Command, args []string) error { if err := appName.Ask(cmd, &inputs.Name, nil); err != nil { return err @@ -455,9 +465,10 @@ func createAppCmd(cli *cli) *cobra.Command { appIsM2M := apiTypeFor(inputs.Type) == appTypeNonInteractive appIsNative := apiTypeFor(inputs.Type) == appTypeNative appIsSPA := apiTypeFor(inputs.Type) == appTypeSPA + appIsResourceServer := apiTypeFor(inputs.Type) == appTypeResourceServer - // Prompt for callback URLs if app is not m2m. - if !appIsM2M { + // Prompt for callback URLs if app is not m2m and not resource_server. + if !appIsM2M && !appIsResourceServer { var defaultValue string if !appIsNative { @@ -469,8 +480,8 @@ func createAppCmd(cli *cli) *cobra.Command { } } - // Prompt for logout URLs if app is not m2m. - if !appIsM2M { + // Prompt for logout URLs if app is not m2m and not resource_server. + if !appIsM2M && !appIsResourceServer { var defaultValue string if !appIsNative { @@ -500,6 +511,13 @@ func createAppCmd(cli *cli) *cobra.Command { } } + // Prompt for resource server identifier if app type is resource_server. + if appIsResourceServer { + if err := appResourceServerIdentifier.Ask(cmd, &inputs.ResourceServerIdentifier, nil); err != nil { + return err + } + } + clientMetadata := make(map[string]interface{}, len(inputs.Metadata)) for k, v := range inputs.Metadata { clientMetadata[k] = v @@ -507,16 +525,29 @@ func createAppCmd(cli *cli) *cobra.Command { // Load values into a fresh app instance. a := &management.Client{ - Name: &inputs.Name, - Description: &inputs.Description, - AppType: auth0.String(apiTypeFor(inputs.Type)), - Callbacks: stringSliceToPtr(inputs.Callbacks), - AllowedOrigins: stringSliceToPtr(inputs.AllowedOrigins), - WebOrigins: stringSliceToPtr(inputs.AllowedWebOrigins), - AllowedLogoutURLs: stringSliceToPtr(inputs.AllowedLogoutURLs), - OIDCConformant: &oidcConformant, - JWTConfiguration: &management.ClientJWTConfiguration{Algorithm: &algorithm}, - ClientMetadata: &clientMetadata, + Name: &inputs.Name, + Description: &inputs.Description, + AppType: auth0.String(apiTypeFor(inputs.Type)), + AllowedOrigins: stringSliceToPtr(inputs.AllowedOrigins), + WebOrigins: stringSliceToPtr(inputs.AllowedWebOrigins), + OIDCConformant: &oidcConformant, + JWTConfiguration: &management.ClientJWTConfiguration{Algorithm: &algorithm}, + ClientMetadata: &clientMetadata, + } + + callback := stringSliceToPtr(inputs.Callbacks) + allowedLogoutURLs := stringSliceToPtr(inputs.AllowedLogoutURLs) + + // Only set for non-resource_server apps. + if appIsResourceServer { + cli.renderer.Infof("Resource server apps do not support callbacks or logout URLs") + } else { + a.Callbacks = callback + a.AllowedLogoutURLs = allowedLogoutURLs + } + + if appIsResourceServer && inputs.ResourceServerIdentifier != "" { + a.ResourceServerIdentifier = &inputs.ResourceServerIdentifier } if len(inputs.RefreshToken) != 0 { @@ -568,6 +599,7 @@ func createAppCmd(cli *cli) *cobra.Command { appLogoutURLs.RegisterStringSlice(cmd, &inputs.AllowedLogoutURLs, nil) appAuthMethod.RegisterString(cmd, &inputs.AuthMethod, "") appGrants.RegisterStringSlice(cmd, &inputs.Grants, nil) + appResourceServerIdentifier.RegisterString(cmd, &inputs.ResourceServerIdentifier, "") revealSecrets.RegisterBool(cmd, &inputs.RevealSecrets, false) refreshToken.RegisterString(cmd, &inputs.RefreshToken, "") @@ -852,6 +884,8 @@ func apiTypeFor(v string) string { return appTypeRegularWeb case "m2m", "machine to machine": return appTypeNonInteractive + case "resource server": + return appTypeResourceServer default: return v } @@ -921,6 +955,8 @@ func apiDefaultGrantsFor(t string) *[]string { return &[]string{"implicit", "authorization_code", "refresh_token", "client_credentials"} case appTypeNonInteractive: return &[]string{"client_credentials"} + case appTypeResourceServer: + return &[]string{"urn:auth0:params:oauth:grant-type:token-exchange:federated-connection-access-token"} default: return nil } @@ -936,6 +972,8 @@ func typeFor(s *string) *string { return auth0.String("Regular Web Application") case appTypeNonInteractive: return auth0.String("Machine to Machine") + case appTypeResourceServer: + return auth0.String("Resource Server") default: return nil } diff --git a/internal/cli/apps_test.go b/internal/cli/apps_test.go index 00785ac82..904b73f5b 100644 --- a/internal/cli/apps_test.go +++ b/internal/cli/apps_test.go @@ -24,9 +24,9 @@ func TestAppsListCmd(t *testing.T) { name: "happy path", assertOutput: func(t testing.TB, out string) { expectTable(t, out, - []string{"CLIENT ID", "NAME", "TYPE"}, + []string{"CLIENT ID", "NAME", "TYPE", "RESOURCE SERVER"}, [][]string{ - {"some-id", "some-name", "Generic"}, + {"some-id", "some-name", "Generic", ""}, }, ) }, @@ -36,9 +36,9 @@ func TestAppsListCmd(t *testing.T) { args: []string{"--reveal-secrets"}, assertOutput: func(t testing.TB, out string) { expectTable(t, out, - []string{"CLIENT ID", "NAME", "TYPE", "CLIENT SECRET"}, + []string{"CLIENT ID", "NAME", "TYPE", "CLIENT SECRET", "RESOURCE SERVER"}, [][]string{ - {"some-id", "some-name", "Generic", "secret-here"}, + {"some-id", "some-name", "Generic", "secret-here", ""}, }, ) }, @@ -112,6 +112,10 @@ func TestTypeFor(t *testing.T) { expected = "Machine to Machine" assert.Equal(t, &expected, typeFor(&testAppType)) + testAppType = appTypeResourceServer + expected = "Resource Server" + assert.Equal(t, &expected, typeFor(&testAppType)) + testAppType = "some-unknown-api-type" assert.Nil(t, typeFor(&testAppType)) } diff --git a/internal/display/apis.go b/internal/display/apis.go index f78cacf3f..ed2748b6c 100644 --- a/internal/display/apis.go +++ b/internal/display/apis.go @@ -21,6 +21,7 @@ type apiView struct { OfflineAccess string SigningAlgorithm string SubjectTypeAuthJSON string + ClientID string raw interface{} } @@ -48,6 +49,10 @@ func (v *apiView) KeyValues() [][]string { kvs = append(kvs, []string{"SUBJECT TYPE AUTHORIZATION", v.SubjectTypeAuthJSON}) } + if len(v.ClientID) > 0 { + kvs = append(kvs, []string{"CLIENT ID", v.ClientID}) + } + return kvs } @@ -136,6 +141,7 @@ func makeAPIView(api *management.ResourceServer) (*apiView, bool) { OfflineAccess: boolean(api.GetAllowOfflineAccess()), SigningAlgorithm: api.GetSigningAlgorithm(), SubjectTypeAuthJSON: subjectTypeAuthJSON, + ClientID: api.GetClientID(), raw: api, } return view, scopesTruncated diff --git a/internal/display/apps.go b/internal/display/apps.go index 533dab9e6..d7b006991 100644 --- a/internal/display/apps.go +++ b/internal/display/apps.go @@ -12,56 +12,66 @@ import ( ) const ( - quickstartsNative = "https://auth0.com/docs/quickstart/native" - quickstartsSPA = "https://auth0.com/docs/quickstart/spa" - quickstartsRegularWeb = "https://auth0.com/docs/quickstart/webapp" - quickstartsM2M = "https://auth0.com/docs/quickstart/backend" - quickstartsGeneric = "https://auth0.com/docs/quickstarts" - friendlyM2M = "Machine to Machine" - friendlyNative = "Native" - friendlySpa = "Single Page Web Application" - friendlyReg = "Regular Web Application" + quickstartsNative = "https://auth0.com/docs/quickstart/native" + quickstartsSPA = "https://auth0.com/docs/quickstart/spa" + quickstartsRegularWeb = "https://auth0.com/docs/quickstart/webapp" + quickstartsM2M = "https://auth0.com/docs/quickstart/backend" + quickstartsGeneric = "https://auth0.com/docs/quickstarts" + friendlyM2M = "Machine to Machine" + friendlyNative = "Native" + friendlySpa = "Single Page Web Application" + friendlyReg = "Regular Web Application" + friendlyResourceServer = "Resource Server" ) type applicationView struct { - Name string - Description string - Type string - ClientID string - ClientSecret string - Callbacks []string - AllowedOrigins []string - AllowedWebOrigins []string - AllowedLogoutURLs []string - AuthMethod string - Grants []string - Metadata []string - RefreshToken string - revealSecret bool + Name string + Description string + Type string + ClientID string + ClientSecret string + Callbacks []string + AllowedOrigins []string + AllowedWebOrigins []string + AllowedLogoutURLs []string + AuthMethod string + Grants []string + Metadata []string + RefreshToken string + ResourceServerIdentifier string + revealSecret bool raw interface{} } func (v *applicationView) AsTableHeader() []string { if v.revealSecret { - return []string{"Client ID", "Name", "Type", "Client Secret"} + return []string{"Client ID", "Name", "Type", "Client Secret", "Resource Server"} } - return []string{"Client ID", "Name", "Type"} + return []string{"Client ID", "Name", "Type", "Resource Server"} } func (v *applicationView) AsTableRow() []string { + // Show resource server identifier if present, otherwise empty. + resourceServerDisplay := "" + if v.ResourceServerIdentifier != "" { + resourceServerDisplay = v.ResourceServerIdentifier + } + if v.revealSecret { return []string{ ansi.Faint(v.ClientID), v.Name, ApplyColorToFriendlyAppType(v.Type), ansi.Italic(v.ClientSecret), + resourceServerDisplay, } } return []string{ ansi.Faint(v.ClientID), v.Name, ApplyColorToFriendlyAppType(v.Type), + resourceServerDisplay, } } @@ -73,8 +83,10 @@ func (v *applicationView) KeyValues() [][]string { grants := strings.Join(v.Grants, ", ") metadata := strings.Join(v.Metadata, ", ") + var keyValues [][]string + if v.revealSecret { - return [][]string{ + keyValues = [][]string{ {"CLIENT ID", ansi.Faint(v.ClientID)}, {"NAME", v.Name}, {"DESCRIPTION", v.Description}, @@ -89,22 +101,29 @@ func (v *applicationView) KeyValues() [][]string { {"METADATA", metadata}, {"REFRESH TOKEN", v.RefreshToken}, } + } else { + keyValues = [][]string{ + {"CLIENT ID", ansi.Faint(v.ClientID)}, + {"NAME", v.Name}, + {"DESCRIPTION", v.Description}, + {"TYPE", ApplyColorToFriendlyAppType(v.Type)}, + {"CALLBACKS", callbacks}, + {"ALLOWED LOGOUT URLS", allowedLogoutURLs}, + {"ALLOWED ORIGINS", allowedOrigins}, + {"ALLOWED WEB ORIGINS", allowedWebOrigins}, + {"TOKEN ENDPOINT AUTH", v.AuthMethod}, + {"GRANTS", grants}, + {"METADATA", metadata}, + {"REFRESH TOKEN", v.RefreshToken}, + } } - return [][]string{ - {"CLIENT ID", ansi.Faint(v.ClientID)}, - {"NAME", v.Name}, - {"DESCRIPTION", v.Description}, - {"TYPE", ApplyColorToFriendlyAppType(v.Type)}, - {"CALLBACKS", callbacks}, - {"ALLOWED LOGOUT URLS", allowedLogoutURLs}, - {"ALLOWED ORIGINS", allowedOrigins}, - {"ALLOWED WEB ORIGINS", allowedWebOrigins}, - {"TOKEN ENDPOINT AUTH", v.AuthMethod}, - {"GRANTS", grants}, - {"METADATA", metadata}, - {"REFRESH TOKEN", v.RefreshToken}, + // Add resource server identifier if present. + if v.ResourceServerIdentifier != "" { + keyValues = append(keyValues, []string{"RESOURCE SERVER IDENTIFIER", v.ResourceServerIdentifier}) } + + return keyValues } func (v *applicationView) Object() interface{} { @@ -174,21 +193,22 @@ func makeApplicationView(client *management.Client, revealSecrets bool) *applica jsonRefreshToken, _ := json.Marshal(client.GetRefreshToken()) return &applicationView{ - revealSecret: revealSecrets, - Name: client.GetName(), - Description: client.GetDescription(), - Type: FriendlyAppType(client.GetAppType()), - ClientID: client.GetClientID(), - ClientSecret: client.GetClientSecret(), - Callbacks: client.GetCallbacks(), - AllowedOrigins: client.GetAllowedOrigins(), - AllowedWebOrigins: client.GetWebOrigins(), - AllowedLogoutURLs: client.GetAllowedLogoutURLs(), - AuthMethod: client.GetTokenEndpointAuthMethod(), - Grants: client.GetGrantTypes(), - Metadata: mapPointerToArray(client.ClientMetadata), - raw: client, - RefreshToken: string(jsonRefreshToken), + revealSecret: revealSecrets, + Name: client.GetName(), + Description: client.GetDescription(), + Type: FriendlyAppType(client.GetAppType()), + ClientID: client.GetClientID(), + ClientSecret: client.GetClientSecret(), + Callbacks: client.GetCallbacks(), + AllowedOrigins: client.GetAllowedOrigins(), + AllowedWebOrigins: client.GetWebOrigins(), + AllowedLogoutURLs: client.GetAllowedLogoutURLs(), + AuthMethod: client.GetTokenEndpointAuthMethod(), + Grants: client.GetGrantTypes(), + Metadata: mapPointerToArray(client.ClientMetadata), + ResourceServerIdentifier: client.GetResourceServerIdentifier(), + raw: client, + RefreshToken: string(jsonRefreshToken), } } @@ -204,6 +224,8 @@ func FriendlyAppType(appType string) string { return friendlySpa case appType == "regular_web": return friendlyReg + case appType == "resource_server": + return friendlyResourceServer default: return appType } @@ -229,6 +251,8 @@ func quickstartsURIFor(appType string) string { return quickstartsRegularWeb case appType == "non_interactive": return quickstartsM2M + case appType == "resource_server": + return quickstartsGeneric default: return quickstartsGeneric } @@ -244,6 +268,8 @@ func ApplyColorToFriendlyAppType(a string) string { return ansi.Blue(a) case a == friendlyReg: return ansi.Magenta(a) + case a == friendlyResourceServer: + return ansi.Yellow(a) default: return a } diff --git a/test/integration/apps-test-cases.yaml b/test/integration/apps-test-cases.yaml index a66965155..50b6ad874 100644 --- a/test/integration/apps-test-cases.yaml +++ b/test/integration/apps-test-cases.yaml @@ -313,3 +313,35 @@ tests: 041 - given a test app, it successfully deletes the app: command: auth0 apps delete $(./test/integration/scripts/get-app-id.sh) --force exit-code: 0 + + 042 - it successfully creates a resource server app with resource-server-identifier: + command: ./test/integration/scripts/get-resource-server-app-id.sh + exit-code: 0 + + 043 - it successfully creates a resource server app with resource-server-identifier and outputs in json: + command: auth0 apps show $(./test/integration/scripts/get-resource-server-app-id.sh) --json + exit-code: 0 + stdout: + json: + name: integration-test-app-resourceserver1 + app_type: resource_server + resource_server_identifier: http://integration-test-api-newapi + + 044 - it shows resource server app with resource-server-identifier: + command: auth0 apps show $(./test/integration/scripts/get-resource-server-app-id.sh) + exit-code: 0 + stdout: + contains: + - TYPE Resource Server + - RESOURCE SERVER IDENTIFIER http://integration-test-api-newapi + + 045 - it fails to update resource-server-identifier (immutable property): + command: auth0 apps update $(./test/integration/scripts/get-resource-server-app-id.sh) --resource-server-identifier http://new-api.localhost --json + exit-code: 1 + stderr: + contains: + - "Unknown flag: --resource-server-identifier" + + 046 - 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 diff --git a/test/integration/scripts/get-resource-server-app-id.sh b/test/integration/scripts/get-resource-server-app-id.sh new file mode 100755 index 000000000..e38a43dc6 --- /dev/null +++ b/test/integration/scripts/get-resource-server-app-id.sh @@ -0,0 +1,17 @@ +#! /bin/bash + +FILE=./test/integration/identifiers/resource-server-app-id +if [ -f "$FILE" ]; then + cat $FILE + exit 0 +fi + +# First, ensure the API exists (cross-domain dependency) +api_identifier=$(./test/integration/scripts/get-api-id.sh) + +# Now create the resource server app using the API's identifier +app=$( auth0 apps create -n integration-test-app-resourceserver1 -t resource_server --resource-server-identifier http://integration-test-api-newapi --json --no-input ) + +mkdir -p ./test/integration/identifiers +echo "$app" | jq -r '.["client_id"]' > $FILE +cat $FILE