Repository: syncope Updated Branches: refs/heads/2_0_X d1e14c106 -> d9105ee8a refs/heads/master 3fc8bf3ef -> a5311460f
[SYNCOPE-1088] Storing Spring Security authorities with AccessToken entities (not for admin) Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/a5311460 Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/a5311460 Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/a5311460 Branch: refs/heads/master Commit: a5311460f81e50852978fa6823905b10d36700c6 Parents: 3fc8bf3 Author: Francesco Chicchiriccò <[email protected]> Authored: Mon May 22 13:23:46 2017 +0200 Committer: Francesco Chicchiriccò <[email protected]> Committed: Mon May 22 13:24:01 2017 +0200 ---------------------------------------------------------------------- .../client/console/SyncopeConsoleSession.java | 4 +- .../client/enduser/SyncopeEnduserSession.java | 2 +- .../apache/syncope/core/logic/AnyTypeLogic.java | 16 +--- .../persistence/api/entity/AccessToken.java | 4 + .../persistence/jpa/entity/JPAAccessToken.java | 14 +++ .../core/persistence/jpa/entity/JPADomain.java | 4 +- .../persistence/jpa/entity/user/JPAUser.java | 8 +- .../core/provisioning/api/AuditManager.java | 2 +- .../provisioning/api/EntitlementsHolder.java | 14 ++- .../api/data/AnyTypeDataBinder.java | 2 + .../java/data/AccessTokenDataBinderImpl.java | 34 ++++++++ .../java/data/AnyTypeDataBinderImpl.java | 89 ++++++++++++++++++++ .../java/data/UserDataBinderImpl.java | 6 +- .../core/spring/security/AuthContextUtils.java | 18 ++++ .../core/spring/security/AuthDataAccessor.java | 25 +++++- .../UsernamePasswordAuthenticationProvider.java | 8 +- 16 files changed, 219 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java ---------------------------------------------------------------------- diff --git a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java index 2fbefe2..3d3daf8 100644 --- a/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java +++ b/client/console/src/main/java/org/apache/syncope/client/console/SyncopeConsoleSession.java @@ -143,8 +143,8 @@ public class SyncopeConsoleSession extends AuthenticatedWebSession { private void afterAuthentication() { Pair<Map<String, Set<String>>, UserTO> self = client.self(); - auth = self.getKey(); - selfTO = self.getValue(); + auth = self.getLeft(); + selfTO = self.getRight(); } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java ---------------------------------------------------------------------- diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java index 8268ef5..cd94d0c 100644 --- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java +++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/SyncopeEnduserSession.java @@ -101,7 +101,7 @@ public class SyncopeEnduserSession extends WebSession { private void afterAuthentication() { Pair<Map<String, Set<String>>, UserTO> self = client.self(); - selfTO = self.getValue(); + selfTO = self.getRight(); // bind explicitly this session to have a stateful behavior during http requests, unless session will // expire for every request http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java index 2a5e89b..b21ab45 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java @@ -29,7 +29,6 @@ import org.apache.syncope.common.lib.SyncopeClientException; import org.apache.syncope.common.lib.to.AnyTypeTO; import org.apache.syncope.common.lib.types.ClientExceptionType; import org.apache.syncope.common.lib.types.StandardEntitlement; -import org.apache.syncope.core.provisioning.api.EntitlementsHolder; import org.apache.syncope.core.persistence.api.dao.NotFoundException; import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO; import org.apache.syncope.core.persistence.api.dao.DuplicateException; @@ -82,9 +81,7 @@ public class AnyTypeLogic extends AbstractTransactionalLogic<AnyTypeTO> { throw new DuplicateException(anyTypeTO.getKey()); } - AnyTypeTO result = binder.getAnyTypeTO(anyTypeDAO.save(binder.create(anyTypeTO))); - EntitlementsHolder.getInstance().addFor(result.getKey()); - return result; + return binder.getAnyTypeTO(anyTypeDAO.save(binder.create(anyTypeTO))); } @PreAuthorize("hasRole('" + StandardEntitlement.ANYTYPE_UPDATE + "')") @@ -95,14 +92,10 @@ public class AnyTypeLogic extends AbstractTransactionalLogic<AnyTypeTO> { throw new NotFoundException(anyTypeTO.getKey()); } - EntitlementsHolder.getInstance().removeFor(anyTypeTO.getKey()); - binder.update(anyType, anyTypeTO); anyType = anyTypeDAO.save(anyType); - AnyTypeTO result = binder.getAnyTypeTO(anyType); - EntitlementsHolder.getInstance().addFor(result.getKey()); - return result; + return binder.getAnyTypeTO(anyTypeDAO.save(anyType)); } @PreAuthorize("hasRole('" + StandardEntitlement.ANYTYPE_DELETE + "')") @@ -114,16 +107,13 @@ public class AnyTypeLogic extends AbstractTransactionalLogic<AnyTypeTO> { throw new NotFoundException(key); } - AnyTypeTO deleted = binder.getAnyTypeTO(anyType); try { - anyTypeDAO.delete(key); - EntitlementsHolder.getInstance().removeFor(deleted.getKey()); + return binder.delete(anyType); } catch (IllegalArgumentException e) { SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidAnyType); sce.getElements().add(e.getMessage()); throw sce; } - return deleted; } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java ---------------------------------------------------------------------- diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java index e08e9e3..ee68d6c 100644 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AccessToken.java @@ -33,4 +33,8 @@ public interface AccessToken extends ProvidedKeyEntity { String getOwner(); void setOwner(String owner); + + byte[] getAuthorities(); + + void setAuthorities(byte[] authorities); } http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccessToken.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccessToken.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccessToken.java index 05464d6..4ddaed1 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccessToken.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAccessToken.java @@ -26,6 +26,7 @@ import javax.persistence.Lob; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; +import org.apache.commons.lang3.ArrayUtils; import org.apache.syncope.core.persistence.api.entity.AccessToken; @Entity @@ -46,6 +47,9 @@ public class JPAAccessToken extends AbstractProvidedKeyEntity implements AccessT @Column(nullable = true) private String owner; + @Lob + private byte[] authorities; + @Override public String getBody() { return body; @@ -80,4 +84,14 @@ public class JPAAccessToken extends AbstractProvidedKeyEntity implements AccessT this.owner = owner; } + @Override + public byte[] getAuthorities() { + return authorities; + } + + @Override + public void setAuthorities(final byte[] authorities) { + this.authorities = ArrayUtils.clone(authorities); + } + } http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java index 5e6a80f..7e0c456 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java @@ -36,6 +36,8 @@ public class JPADomain extends AbstractProvidedKeyEntity implements Domain { public static final String TABLE = "SyncopeDomain"; + private static final Encryptor ENCRYPTOR = Encryptor.getInstance(); + private String adminPwd; @Enumerated(EnumType.STRING) @@ -54,7 +56,7 @@ public class JPADomain extends AbstractProvidedKeyEntity implements Domain { @Override public void setPassword(final String password, final CipherAlgorithm cipherAlgoritm) { try { - this.adminPwd = Encryptor.getInstance().encode(password, cipherAlgoritm); + this.adminPwd = ENCRYPTOR.encode(password, cipherAlgoritm); this.adminCipherAlgorithm = cipherAlgoritm; } catch (Exception e) { LOG.error("Could not encode password", e); http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java index ba1544d..0dddb77 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java @@ -78,6 +78,8 @@ public class JPAUser public static final String TABLE = "SyncopeUser"; + private static final Encryptor ENCRYPTOR = Encryptor.getInstance(); + @Column(nullable = true) private String password; @@ -256,7 +258,7 @@ public class JPAUser this.clearPassword = password; try { - this.password = Encryptor.getInstance().encode(password, cipherAlgoritm); + this.password = ENCRYPTOR.encode(password, cipherAlgoritm); this.cipherAlgorithm = cipherAlgoritm; } catch (Exception e) { LOG.error("Could not encode password", e); @@ -460,8 +462,8 @@ public class JPAUser res = passwordHistory.subList(size >= passwordHistory.size() ? 0 : passwordHistory.size() - size, passwordHistory.size()).contains(cipherAlgorithm == null - ? password - : Encryptor.getInstance().encode(password, cipherAlgorithm)); + ? password + : ENCRYPTOR.encode(password, cipherAlgorithm)); } catch (Exception e) { LOG.error("Error evaluating password history", e); } http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/AuditManager.java ---------------------------------------------------------------------- diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/AuditManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/AuditManager.java index 333d415..64c03e9 100644 --- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/AuditManager.java +++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/AuditManager.java @@ -45,7 +45,7 @@ public interface AuditManager { * @param subcategory event subcategory * @param event event * @param condition result value condition. - * @param before object(s) availabile before the event + * @param before object(s) available before the event * @param output object(s) produced by the event * @param input object(s) provided to the event */ http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/EntitlementsHolder.java ---------------------------------------------------------------------- diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/EntitlementsHolder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/EntitlementsHolder.java index 53a86f5..bb7eab8 100644 --- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/EntitlementsHolder.java +++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/EntitlementsHolder.java @@ -50,16 +50,26 @@ public final class EntitlementsHolder { this.values.addAll(values); } - public void addFor(final String anyType) { + public Set<String> addFor(final String anyType) { + Set<String> added = new HashSet<>(); + for (AnyEntitlement operation : AnyEntitlement.values()) { this.values.add(operation.getFor(anyType)); + added.add(operation.getFor(anyType)); } + + return added; } - public void removeFor(final String anyType) { + public Set<String> removeFor(final String anyType) { + Set<String> removed = new HashSet<>(); + for (AnyEntitlement operation : AnyEntitlement.values()) { this.values.remove(operation.getFor(anyType)); + removed.add(operation.getFor(anyType)); } + + return removed; } public Set<String> getValues() { http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeDataBinder.java ---------------------------------------------------------------------- diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeDataBinder.java index c29c2ac..e644121 100644 --- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeDataBinder.java +++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeDataBinder.java @@ -27,5 +27,7 @@ public interface AnyTypeDataBinder { void update(AnyType anyType, AnyTypeTO anyTypeTO); + AnyTypeTO delete(AnyType anyType); + AnyTypeTO getAnyTypeTO(AnyType anyType); } http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java ---------------------------------------------------------------------- diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java index b278e30..6bca7e0 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AccessTokenDataBinderImpl.java @@ -34,24 +34,37 @@ import org.apache.cxf.rs.security.jose.jws.JwsSignatureProvider; import org.apache.cxf.rs.security.jose.jwt.JwtClaims; import org.apache.cxf.rs.security.jose.jwt.JwtToken; import org.apache.syncope.common.lib.to.AccessTokenTO; +import org.apache.syncope.common.lib.types.CipherAlgorithm; import org.apache.syncope.core.persistence.api.dao.AccessTokenDAO; import org.apache.syncope.core.persistence.api.dao.ConfDAO; import org.apache.syncope.core.persistence.api.entity.AccessToken; import org.apache.syncope.core.persistence.api.entity.EntityFactory; import org.apache.syncope.core.provisioning.api.data.AccessTokenDataBinder; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; import org.apache.syncope.core.spring.BeanUtils; +import org.apache.syncope.core.spring.security.AuthContextUtils; +import org.apache.syncope.core.spring.security.Encryptor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class AccessTokenDataBinderImpl implements AccessTokenDataBinder { + private static final Logger LOG = LoggerFactory.getLogger(AccessTokenDataBinder.class); + + private static final Encryptor ENCRYPTOR = Encryptor.getInstance(); + private static final String[] IGNORE_PROPERTIES = { "owner" }; private static final RandomBasedGenerator UUID_GENERATOR = Generators.randomBasedGenerator(); private static final JwsHeaders JWS_HEADERS = new JwsHeaders(JoseType.JWT, SignatureAlgorithm.HS512); + @Resource(name = "adminUser") + private String adminUser; + @Resource(name = "jwtIssuer") private String jwtIssuer; @@ -118,6 +131,17 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder { accessToken.setBody(body); accessToken.setExpiryTime(created.getRight()); accessToken.setOwner(subject); + + if (!adminUser.equals(accessToken.getOwner())) { + try { + accessToken.setAuthorities(ENCRYPTOR.encode( + POJOHelper.serialize(AuthContextUtils.getAuthorities()), CipherAlgorithm.AES). + getBytes()); + } catch (Exception e) { + LOG.error("Could not store authorities", e); + } + } + accessTokenDAO.save(accessToken); } @@ -147,6 +171,16 @@ public class AccessTokenDataBinderImpl implements AccessTokenDataBinder { accessToken.setBody(body); accessToken.setExpiryTime(expiry.getTime()); + if (!adminUser.equals(accessToken.getOwner())) { + try { + accessToken.setAuthorities(ENCRYPTOR.encode( + POJOHelper.serialize(AuthContextUtils.getAuthorities()), CipherAlgorithm.AES). + getBytes()); + } catch (Exception e) { + LOG.error("Could not store authorities", e); + } + } + accessTokenDAO.save(accessToken); return body; http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java ---------------------------------------------------------------------- diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java index f74efbc..84d9bd9 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java @@ -18,15 +18,31 @@ */ package org.apache.syncope.core.provisioning.java.data; +import com.fasterxml.jackson.core.type.TypeReference; +import java.util.HashSet; +import java.util.Set; +import javax.annotation.Resource; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Predicate; import org.apache.syncope.common.lib.SyncopeClientException; +import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.to.AnyTypeTO; import org.apache.syncope.common.lib.types.AnyTypeKind; +import org.apache.syncope.common.lib.types.CipherAlgorithm; import org.apache.syncope.common.lib.types.ClientExceptionType; +import org.apache.syncope.core.persistence.api.dao.AccessTokenDAO; import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO; +import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO; +import org.apache.syncope.core.persistence.api.entity.AccessToken; import org.apache.syncope.core.persistence.api.entity.EntityFactory; import org.apache.syncope.core.persistence.api.entity.AnyType; import org.apache.syncope.core.persistence.api.entity.AnyTypeClass; +import org.apache.syncope.core.provisioning.api.EntitlementsHolder; import org.apache.syncope.core.provisioning.api.data.AnyTypeDataBinder; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.apache.syncope.core.spring.security.AuthContextUtils; +import org.apache.syncope.core.spring.security.Encryptor; +import org.apache.syncope.core.spring.security.SyncopeGrantedAuthority; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -37,16 +53,52 @@ public class AnyTypeDataBinderImpl implements AnyTypeDataBinder { private static final Logger LOG = LoggerFactory.getLogger(AnyTypeDataBinder.class); + private static final Encryptor ENCRYPTOR = Encryptor.getInstance(); + + @Resource(name = "adminUser") + private String adminUser; + + @Autowired + private AnyTypeDAO anyTypeDAO; + @Autowired private AnyTypeClassDAO anyTypeClassDAO; @Autowired + private AccessTokenDAO accessTokenDAO; + + @Autowired private EntityFactory entityFactory; @Override public AnyType create(final AnyTypeTO anyTypeTO) { AnyType anyType = entityFactory.newEntity(AnyType.class); update(anyType, anyTypeTO); + + Set<String> added = EntitlementsHolder.getInstance().addFor(anyType.getKey()); + + if (!adminUser.equals(AuthContextUtils.getUsername())) { + AccessToken accessToken = accessTokenDAO.findByOwner(AuthContextUtils.getUsername()); + try { + Set<SyncopeGrantedAuthority> authorities = new HashSet<>(POJOHelper.deserialize( + ENCRYPTOR.decode(new String(accessToken.getAuthorities()), CipherAlgorithm.AES), + new TypeReference<Set<SyncopeGrantedAuthority>>() { + })); + + for (String entitlement : added) { + authorities.add(new SyncopeGrantedAuthority(entitlement, SyncopeConstants.ROOT_REALM)); + } + + accessToken.setAuthorities(ENCRYPTOR.encode( + POJOHelper.serialize(authorities), CipherAlgorithm.AES). + getBytes()); + + accessTokenDAO.save(accessToken); + } catch (Exception e) { + LOG.error("Could not fetch or store authorities", e); + } + } + return anyType; } @@ -76,6 +128,43 @@ public class AnyTypeDataBinderImpl implements AnyTypeDataBinder { } @Override + public AnyTypeTO delete(final AnyType anyType) { + AnyTypeTO deleted = getAnyTypeTO(anyType); + + anyTypeDAO.delete(anyType.getKey()); + + final Set<String> removed = EntitlementsHolder.getInstance().removeFor(deleted.getKey()); + + if (!adminUser.equals(AuthContextUtils.getUsername())) { + AccessToken accessToken = accessTokenDAO.findByOwner(AuthContextUtils.getUsername()); + try { + Set<SyncopeGrantedAuthority> authorities = new HashSet<>(POJOHelper.deserialize( + ENCRYPTOR.decode(new String(accessToken.getAuthorities()), CipherAlgorithm.AES), + new TypeReference<Set<SyncopeGrantedAuthority>>() { + })); + + CollectionUtils.filterInverse(authorities, new Predicate<SyncopeGrantedAuthority>() { + + @Override + public boolean evaluate(final SyncopeGrantedAuthority authority) { + return removed.contains(authority.getAuthority()); + } + }); + + accessToken.setAuthorities(ENCRYPTOR.encode( + POJOHelper.serialize(authorities), CipherAlgorithm.AES). + getBytes()); + + accessTokenDAO.save(accessToken); + } catch (Exception e) { + LOG.error("Could not fetch or store authorities", e); + } + } + + return deleted; + } + + @Override public AnyTypeTO getAnyTypeTO(final AnyType anyType) { AnyTypeTO anyTypeTO = new AnyTypeTO(); http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java ---------------------------------------------------------------------- diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java index 2ba5d85..647e850 100644 --- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java +++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java @@ -89,6 +89,8 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat "plainAttrs", "derAttrs", "virAttrs", "resources", "securityQuestion", "securityAnswer" }; + private static final Encryptor ENCRYPTOR = Encryptor.getInstance(); + @Autowired private RoleDAO roleDAO; @@ -110,8 +112,6 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat @Resource(name = "anonymousUser") private String anonymousUser; - private final Encryptor encryptor = Encryptor.getInstance(); - @Transactional(readOnly = true) @Override public UserTO returnUserTO(final UserTO userTO) { @@ -152,7 +152,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat @Transactional(readOnly = true) @Override public boolean verifyPassword(final User user, final String password) { - return encryptor.verify(password, user.getCipherAlgorithm(), user.getPassword()); + return ENCRYPTOR.verify(password, user.getCipherAlgorithm(), user.getPassword()); } private void setPassword(final User user, final String password, final SyncopeClientCompositeException scce) { http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java ---------------------------------------------------------------------- diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java index 36e4188..cc0b4fd 100644 --- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java +++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java @@ -19,7 +19,9 @@ package org.apache.syncope.core.spring.security; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -63,6 +65,22 @@ public final class AuthContextUtils { SecurityContextHolder.getContext().setAuthentication(newAuth); } + public static Set<SyncopeGrantedAuthority> getAuthorities() { + SecurityContext ctx = SecurityContextHolder.getContext(); + if (ctx != null && ctx.getAuthentication() != null && ctx.getAuthentication().getAuthorities() != null) { + Set<SyncopeGrantedAuthority> result = new HashSet<>(); + for (GrantedAuthority authority : ctx.getAuthentication().getAuthorities()) { + if (authority instanceof SyncopeGrantedAuthority) { + result.add(SyncopeGrantedAuthority.class.cast(authority)); + } + } + + return result; + } + + return Collections.emptySet(); + } + public static Map<String, Set<String>> getAuthorizations() { Map<String, Set<String>> result = null; http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java ---------------------------------------------------------------------- diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java index b54d756..aba2e50 100644 --- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java +++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java @@ -18,6 +18,7 @@ */ package org.apache.syncope.core.spring.security; +import com.fasterxml.jackson.core.type.TypeReference; import java.util.Arrays; import java.util.Collections; import java.util.Date; @@ -38,6 +39,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.types.AnyTypeKind; import org.apache.syncope.common.lib.types.AuditElements; +import org.apache.syncope.common.lib.types.CipherAlgorithm; import org.apache.syncope.common.lib.types.StandardEntitlement; import org.apache.syncope.core.persistence.api.dao.AccessTokenDAO; import org.apache.syncope.core.persistence.api.dao.AnySearchDAO; @@ -62,6 +64,7 @@ import org.apache.syncope.core.provisioning.api.AuditManager; import org.apache.syncope.core.provisioning.api.ConnectorFactory; import org.apache.syncope.core.provisioning.api.EntitlementsHolder; import org.apache.syncope.core.provisioning.api.MappingManager; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; import org.identityconnectors.framework.common.objects.Uid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -362,6 +365,7 @@ public class AuthDataAccessor { } Set<SyncopeGrantedAuthority> authorities; + if (adminUser.equals(accessToken.getOwner())) { authorities = getAdminAuthorities(); } else { @@ -381,7 +385,26 @@ public class AuthDataAccessor { throw new DisabledException("User " + user.getUsername() + " not allowed to authenticate"); } - authorities = getUserAuthorities(user); + if (user.isMustChangePassword()) { + authorities = Collections.singleton( + new SyncopeGrantedAuthority(StandardEntitlement.MUST_CHANGE_PASSWORD)); + } else if (accessToken.getAuthorities() == null) { + LOG.debug("No authorities found in JWT, calculating..."); + + authorities = getUserAuthorities(user); + } else { + LOG.debug("Authorities found in JWT, fetching..."); + + try { + authorities = POJOHelper.deserialize( + ENCRYPTOR.decode(new String(accessToken.getAuthorities()), CipherAlgorithm.AES), + new TypeReference<Set<SyncopeGrantedAuthority>>() { + }); + } catch (Exception e) { + LOG.error("Could not read stored authorities", e); + authorities = Collections.emptySet(); + } + } } return authorities; http://git-wip-us.apache.org/repos/asf/syncope/blob/a5311460/core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java index 83a03c3..28cc970 100644 --- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java +++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/UsernamePasswordAuthenticationProvider.java @@ -42,6 +42,8 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro protected static final Logger LOG = LoggerFactory.getLogger(UsernamePasswordAuthenticationProvider.class); + protected static final Encryptor ENCRYPTOR = Encryptor.getInstance(); + @Autowired protected AuthDataAccessor dataAccessor; @@ -63,8 +65,6 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro @Resource(name = "anonymousKey") protected String anonymousKey; - protected final Encryptor encryptor = Encryptor.getInstance(); - /** * @param adminPassword the adminPassword to set */ @@ -99,7 +99,7 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro } else if (adminUser.equals(authentication.getName())) { username[0] = adminUser; if (SyncopeConstants.MASTER_DOMAIN.equals(domainKey)) { - authenticated = encryptor.verify( + authenticated = ENCRYPTOR.verify( authentication.getCredentials().toString(), CipherAlgorithm.valueOf(adminPasswordAlgorithm), adminPassword); @@ -112,7 +112,7 @@ public class UsernamePasswordAuthenticationProvider implements AuthenticationPro public Boolean exec() { Domain domain = dataAccessor.findDomain(domainToFind); - return encryptor.verify( + return ENCRYPTOR.verify( authentication.getCredentials().toString(), domain.getAdminCipherAlgorithm(), domain.getAdminPwd());
