This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new f96ddd329b ISIS-3283: fixes unreachable code in keycloak integration
f96ddd329b is described below
commit f96ddd329ba8ab54fa94031f38f0425235ef8ed1
Author: andi-huber <[email protected]>
AuthorDate: Sat Nov 19 08:51:35 2022 +0100
ISIS-3283: fixes unreachable code in keycloak integration
---
security/keycloak/src/main/java/module-info.java | 1 +
.../services/KeycloakOauth2UserService.java | 112 ++++++++++-----------
2 files changed, 56 insertions(+), 57 deletions(-)
diff --git a/security/keycloak/src/main/java/module-info.java
b/security/keycloak/src/main/java/module-info.java
index ba9fcba7d5..b964fd68d4 100644
--- a/security/keycloak/src/main/java/module-info.java
+++ b/security/keycloak/src/main/java/module-info.java
@@ -39,4 +39,5 @@ module org.apache.causeway.security.keycloak {
requires spring.security.oauth2.jose;
requires spring.security.web;
requires spring.web;
+ requires org.apache.causeway.commons;
}
\ No newline at end of file
diff --git
a/security/keycloak/src/main/java/org/apache/causeway/security/keycloak/services/KeycloakOauth2UserService.java
b/security/keycloak/src/main/java/org/apache/causeway/security/keycloak/services/KeycloakOauth2UserService.java
index 88e561b459..8fd40dc317 100644
---
a/security/keycloak/src/main/java/org/apache/causeway/security/keycloak/services/KeycloakOauth2UserService.java
+++
b/security/keycloak/src/main/java/org/apache/causeway/security/keycloak/services/KeycloakOauth2UserService.java
@@ -26,7 +26,10 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import org.springframework.lang.Nullable;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import
org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
@@ -42,8 +45,11 @@ import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtException;
import org.springframework.util.CollectionUtils;
+import org.apache.causeway.commons.internal.base._Casts;
+import org.apache.causeway.commons.internal.base._NullSafe;
import org.apache.causeway.core.config.CausewayConfiguration;
+import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.val;
@@ -65,7 +71,7 @@ public class KeycloakOauth2UserService extends
OidcUserService {
* {@link OidcUserRequest}.
*/
@Override
- public OidcUser loadUser(OidcUserRequest userRequest) throws
OAuth2AuthenticationException {
+ public OidcUser loadUser(final OidcUserRequest userRequest) throws
OAuth2AuthenticationException {
OidcUser user = super.loadUser(userRequest);
@@ -83,75 +89,45 @@ public class KeycloakOauth2UserService extends
OidcUserService {
* @param userRequest
* @return
*/
- private Collection<? extends GrantedAuthority>
extractKeycloakAuthorities(OidcUserRequest userRequest) {
+ private Collection<? extends GrantedAuthority>
extractKeycloakAuthorities(final OidcUserRequest userRequest) {
Jwt token = parseJwt(userRequest.getAccessToken().getTokenValue());
- List<String> combinedRoles = new ArrayList<>();
+ final List<String> combinedRoles = new ArrayList<>();
if(causewayConfiguration.getSecurity().getKeycloak().isExtractClientRoles()) {
-
// attempt to parse out 'resource_access.${client_id}.roles'
-
- val resourceObj = token.getClaims().get("resource_access");
- if (resourceObj instanceof Map) {
- @SuppressWarnings("rawtypes")
- val resourceMap = (Map) resourceObj;
-
- val clientId =
userRequest.getClientRegistration().getClientId();
- val clientResourceObj = resourceMap.get(clientId);
- if(clientResourceObj instanceof Map) {
- @SuppressWarnings("rawtypes")
- val clientResource = (Map) clientResourceObj;
- if (!CollectionUtils.isEmpty(clientResource)) {
- val clientRolesObj = clientResource.get("roles");
- if (clientResourceObj instanceof List) {
- @SuppressWarnings("unchecked")
- val clientRoles = (List<Object>) clientRolesObj;
- if (!CollectionUtils.isEmpty(clientRoles)) {
- val prefix =
Optional.ofNullable(causewayConfiguration.getSecurity().getKeycloak().getClientRolePrefix()).orElse("");
- clientRoles.stream()
- .filter(Objects::nonNull)
- .map(clientRole -> prefix + clientRole)
- .forEach(combinedRoles::add);
- }
- }
- }
- }
- }
+ val rolePrefix =
Optional.ofNullable(causewayConfiguration.getSecurity().getKeycloak().getClientRolePrefix()).orElse("");
+ asNonEmptyMap(token.getClaims().get("resource_access"))
+ .ifPresent(resourceMap->{
+ final String clientId =
userRequest.getClientRegistration().getClientId();
+ asNonEmptyMap(resourceMap.get(clientId))
+
.flatMap(clientResource->asNonEmptyCollection(clientResource.get("roles")))
+ .ifPresent(clientRoles->
+ forEachNonNullIn(clientRoles, clientRole ->
combinedRoles.add(rolePrefix + clientRole))
+ );
+ });
}
if
(causewayConfiguration.getSecurity().getKeycloak().isExtractRealmRoles()) {
// attempt to parse out 'realm_access.roles'
- val realmAccessObj = token.getClaims().get("realm_access");
- if (realmAccessObj instanceof Map) {
- @SuppressWarnings("rawtypes")
- val realmAccessMap = (Map)realmAccessObj;
- Object realmRolesObj = realmAccessMap.get("roles");
- if (realmRolesObj instanceof List) {
- @SuppressWarnings("unchecked")
- val realmRoles = (List<Object>) realmRolesObj;
- val prefix =
Optional.ofNullable(causewayConfiguration.getSecurity().getKeycloak().getRealmRolePrefix()).orElse("");
- realmRoles.stream()
- .filter(Objects::nonNull)
- .map(realmRole -> prefix + realmRole)
- .forEach(combinedRoles::add);
- }
- }
+ val rolePrefix =
Optional.ofNullable(causewayConfiguration.getSecurity().getKeycloak().getRealmRolePrefix()).orElse("");
+ asNonEmptyMap(token.getClaims().get("realm_access"))
+ .ifPresent(realmAccessMap->{
+ asNonEmptyCollection(realmAccessMap.get("roles"))
+ .ifPresent(realmRoles->{
+ forEachNonNullIn(realmRoles, realmRole ->
combinedRoles.add(rolePrefix + realmRole));
+ });
+ });
}
if
(causewayConfiguration.getSecurity().getKeycloak().isExtractRoles()) {
// attempt to parse out 'roles'
- val rolesObj = token.getClaims().get("roles");
- if (rolesObj instanceof List) {
- @SuppressWarnings("unchecked")
- val roles = (List<Object>) rolesObj;
- val prefix =
Optional.ofNullable(causewayConfiguration.getSecurity().getKeycloak().getRolePrefix()).orElse("");
- roles.stream()
- .filter(Objects::nonNull)
- .map(role -> prefix + role)
- .forEach(combinedRoles::add);
- }
+ val rolePrefix =
Optional.ofNullable(causewayConfiguration.getSecurity().getKeycloak().getRolePrefix()).orElse("");
+ asNonEmptyCollection(token.getClaims().get("roles"))
+ .ifPresent(roles->{
+ forEachNonNullIn(roles, role -> combinedRoles.add(rolePrefix +
role));
+ });
}
Collection<? extends GrantedAuthority> authorities =
AuthorityUtils.createAuthorityList(combinedRoles.toArray(new String[]{}));
@@ -161,7 +137,29 @@ public class KeycloakOauth2UserService extends
OidcUserService {
}
- private Jwt parseJwt(String accessTokenValue) {
+ // -- HELPER
+
+ @SuppressWarnings("rawtypes")
+ private Optional<Map> asNonEmptyMap(final @Nullable Object x){
+ return _Casts.castTo(Map.class, x)
+ .filter(Predicate.not(_NullSafe::isEmpty));
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private void forEachNonNullIn(final @NonNull Collection x, final @NonNull
Consumer<Object> _do){
+ x.stream()
+ .filter(Objects::nonNull)
+ .forEach(_do);
+ }
+
+ @SuppressWarnings("rawtypes")
+ private Optional<Collection> asNonEmptyCollection(final @Nullable Object
x){
+ return _Casts.castTo(Collection.class, x)
+ .filter(Predicate.not(_NullSafe::isEmpty));
+ }
+
+
+ private Jwt parseJwt(final String accessTokenValue) {
try {
// Token is already verified by spring security infrastructure
return jwtDecoder.decode(accessTokenValue);