diff --git a/model/src/main/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderSecretChange.java b/model/src/main/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderSecretChange.java deleted file mode 100644 index 74d8cb6a64..0000000000 --- a/model/src/main/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderSecretChange.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.cloudfoundry.identity.uaa.provider; - -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonInclude(JsonInclude.Include.NON_NULL) -public class IdentityProviderSecretChange { - - private String secret; - - public String getSecret() { - return this.secret; - } - - public void setSecret(final String secret) { - this.secret = secret; - } -} diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderEndpoints.java b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderEndpoints.java index b3d3fcb154..8fdafe406c 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderEndpoints.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderEndpoints.java @@ -70,7 +70,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -411,7 +410,6 @@ protected void patchSensitiveData(String id, IdentityProvider provider) { definition.setBindPassword(existingDefinition.getBindPassword()); } } - } break; } case OAUTH20, OIDC10 : { diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderEndpointsTest.java b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderEndpointsTest.java index d77813d8fc..cd70f25902 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderEndpointsTest.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/provider/IdentityProviderEndpointsTest.java @@ -329,79 +329,6 @@ void retrieve_by_origin_providers_redacts_data() { assertEquals(ClientAuthentication.CLIENT_SECRET_BASIC, oidc.getConfig().getAuthMethod()); } - @Test - void delete_secret_and_retrieve_by_origin_providers_redacts_data() { - IdentityProvider idp = getExternalOAuthProvider(); - when(mockIdpAliasHandler.ensureConsistencyOfAliasEntity(null, idp)).thenReturn(idp); - when(mockIdentityProviderProvisioning.retrieve("puppyId", "uaa")).thenReturn(idp); - ResponseEntity oidcBody = identityProviderEndpoints.deleteSecret("puppyId"); - IdentityProvider oidc = oidcBody.getBody(); - assertNotNull(oidc); - assertNotNull(oidc.getConfig()); - assertTrue(oidc.getConfig() instanceof AbstractExternalOAuthIdentityProviderDefinition); - assertNull(((AbstractExternalOAuthIdentityProviderDefinition) oidc.getConfig()).getRelyingPartySecret()); - assertEquals(ClientAuthentication.NONE, ((AbstractExternalOAuthIdentityProviderDefinition) oidc.getConfig()).getAuthMethod()); - } - - @Test - void delete_secret_on_ldap_fails() { - when(mockIdentityProviderProvisioning.retrieve("puppyId", "uaa")).thenReturn(getLdapDefinition()); - ResponseEntity oidcBody = identityProviderEndpoints.deleteSecret("puppyId"); - IdentityProvider oidc = oidcBody.getBody(); - assertEquals(UNPROCESSABLE_ENTITY, oidcBody.getStatusCode()); - assertNull(oidc); - } - - @Test - void change_bindPassword_and_retrieve_by_origin_providers_redacts_data() { - IdentityProvider idp = getLdapDefinition(); - when(mockIdentityProviderProvisioning.retrieve("puppyId", "uaa")).thenReturn(idp); - IdentityProviderSecretChange identityProviderSecretChange = new IdentityProviderSecretChange(); - identityProviderSecretChange.setSecret("newSecret"); - ResponseEntity oidcBody = identityProviderEndpoints.changeSecret("puppyId", identityProviderSecretChange); - IdentityProvider oidc = oidcBody.getBody(); - assertNotNull(oidc); - assertNotNull(oidc.getConfig()); - assertTrue(oidc.getConfig() instanceof LdapIdentityProviderDefinition); - assertNull(((LdapIdentityProviderDefinition) oidc.getConfig()).getBindPassword()); - } - - @Test - void change_secret_and_retrieve_by_origin_providers_redacts_data() { - IdentityProvider idp = getExternalOAuthProvider(); - when(mockIdpAliasHandler.ensureConsistencyOfAliasEntity(null, idp)).thenReturn(idp); - when(mockIdentityProviderProvisioning.retrieve("puppyId", "uaa")).thenReturn(idp); - IdentityProviderSecretChange identityProviderSecretChange = new IdentityProviderSecretChange(); - identityProviderSecretChange.setSecret("newSecret"); - ResponseEntity oidcBody = identityProviderEndpoints.changeSecret("puppyId", identityProviderSecretChange); - IdentityProvider oidc = oidcBody.getBody(); - assertNotNull(oidc); - assertNotNull(oidc.getConfig()); - assertTrue(oidc.getConfig() instanceof AbstractExternalOAuthIdentityProviderDefinition); - assertNull(((AbstractExternalOAuthIdentityProviderDefinition) oidc.getConfig()).getRelyingPartySecret()); - assertEquals(ClientAuthentication.CLIENT_SECRET_BASIC, ((AbstractExternalOAuthIdentityProviderDefinition) oidc.getConfig()).getAuthMethod()); - } - - @Test - void change_secret_on_uaafails() { - IdentityProvider identityProvider = new IdentityProvider<>(); - identityProvider.setConfig(new SamlIdentityProviderDefinition()); - identityProvider.setName("my saml provider"); - identityProvider.setIdentityZoneId(OriginKeys.UAA); - identityProvider.setType(OriginKeys.SAML); - IdentityProviderSecretChange identityProviderSecretChange = new IdentityProviderSecretChange(); - when(mockIdentityProviderProvisioning.retrieve("puppyId", "uaa")).thenReturn(identityProvider); - ResponseEntity oidcBody = identityProviderEndpoints.changeSecret("puppyId", identityProviderSecretChange); - IdentityProvider oidc = oidcBody.getBody(); - assertEquals(UNPROCESSABLE_ENTITY, oidcBody.getStatusCode()); - assertNull(oidc); - identityProviderSecretChange.setSecret("newSecret"); - oidcBody = identityProviderEndpoints.changeSecret("puppyId", identityProviderSecretChange); - oidc = oidcBody.getBody(); - assertEquals(UNPROCESSABLE_ENTITY, oidcBody.getStatusCode()); - assertNull(oidc); - } - @Test void update_ldap_provider_patches_password() throws Exception { IdentityProvider provider = retrieve_ldap_provider_by_id("id"); diff --git a/uaa/slateCustomizations/source/index.html.md.erb b/uaa/slateCustomizations/source/index.html.md.erb index 632f61d529..792a2ce97b 100644 --- a/uaa/slateCustomizations/source/index.html.md.erb +++ b/uaa/slateCustomizations/source/index.html.md.erb @@ -1261,82 +1261,6 @@ _Error Codes_ | 403 | Forbidden - Insufficient scope | | 422 | Unprocessable Entity - Invalid config | -## Change Secret - - -
-Change a relyingPartySecret in the OAuth2 / OIDC IdP configuration or bindPassword in case of LDAP. -
- -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenChangeSecret/curl-request.md') %> -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenChangeSecret/http-request.md') %> -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenChangeSecret/http-response.md') %> - -_Path Parameters_ - -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenChangeSecret/path-parameters.md') %> - -_Request Headers_ - -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenChangeSecret/request-headers.md') %> - - - -_Request and Response Fields_ - -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenChangeSecret/response-fields.md') %> - -_Error Codes_ - -| Error Code | Description | -|------------|-----------------------------------------------------------------------| -| 403 | Forbidden - Insufficient scope | -| 422 | Unprocessable Entity - Invalid config | - -## Delete Secret - - -
-Delete a secret from the OAuth2 / OIDC IdP configuration only, because these providers support usages without a secret. -
- -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenDeleteSecret/curl-request.md') %> -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenDeleteSecret/http-request.md') %> -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenDeleteSecret/http-response.md') %> - -_Path Parameters_ - -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenDeleteSecret/path-parameters.md') %> - -_Request Headers_ - -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenDeleteSecret/request-headers.md') %> - - - -_Request and Response Fields_ - -<%= render('IdentityProviderEndpointDocs/createOAuthIdentityProviderThenDeleteSecret/response-fields.md') %> - -_Error Codes_ - -| Error Code | Description | -|------------|-----------------------------------------------------------------------| -| 403 | Forbidden - Insufficient scope | -| 422 | Unprocessable Entity - Invalid config | # Users diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/providers/IdentityProviderEndpointDocs.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/providers/IdentityProviderEndpointDocs.java index ec58a149fa..b944110354 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/providers/IdentityProviderEndpointDocs.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/providers/IdentityProviderEndpointDocs.java @@ -77,7 +77,6 @@ import org.cloudfoundry.identity.uaa.provider.AbstractExternalOAuthIdentityProviderDefinition; import org.cloudfoundry.identity.uaa.provider.IdentityProvider; import org.cloudfoundry.identity.uaa.provider.IdentityProviderProvisioning; -import org.cloudfoundry.identity.uaa.provider.IdentityProviderSecretChange; import org.cloudfoundry.identity.uaa.provider.IdentityProviderStatus; import org.cloudfoundry.identity.uaa.provider.JdbcIdentityProviderProvisioning; import org.cloudfoundry.identity.uaa.provider.LdapIdentityProviderDefinition; @@ -590,7 +589,6 @@ void createOAuthIdentityProvider() throws Exception { fieldWithPath("config.userInfoUrl").optional(null).type(STRING).description("A URL for fetching user info attributes when queried with the obtained token authorization."), fieldWithPath("config.showLinkText").optional(true).type(BOOLEAN).description("A flag controlling whether a link to this provider's login will be shown on the UAA login page"), fieldWithPath("config.linkText").optional(null).type(STRING).description("Text to use for the login link to the provider"), - fieldWithPath("config.auth_method").optional(null).type(STRING).description("UAA 77.10.0 Client authentication method. Possible strings are: client_secret_basic, client_secret_post, private_key_jwt, none."), fieldWithPath("config.relyingPartyId").required().type(STRING).description("The client ID which is registered with the external OAuth provider for use by the UAA"), fieldWithPath("config.skipSslValidation").optional(null).type(BOOLEAN).description("A flag controlling whether SSL validation should be skipped when communicating with the external OAuth server"), fieldWithPath("config.scopes").optional(null).type(ARRAY).description("What scopes to request on a call to the external OAuth provider"), @@ -635,7 +633,7 @@ void createOAuthIdentityProvider() throws Exception { IDENTITY_ZONE_ID, CREATED, LAST_MODIFIED, - fieldWithPath("config.externalGroupsWhitelist").optional(null).type(ARRAY).description("Not currently used."), + fieldWithPath("config.externalGroupsWhitelist").optional(null).type(ARRAY).description("Not currently used.") }, ALIAS_FIELDS_GET ) @@ -697,7 +695,6 @@ void createOidcIdentityProvider() throws Exception { fieldWithPath("config.tokenKey").optional(null).type(STRING).description("A verification key for validating token signatures. We recommend not setting this as it will not allow for key rotation. This can be left blank if a discovery URL is provided. If both are provided, this property overrides the discovery URL.").attributes(new Attributes.Attribute("constraints", "Required unless `discoveryUrl` is set.")), fieldWithPath("config.showLinkText").optional(true).type(BOOLEAN).description("A flag controlling whether a link to this provider's login will be shown on the UAA login page"), fieldWithPath("config.linkText").optional(null).type(STRING).description("Text to use for the login link to the provider"), - fieldWithPath("config.auth_method").optional(null).type(STRING).description("UAA 77.10.0 Client authentication method. Possible strings are: client_secret_basic, client_secret_post, private_key_jwt, none."), fieldWithPath("config.relyingPartyId").required().type(STRING).description("The client ID which is registered with the external OAuth provider for use by the UAA"), fieldWithPath("config.skipSslValidation").optional(null).type(BOOLEAN).description("A flag controlling whether SSL validation should be skipped when communicating with the external OAuth server"), fieldWithPath("config.scopes").optional(null).type(ARRAY).description("What scopes to request on a call to the external OAuth/OpenID provider. For example, can provide " + @@ -1143,56 +1140,6 @@ void patchIdentityProviderStatus() throws Exception { } - @Test - void createOAuthIdentityProviderThenChangeSecret() throws Exception { - IdentityProvider identityProvider = identityProviderProvisioning.retrieveByOrigin("my-oauth2-provider", IdentityZoneHolder.get().getId()); - - IdentityProviderSecretChange identityProviderSecretChange = new IdentityProviderSecretChange(); - identityProviderSecretChange.setSecret("newSecret" + new AlphanumericRandomValueStringGenerator(10).generate()); - - FieldDescriptor[] idempotentFields = new FieldDescriptor[]{ - fieldWithPath("secret").required().description("Set new secret and/or bind password, depending on provided IdP type.") - }; - - Snippet requestFields = requestFields(idempotentFields); - - mockMvc.perform(patch("/identity-providers/{id}/secret", identityProvider.getId()) - .header("Authorization", "Bearer " + adminToken) - .contentType(APPLICATION_JSON) - .content(serializeExcludingProperties(identityProviderSecretChange))) - .andExpect(status().isOk()) - .andDo(document("{ClassName}/{methodName}", - preprocessResponse(prettyPrint()), - pathParameters(parameterWithName("id").description(ID_DESC) - ), - requestHeaders( - headerWithName("Authorization").description("Bearer token containing `zones..admin` or `uaa.admin` or `idps.write` (only in the same zone that you are a user of)"), - IDENTITY_ZONE_ID_HEADER, - IDENTITY_ZONE_SUBDOMAIN_HEADER - ), - requestFields, - responseFields(getCommonProviderFieldsAnyType()))); - } - - @Test - void createOAuthIdentityProviderThenDeleteSecret() throws Exception { - IdentityProvider identityProvider = identityProviderProvisioning.retrieveByOrigin("my-oauth2-provider", IdentityZoneHolder.get().getId()); - - mockMvc.perform(delete("/identity-providers/{id}/secret", identityProvider.getId()) - .header("Authorization", "Bearer " + adminToken)) - .andExpect(status().isOk()) - .andDo(document("{ClassName}/{methodName}", - preprocessResponse(prettyPrint()), - pathParameters(parameterWithName("id").description(ID_DESC) - ), - requestHeaders( - headerWithName("Authorization").description("Bearer token containing `zones..admin` or `uaa.admin` or `idps.write` (only in the same zone that you are a user of)"), - IDENTITY_ZONE_ID_HEADER, - IDENTITY_ZONE_SUBDOMAIN_HEADER - ), - responseFields(getCommonProviderFieldsAnyType()))); - } - @Test void deleteIdentityProvider() throws Exception { IdentityProvider identityProvider = JsonUtils.readValue(mockMvc.perform(post("/identity-providers")