-
Notifications
You must be signed in to change notification settings - Fork 827
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
2nd alternative fix: allow to change or delete a relyingPartySecret o…
…n IdP (#2896) * WIP: idp secret * feature: delete secret on existing IdP - allow to delete a relyingPartySecret on IdP - Filter IdP list by origin - Return the auth_method to show current configured client authentication method * Documentation * fix names * sonar * sonar * Add patch call to change a secret from an external IdP * Alias handling * 2nd alternative fix: allow to change or delete a relyingPartySecret on IdP Alternative to PR: #2882, #2887 and PR: #2885 Only one call in backend, but more input on client side. authMethod is used to make this change non-breakable. Because before the update prevented the removal of the relyingPartySecret. No if authMethod is not client_secret_basic or client_secret_post, then the relyingPartySecret can be overwritten with null. * sonar * Tests added * Sonar smell * Review * more checks for edge cases * more tests to cover edge cases * Review Again fixed an edge case CLIENT_SECRET_BASIC, CLIENT_SECRET_POST both same method, therefore treat them equal * Review Again fixed an edge case Found during tests * Test refactored * small doc fixes - some clarification & formatting - no need to call out what the default is in the description because the `.optional("client_secret_basic")` syntax would automatically add that language. * doc: clarify when external OIDC client auth requirements - clarify when config.jwtClientAuthentication and config.relyingPartySecret are required in relation to the new field config.authMethod * Review, removed auth_method which is not used, but we ue authMethod field only * revert this * remove deprecated --------- Co-authored-by: Peter Chen <peter-h.chen@broadcom.com>
- Loading branch information
1 parent
b382c9f
commit 5812d75
Showing
12 changed files
with
331 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
model/src/main/java/org/cloudfoundry/identity/uaa/constants/ClientAuthentication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package org.cloudfoundry.identity.uaa.constants; | ||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
|
||
/** | ||
* ClientAuthentication constants are defined in OIDC core and discovery standard, e.g. https://openid.net/specs/openid-connect-registration-1_0.html | ||
* OIDC possible values are: client_secret_post, client_secret_basic, client_secret_jwt, private_key_jwt, and none | ||
* UAA knows only: client_secret_post, client_secret_basic, private_key_jwt, and none | ||
* | ||
* Planned: tls_client_auth | ||
*/ | ||
public final class ClientAuthentication { | ||
|
||
private ClientAuthentication() {} | ||
|
||
public static final String CLIENT_SECRET_BASIC = "client_secret_basic"; | ||
public static final String CLIENT_SECRET_POST = "client_secret_post"; | ||
public static final String PRIVATE_KEY_JWT = "private_key_jwt"; | ||
public static final String NONE = "none"; | ||
|
||
public static final List<String> UAA_SUPPORTED_METHODS = List.of(CLIENT_SECRET_BASIC, CLIENT_SECRET_POST, NONE, PRIVATE_KEY_JWT); | ||
|
||
public static boolean secretNeeded(String method) { | ||
return method == null || CLIENT_SECRET_POST.equals(method) || CLIENT_SECRET_BASIC.equals(method); | ||
} | ||
|
||
public static boolean isMethodSupported(String method) { | ||
return Optional.ofNullable(method).map(UAA_SUPPORTED_METHODS::contains).orElse(true); | ||
} | ||
|
||
public static boolean isValidMethod(String method, boolean hasSecret, boolean hasKeyConfiguration) { | ||
return (isMethodSupported(method) && secretNeeded(method) && hasSecret && !hasKeyConfiguration || | ||
isMethodSupported(method) && !secretNeeded(method) && !hasSecret || | ||
(method == null && (!hasSecret || !hasKeyConfiguration))); | ||
} | ||
|
||
public static boolean isAuthMethodEqual(String method1, String method2) { | ||
return secretNeeded(method1) && secretNeeded(method2) || Objects.equals(method1, method2); | ||
} | ||
|
||
public static String getCalculatedMethod(String method, boolean hasSecret, boolean hasKeyConfiguration) { | ||
if (method != null && isMethodSupported(method)) { | ||
return method; | ||
} else { | ||
if (hasSecret) { | ||
return CLIENT_SECRET_BASIC; | ||
} else if (hasKeyConfiguration) { | ||
return PRIVATE_KEY_JWT; | ||
} else | ||
return NONE; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
model/src/test/java/org/cloudfoundry/identity/uaa/constants/ClientAuthenticationTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package org.cloudfoundry.identity.uaa.constants; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.cloudfoundry.identity.uaa.constants.ClientAuthentication.CLIENT_SECRET_BASIC; | ||
import static org.cloudfoundry.identity.uaa.constants.ClientAuthentication.CLIENT_SECRET_POST; | ||
import static org.cloudfoundry.identity.uaa.constants.ClientAuthentication.NONE; | ||
import static org.cloudfoundry.identity.uaa.constants.ClientAuthentication.PRIVATE_KEY_JWT; | ||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertFalse; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
class ClientAuthenticationTest { | ||
|
||
@Test | ||
void secretNeeded() { | ||
assertTrue(ClientAuthentication.secretNeeded(CLIENT_SECRET_POST)); | ||
assertTrue(ClientAuthentication.secretNeeded(CLIENT_SECRET_BASIC)); | ||
assertFalse(ClientAuthentication.secretNeeded(NONE)); | ||
assertFalse(ClientAuthentication.secretNeeded(PRIVATE_KEY_JWT)); | ||
} | ||
|
||
@Test | ||
void isMethodSupported() { | ||
assertTrue(ClientAuthentication.isMethodSupported(CLIENT_SECRET_POST)); | ||
assertFalse(ClientAuthentication.isMethodSupported("foo")); | ||
} | ||
|
||
@Test | ||
void isValidMethodTrue() { | ||
assertTrue(ClientAuthentication.isValidMethod(NONE, false, false)); | ||
assertTrue(ClientAuthentication.isValidMethod(PRIVATE_KEY_JWT, false, true)); | ||
assertTrue(ClientAuthentication.isValidMethod(CLIENT_SECRET_POST, true, false)); | ||
assertTrue(ClientAuthentication.isValidMethod(CLIENT_SECRET_BASIC, true, false)); | ||
// legacy checks, no method passed | ||
assertTrue(ClientAuthentication.isValidMethod(null, false, false)); | ||
assertTrue(ClientAuthentication.isValidMethod(null, true, false)); | ||
assertTrue(ClientAuthentication.isValidMethod(null, false, true)); | ||
|
||
} | ||
|
||
@Test | ||
void isValidMethodFalse() { | ||
assertFalse(ClientAuthentication.isValidMethod(CLIENT_SECRET_BASIC, false, false)); | ||
assertFalse(ClientAuthentication.isValidMethod(CLIENT_SECRET_POST, false, false)); | ||
assertFalse(ClientAuthentication.isValidMethod(NONE, true, false)); | ||
assertFalse(ClientAuthentication.isValidMethod(PRIVATE_KEY_JWT, true, true)); | ||
assertFalse(ClientAuthentication.isValidMethod(CLIENT_SECRET_BASIC, true, true)); | ||
// legacy checks, no method passed | ||
assertFalse(ClientAuthentication.isValidMethod(null, true, true)); | ||
} | ||
|
||
@Test | ||
void getCalculatedMethod() { | ||
assertEquals(NONE, ClientAuthentication.getCalculatedMethod(NONE, false, false)); | ||
assertEquals(NONE, ClientAuthentication.getCalculatedMethod(null, false, false)); | ||
assertEquals(PRIVATE_KEY_JWT, ClientAuthentication.getCalculatedMethod(PRIVATE_KEY_JWT, false, true)); | ||
assertEquals(PRIVATE_KEY_JWT, ClientAuthentication.getCalculatedMethod(null, false, true)); | ||
assertEquals(CLIENT_SECRET_BASIC, ClientAuthentication.getCalculatedMethod(CLIENT_SECRET_BASIC, true, false)); | ||
assertEquals(CLIENT_SECRET_BASIC, ClientAuthentication.getCalculatedMethod(null, true, false)); | ||
} | ||
|
||
@Test | ||
void isAuthMethodEqualTrue() { | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(NONE, NONE)); | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(CLIENT_SECRET_BASIC, CLIENT_SECRET_POST)); | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(CLIENT_SECRET_POST, CLIENT_SECRET_BASIC)); | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(CLIENT_SECRET_BASIC, CLIENT_SECRET_BASIC)); | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(CLIENT_SECRET_POST, CLIENT_SECRET_POST)); | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(PRIVATE_KEY_JWT, PRIVATE_KEY_JWT)); | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(null, null)); | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(null, CLIENT_SECRET_BASIC)); | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(null, CLIENT_SECRET_POST)); | ||
assertTrue(ClientAuthentication.isAuthMethodEqual(CLIENT_SECRET_BASIC, null)); | ||
} | ||
|
||
@Test | ||
void isAuthMethodEqualFalse() { | ||
assertFalse(ClientAuthentication.isAuthMethodEqual(PRIVATE_KEY_JWT, null)); | ||
assertFalse(ClientAuthentication.isAuthMethodEqual(PRIVATE_KEY_JWT, CLIENT_SECRET_BASIC)); | ||
assertFalse(ClientAuthentication.isAuthMethodEqual(PRIVATE_KEY_JWT, NONE)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.