From dbdc2e777de1e91d8053280dee78233eab00cc04 Mon Sep 17 00:00:00 2001 From: Justin Richer Date: Tue, 10 Sep 2013 17:15:58 -0400 Subject: [PATCH] added pairwise identifier service and repository --- .../connect/model/PairwiseIdentifier.java | 118 ++++++++++++++++++ .../PairwiseIdentifierRepository.java | 39 ++++++ .../service/PairwiseIdentiferService.java | 22 ++++ .../impl/JpaPairwiseIdentifierRepository.java | 61 +++++++++ .../service/impl/DefaultUserInfoService.java | 42 ++++--- .../impl/UUIDPairwiseIdentiferService.java | 68 ++++++++++ .../db/tables/hsql_database_tables.sql | 8 ++ .../db/tables/mysql_database_tables.sql | 8 ++ 8 files changed, 347 insertions(+), 19 deletions(-) create mode 100644 openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java create mode 100644 openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java create mode 100644 openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java create mode 100644 openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java create mode 100644 openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java new file mode 100644 index 000000000..3feab0492 --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/PairwiseIdentifier.java @@ -0,0 +1,118 @@ +/** + * + */ +package org.mitre.openid.connect.model; + +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; + +/** + * + * Holds the generated pairwise identifiers for a user. Can be tied to either a client ID or a sector identifier URL. + * + * @author jricher + * + */ +@Entity +@Table(name = "pairwise_identifier") +@NamedQueries({ + @NamedQuery(name="PairwiseIdentifier.getAll", query = "select p from PairwiseIdentifier p"), + @NamedQuery(name="PairwiseIdentifier.getByClientId", query = "select p from PairwiseIdentifier p WHERE p.userSub = :sub AND p.clientId = :clientId"), + @NamedQuery(name="PairwiseIdentifier.getBySectorIdentifier", query = "select p from PairwiseIdentifier p WHERE p.userSub = :sub AND p.sectorIdentifier = :sectorIdentifier") +}) +public class PairwiseIdentifier { + + private Long id; + private String identifier; + private String userSub; + private String clientId; + private String sectorIdentifier; + + /** + * @return the id + */ + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name = "id") + public Long getId() { + return id; + } + + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + + /** + * @return the identifier + */ + @Basic + @Column(name = "identifier") + public String getIdentifier() { + return identifier; + } + + /** + * @param identifier the identifier to set + */ + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + /** + * @return the userSub + */ + @Basic + @Column(name = "sub") + public String getUserSub() { + return userSub; + } + + /** + * @param userSub the userSub to set + */ + public void setUserSub(String userSub) { + this.userSub = userSub; + } + + /** + * @return the clientId + */ + @Basic + @Column(name = "client_id") + public String getClientId() { + return clientId; + } + + /** + * @param clientId the clientId to set + */ + public void setClientId(String clientId) { + this.clientId = clientId; + } + + /** + * @return the sectorIdentifier + */ + @Basic + @Column(name = "sector_identifier") + public String getSectorIdentifier() { + return sectorIdentifier; + } + + /** + * @param sectorIdentifier the sectorIdentifier to set + */ + public void setSectorIdentifier(String sectorIdentifier) { + this.sectorIdentifier = sectorIdentifier; + } +} diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java new file mode 100644 index 000000000..574104b55 --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/PairwiseIdentifierRepository.java @@ -0,0 +1,39 @@ +/** + * + */ +package org.mitre.openid.connect.repository; + +import org.mitre.openid.connect.model.PairwiseIdentifier; + +/** + * @author jricher + * + */ +public interface PairwiseIdentifierRepository { + + /** + * Get a pairwise identifier by its associated user subject and sector identifier. + * + * @param sub + * @param sectorIdentifierUri + * @return + */ + public PairwiseIdentifier getBySectorIdentifier(String sub, String sectorIdentifierUri); + + /** + * Get a pairwise identifier by its associated user subject and client id. + * + * @param sub + * @param clientId + * @return + */ + public PairwiseIdentifier getByClientId(String sub, String clientId); + + /** + * Save a pairwise identifier to the database. + * + * @param pairwise + */ + public void save(PairwiseIdentifier pairwise); + +} diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java new file mode 100644 index 000000000..ef59a5390 --- /dev/null +++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/PairwiseIdentiferService.java @@ -0,0 +1,22 @@ +/** + * + */ +package org.mitre.openid.connect.service; + +import org.mitre.oauth2.model.ClientDetailsEntity; +import org.mitre.openid.connect.model.UserInfo; + +/** + * @author jricher + * + */ +public interface PairwiseIdentiferService { + + /** + * @param userInfo + * @param client + * @return + */ + public String getIdentifier(UserInfo userInfo, ClientDetailsEntity client); + +} diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java new file mode 100644 index 000000000..a4ad578d0 --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaPairwiseIdentifierRepository.java @@ -0,0 +1,61 @@ +/** + * + */ +package org.mitre.openid.connect.repository.impl; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.TypedQuery; + +import org.mitre.openid.connect.model.PairwiseIdentifier; +import org.mitre.openid.connect.repository.PairwiseIdentifierRepository; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import static org.mitre.util.jpa.JpaUtil.getSingleResult; +import static org.mitre.util.jpa.JpaUtil.saveOrUpdate; + +/** + * @author jricher + * + */ +@Repository +public class JpaPairwiseIdentifierRepository implements PairwiseIdentifierRepository { + + @PersistenceContext + private EntityManager manager; + + /* (non-Javadoc) + * @see org.mitre.openid.connect.repository.PairwiseIdentifierRepository#getBySectorIdentifier(java.lang.String, java.lang.String) + */ + @Override + public PairwiseIdentifier getBySectorIdentifier(String sub, String sectorIdentifierUri) { + TypedQuery query = manager.createNamedQuery("PairwiseIdentifier.getBySectorIdentifier", PairwiseIdentifier.class); + query.setParameter("sub", sub); + query.setParameter("sectorIdentifier", sectorIdentifierUri); + + return getSingleResult(query.getResultList()); + } + + /* (non-Javadoc) + * @see org.mitre.openid.connect.repository.PairwiseIdentifierRepository#getByClientId(java.lang.String, java.lang.String) + */ + @Override + public PairwiseIdentifier getByClientId(String sub, String clientId) { + TypedQuery query = manager.createNamedQuery("PairwiseIdentifier.getByClientId", PairwiseIdentifier.class); + query.setParameter("sub", sub); + query.setParameter("clientId", clientId); + + return getSingleResult(query.getResultList()); + } + + /* (non-Javadoc) + * @see org.mitre.openid.connect.repository.PairwiseIdentifierRepository#save(org.mitre.openid.connect.model.PairwiseIdentifier) + */ + @Override + @Transactional + public void save(PairwiseIdentifier pairwise) { + saveOrUpdate(pairwise.getId(), manager, pairwise); + } + +} diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java index 419e001f8..93c2d5efe 100644 --- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/DefaultUserInfoService.java @@ -20,10 +20,10 @@ import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.service.ClientDetailsEntityService; import org.mitre.openid.connect.model.UserInfo; import org.mitre.openid.connect.repository.UserInfoRepository; +import org.mitre.openid.connect.service.PairwiseIdentiferService; import org.mitre.openid.connect.service.UserInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; /** * Implementation of the UserInfoService @@ -40,6 +40,9 @@ public class DefaultUserInfoService implements UserInfoService { @Autowired private ClientDetailsEntityService clientService; + @Autowired + private PairwiseIdentiferService pairwiseIdentifierService; + @Override public void save(UserInfo userInfo) { userInfoRepository.save(userInfo); @@ -60,23 +63,24 @@ public class DefaultUserInfoService implements UserInfoService { return userInfoRepository.getByUsername(username); } - @Override - public UserInfo getByUsernameAndClientId(String username, String clientId) { - - ClientDetailsEntity client = clientService.loadClientByClientId(clientId); - - UserInfo userInfo = getByUsername(username); - - if (client == null || userInfo == null) { - return null; - } - - if (client.getSubjectType().equals(ClientDetailsEntity.SubjectType.PAIRWISE)) { - userInfo.setSub(userInfo.getSub() + "@" + clientId); - } - - return userInfo; - - } + @Override + public UserInfo getByUsernameAndClientId(String username, String clientId) { + + ClientDetailsEntity client = clientService.loadClientByClientId(clientId); + + UserInfo userInfo = getByUsername(username); + + if (client == null || userInfo == null) { + return null; + } + + if (client.getSubjectType().equals(ClientDetailsEntity.SubjectType.PAIRWISE)) { + String pairwiseSub = pairwiseIdentifierService.getIdentifier(userInfo, client); + userInfo.setSub(pairwiseSub); + } + + return userInfo; + + } } diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java new file mode 100644 index 000000000..b1110a1a8 --- /dev/null +++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UUIDPairwiseIdentiferService.java @@ -0,0 +1,68 @@ +/** + * + */ +package org.mitre.openid.connect.service.impl; + +import java.util.UUID; + +import org.mitre.oauth2.model.ClientDetailsEntity; +import org.mitre.openid.connect.model.PairwiseIdentifier; +import org.mitre.openid.connect.model.UserInfo; +import org.mitre.openid.connect.repository.PairwiseIdentifierRepository; +import org.mitre.openid.connect.service.PairwiseIdentiferService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.google.common.base.Strings; + +/** + * @author jricher + * + */ +@Service("uuidPairwiseIdentiferService") +public class UUIDPairwiseIdentiferService implements PairwiseIdentiferService { + + @Autowired + private PairwiseIdentifierRepository pairwiseIdentifierRepository; + + @Override + public String getIdentifier(UserInfo userInfo, ClientDetailsEntity client) { + + if (!Strings.isNullOrEmpty(client.getSectorIdentifierUri())) { + // if there's a sector identifier, use that for the lookup + PairwiseIdentifier pairwise = pairwiseIdentifierRepository.getBySectorIdentifier(userInfo.getSub(), client.getSectorIdentifierUri()); + + if (pairwise == null) { + // we don't have an identifier, need to make and save one + + pairwise = new PairwiseIdentifier(); + pairwise.setIdentifier(UUID.randomUUID().toString()); + pairwise.setUserSub(userInfo.getSub()); + pairwise.setSectorIdentifier(client.getSectorIdentifierUri()); + + pairwiseIdentifierRepository.save(pairwise); + } + + return pairwise.getIdentifier(); + } else { + // if there's no sector identifier, use the client ID + PairwiseIdentifier pairwise = pairwiseIdentifierRepository.getByClientId(userInfo.getSub(), client.getClientId()); + + if (pairwise == null) { + // we don't have an identifier, need to make and save one + + pairwise = new PairwiseIdentifier(); + pairwise.setIdentifier(UUID.randomUUID().toString()); + pairwise.setUserSub(userInfo.getSub()); + pairwise.setClientId(client.getClientId()); + + pairwiseIdentifierRepository.save(pairwise); + } + + return pairwise.getIdentifier(); + } + + + } + +} diff --git a/openid-connect-server/src/main/resources/db/tables/hsql_database_tables.sql b/openid-connect-server/src/main/resources/db/tables/hsql_database_tables.sql index 7e9d87cfa..5cf29416c 100644 --- a/openid-connect-server/src/main/resources/db/tables/hsql_database_tables.sql +++ b/openid-connect-server/src/main/resources/db/tables/hsql_database_tables.sql @@ -203,3 +203,11 @@ CREATE TABLE IF NOT EXISTS whitelisted_site_scope ( owner_id BIGINT, scope VARCHAR(256) ); + +CREATE TABLE IF NOT EXISTS pairwise_identifier ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, + identifier VARCHAR(256), + sub VARCHAR(256), + client_id VARCHAR(256), + sector_identifier VARCHAR(2048) +); diff --git a/openid-connect-server/src/main/resources/db/tables/mysql_database_tables.sql b/openid-connect-server/src/main/resources/db/tables/mysql_database_tables.sql index c98d6d1f1..d2800fe81 100644 --- a/openid-connect-server/src/main/resources/db/tables/mysql_database_tables.sql +++ b/openid-connect-server/src/main/resources/db/tables/mysql_database_tables.sql @@ -203,3 +203,11 @@ CREATE TABLE IF NOT EXISTS whitelisted_site_scope ( owner_id BIGINT, scope VARCHAR(256) ); + +CREATE TABLE IF NOT EXISTS pairwise_identifier ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + identifier VARCHAR(256), + sub VARCHAR(256), + client_id VARCHAR(256), + sector_identifier VARCHAR(2048) +);