Merge branch 'user-approval-handler-updated-rebase'
commit
a061e64abf
|
@ -19,6 +19,7 @@ import java.util.Date;
|
|||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
|
@ -31,15 +32,14 @@ import javax.persistence.NamedQueries;
|
|||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
|
||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
@Entity
|
||||
@Table(name="approvedsite")
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "ApprovedSite.getAll", query = "select a from ApprovedSite a"),
|
||||
@NamedQuery(name = "ApprovedSite.getByUserInfo", query = "select a from ApprovedSite a where a.userInfo = :approvedSiteUserInfo"),
|
||||
@NamedQuery(name = "ApprovedSite.getByClientDetails", query = "select a from ApprovedSite a where a.clientDetails = :approvedSiteClientDetails")
|
||||
@NamedQuery(name = "ApprovedSite.getByUserId", query = "select a from ApprovedSite a where a.userId = :userId"),
|
||||
@NamedQuery(name = "ApprovedSite.getByClientIdAndUserId", query = "select a from ApprovedSite a where a.clientId = :clientId and a.userId = :userId")
|
||||
})
|
||||
public class ApprovedSite {
|
||||
|
||||
|
@ -47,10 +47,10 @@ public class ApprovedSite {
|
|||
private Long id;
|
||||
|
||||
// which user made the approval
|
||||
private String userInfo;
|
||||
private String userId;
|
||||
|
||||
// which OAuth2 client is this tied to
|
||||
private ClientDetailsEntity clientDetails;
|
||||
private String clientId;
|
||||
|
||||
// when was this first approved?
|
||||
private Date creationDate;
|
||||
|
@ -65,6 +65,9 @@ public class ApprovedSite {
|
|||
// this should include all information for what data to access
|
||||
private Set<String> allowedScopes;
|
||||
|
||||
// If this AP is a WS, link to the WS
|
||||
private WhitelistedSite whitelistedSite;
|
||||
|
||||
// TODO: should we store the OAuth2 tokens and IdTokens here?
|
||||
|
||||
/**
|
||||
|
@ -94,31 +97,30 @@ public class ApprovedSite {
|
|||
* @return the userInfo
|
||||
*/
|
||||
@Basic
|
||||
public String getUserInfo() {
|
||||
return userInfo;
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param userInfo the userInfo to set
|
||||
*/
|
||||
public void setUserInfo(String userInfo) {
|
||||
this.userInfo = userInfo;
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the clientDetails
|
||||
* @return the clientId
|
||||
*/
|
||||
@ManyToOne
|
||||
@JoinColumn(name="clientdetails_id")
|
||||
public ClientDetailsEntity getClientDetails() {
|
||||
return clientDetails;
|
||||
@Basic
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clientDetails the clientDetails to set
|
||||
* @param clientId the clientId to set
|
||||
*/
|
||||
public void setClientDetails(ClientDetailsEntity clientDetails) {
|
||||
this.clientDetails = clientDetails;
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -157,6 +159,10 @@ public class ApprovedSite {
|
|||
* @return the allowedScopes
|
||||
*/
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(
|
||||
name="allowed_scopes",
|
||||
joinColumns=@JoinColumn(name="owner_id")
|
||||
)
|
||||
public Set<String> getAllowedScopes() {
|
||||
return allowedScopes;
|
||||
}
|
||||
|
@ -183,7 +189,25 @@ public class ApprovedSite {
|
|||
public void setTimeoutDate(Date timeoutDate) {
|
||||
this.timeoutDate = timeoutDate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Does this AP entry correspond to a WS?
|
||||
* @return
|
||||
*/
|
||||
@Transient
|
||||
public Boolean getIsWhitelisted() {
|
||||
return (whitelistedSite != null);
|
||||
}
|
||||
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name="whitelistedsite_id")
|
||||
public WhitelistedSite getWhitelistedSite() {
|
||||
return whitelistedSite;
|
||||
}
|
||||
|
||||
public void setWhitelistedSite(WhitelistedSite whitelistedSite) {
|
||||
this.whitelistedSite = whitelistedSite;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.mitre.openid.connect.model;
|
|||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
|
@ -25,34 +26,33 @@ import javax.persistence.GeneratedValue;
|
|||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||
|
||||
/**
|
||||
* Indicator that login to a site should be automatically granted
|
||||
* without user interaction.
|
||||
* @author jricher
|
||||
* @author jricher, aanganes
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
@Table(name="whitelistedsite")
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "WhitelistedSite.getAll", query = "select w from WhitelistedSite w")
|
||||
@NamedQuery(name = "WhitelistedSite.getAll", query = "select w from WhitelistedSite w"),
|
||||
@NamedQuery(name = "WhitelistedSite.getByClientId", query = "select w from WhitelistedSite w where w.clientId = :clientId"),
|
||||
@NamedQuery(name = "WhitelistedSite.getByCreatoruserId", query = "select w from WhitelistedSite w where w.creatorUserId = :userId")
|
||||
})
|
||||
public class WhitelistedSite {
|
||||
|
||||
// unique id
|
||||
private Long id;
|
||||
|
||||
// who added this site to the whitelist (should be an admin)
|
||||
private String userInfo;
|
||||
|
||||
// Reference to the admin user who created this entry
|
||||
private String creatorUserId;
|
||||
|
||||
// which OAuth2 client is this tied to
|
||||
private ClientDetailsEntity clientDetails;
|
||||
private String clientId;
|
||||
|
||||
// what scopes be allowed by default
|
||||
// this should include all information for what data to access
|
||||
|
@ -82,40 +82,28 @@ public class WhitelistedSite {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the userInfo
|
||||
* @return the clientId
|
||||
*/
|
||||
@Basic
|
||||
public String getUserInfo() {
|
||||
return userInfo;
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param userInfo the userInfo to set
|
||||
* @param clientId the clientId to set
|
||||
*/
|
||||
public void setUserInfo(String userInfo) {
|
||||
this.userInfo = userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the clientDetails
|
||||
*/
|
||||
@ManyToOne
|
||||
@JoinColumn(name="clientdetails_id")
|
||||
public ClientDetailsEntity getClientDetails() {
|
||||
return clientDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clientDetails the clientDetails to set
|
||||
*/
|
||||
public void setClientDetails(ClientDetailsEntity clientDetails) {
|
||||
this.clientDetails = clientDetails;
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the allowedScopes
|
||||
*/
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(
|
||||
name="allowed_scopes",
|
||||
joinColumns=@JoinColumn(name="owner_id")
|
||||
)
|
||||
public Set<String> getAllowedScopes() {
|
||||
return allowedScopes;
|
||||
}
|
||||
|
@ -126,4 +114,13 @@ public class WhitelistedSite {
|
|||
public void setAllowedScopes(Set<String> allowedScopes) {
|
||||
this.allowedScopes = allowedScopes;
|
||||
}
|
||||
|
||||
@Basic
|
||||
public String getCreatorUserId() {
|
||||
return creatorUserId;
|
||||
}
|
||||
|
||||
public void setCreatorUserId(String creatorUserId) {
|
||||
this.creatorUserId = creatorUserId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,14 +17,12 @@ package org.mitre.openid.connect.repository;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||
import org.mitre.openid.connect.model.ApprovedSite;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
|
||||
/**
|
||||
* ApprovedSite repository interface
|
||||
*
|
||||
* @author Michael Joseph Walsh
|
||||
* @author Michael Joseph Walsh, aanganes
|
||||
*
|
||||
*/
|
||||
public interface ApprovedSiteRepository {
|
||||
|
@ -47,22 +45,13 @@ public interface ApprovedSiteRepository {
|
|||
|
||||
/**
|
||||
* Return a collection of ApprovedSite managed by this repository matching the
|
||||
* provided ClientDetailsEntity
|
||||
* provided client ID and user ID
|
||||
*
|
||||
* @param clientId
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
public Collection<ApprovedSite> getByClientDetails(
|
||||
ClientDetailsEntity clientDetails);
|
||||
|
||||
/**
|
||||
* Return a collection of ApprovedSite managed by this repository matching the
|
||||
* provided UserInfo
|
||||
*
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
public Collection<ApprovedSite> getByUserInfo(UserInfo userInfo);
|
||||
*/
|
||||
public ApprovedSite getByClientIdAndUserId(String clientId, String userId);
|
||||
|
||||
/**
|
||||
* Removes the given ApprovedSite from the repository
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.mitre.openid.connect.model.WhitelistedSite;
|
|||
/**
|
||||
* WhitelistedSite repository interface
|
||||
*
|
||||
* @author Michael Joseph Walsh
|
||||
* @author Michael Joseph Walsh, aanganes
|
||||
*
|
||||
*/
|
||||
public interface WhitelistedSiteRepository {
|
||||
|
@ -42,6 +42,22 @@ public interface WhitelistedSiteRepository {
|
|||
* @return a valid WhitelistedSite if it exists, null otherwise
|
||||
*/
|
||||
public WhitelistedSite getById(Long id);
|
||||
|
||||
/**
|
||||
* Find a WhitelistedSite by its associated ClientDetails reference
|
||||
*
|
||||
* @param client the Relying Party
|
||||
* @return the corresponding WhitelistedSite if one exists for the RP, or null
|
||||
*/
|
||||
public WhitelistedSite getByClientId(String clientId);
|
||||
|
||||
/**
|
||||
* Return a collection of the WhitelistedSites created by a given user
|
||||
*
|
||||
* @param creator the id of the admin who may have created some WhitelistedSites
|
||||
* @return the collection of corresponding WhitelistedSites, if any, or null
|
||||
*/
|
||||
public Collection<WhitelistedSite> getByCreator(String creatorId);
|
||||
|
||||
/**
|
||||
* Removes the given IdToken from the repository
|
||||
|
|
|
@ -16,20 +16,23 @@
|
|||
package org.mitre.openid.connect.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||
import org.mitre.openid.connect.model.ApprovedSite;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
import org.mitre.openid.connect.model.WhitelistedSite;
|
||||
|
||||
/**
|
||||
* Interface for ApprovedSite service
|
||||
*
|
||||
* @author Michael Joseph Walsh
|
||||
* @author Michael Joseph Walsh, aanganes
|
||||
*
|
||||
*/
|
||||
public interface ApprovedSiteService {
|
||||
|
||||
|
||||
public ApprovedSite createApprovedSite(String clientId, String userId, Date timeoutDate, Set<String> allowedScopes, WhitelistedSite whitelistedSite);
|
||||
|
||||
/**
|
||||
* Return a collection of all ApprovedSites
|
||||
*
|
||||
|
@ -39,21 +42,13 @@ public interface ApprovedSiteService {
|
|||
|
||||
/**
|
||||
* Return a collection of ApprovedSite managed by this repository matching the
|
||||
* provided ClientDetailsEntity
|
||||
* provided client ID and user ID
|
||||
*
|
||||
* @param clientId
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
public Collection<ApprovedSite> getByClientDetails(ClientDetailsEntity clientDetails);
|
||||
|
||||
/**
|
||||
* Return a collection of ApprovedSite managed by this repository matching the
|
||||
* provided UserInfo
|
||||
*
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
public Collection<ApprovedSite> getByUserInfo(UserInfo userInfo);
|
||||
public ApprovedSite getByClientIdAndUserId(String clientId, String userId);
|
||||
|
||||
/**
|
||||
* Save an ApprovedSite
|
||||
|
@ -61,7 +56,7 @@ public interface ApprovedSiteService {
|
|||
* @param approvedSite
|
||||
* the ApprovedSite to be saved
|
||||
*/
|
||||
public void save(ApprovedSite approvedSite);
|
||||
public ApprovedSite save(ApprovedSite approvedSite);
|
||||
|
||||
/**
|
||||
* Get ApprovedSite for id
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
******************************************************************************/
|
||||
package org.mitre.openid.connect.service;
|
||||
|
||||
import org.mitre.openid.connect.model.DefaultUserInfo;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +31,7 @@ public interface UserInfoService {
|
|||
* @param userInfo
|
||||
* the UserInfo to be saved
|
||||
*/
|
||||
public void save(DefaultUserInfo userInfo);
|
||||
public void save(UserInfo userInfo);
|
||||
|
||||
/**
|
||||
* Get UserInfo for user id
|
||||
|
|
|
@ -15,16 +15,25 @@
|
|||
******************************************************************************/
|
||||
package org.mitre.openid.connect.service;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mitre.openid.connect.model.WhitelistedSite;
|
||||
|
||||
/**
|
||||
* Interface for WhitelistedSite service
|
||||
*
|
||||
* @author Michael Joseph Walsh
|
||||
* @author Michael Joseph Walsh, aanganes
|
||||
*
|
||||
*/
|
||||
public interface WhitelistedSiteService {
|
||||
|
||||
/**
|
||||
* Return a collection of all WhitelistedSite managed by this service
|
||||
*
|
||||
* @return the WhitelistedSite collection, or null
|
||||
*/
|
||||
public Collection<WhitelistedSite> getAll();
|
||||
|
||||
/**
|
||||
* Returns the WhitelistedSite for the given id
|
||||
*
|
||||
|
@ -34,6 +43,22 @@ public interface WhitelistedSiteService {
|
|||
*/
|
||||
public WhitelistedSite getById(Long id);
|
||||
|
||||
/**
|
||||
* Find a WhitelistedSite by its associated ClientDetails reference
|
||||
*
|
||||
* @param client the Relying Party
|
||||
* @return the corresponding WhitelistedSite if one exists for the RP, or null
|
||||
*/
|
||||
public WhitelistedSite getByClientId(String clientId);
|
||||
|
||||
/**
|
||||
* Return a collection of the WhitelistedSites created by a given user
|
||||
*
|
||||
* @param creator the user id of an admin who may have made some WhitelistedSites
|
||||
* @return the collection of corresponding WhitelistedSites, if any, or null
|
||||
*/
|
||||
public Collection<WhitelistedSite> getByCreator(String creatorId);
|
||||
|
||||
/**
|
||||
* Removes the given WhitelistedSite from the repository
|
||||
*
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
create table allowed_scopes(
|
||||
owner_id VARCHAR(256),
|
||||
allowedScopes VARCHAR(256)
|
||||
);
|
|
@ -1,8 +1,9 @@
|
|||
CREATE TABLE approvedsite (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
userinfo_id VARCHAR(256),
|
||||
clientdetails_id VARCHAR(256),
|
||||
userId VARCHAR(256),
|
||||
clientId VARCHAR(256),
|
||||
creationDate DATE,
|
||||
accessDate DATE,
|
||||
timeoutDate DATE
|
||||
timeoutDate DATE,
|
||||
whitelistedsite_id VARCHAR(256)
|
||||
);
|
|
@ -1,5 +1,5 @@
|
|||
CREATE TABLE whitelistedsite (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
userinfo_id VARCHAR(256),
|
||||
clientdetails_id VARCHAR(256)
|
||||
creatorUserId VARCHAR(256),
|
||||
clientId VARCHAR(256)
|
||||
);
|
|
@ -42,8 +42,6 @@ import org.springframework.security.oauth2.provider.token.TokenEnhancer;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
|
||||
/**
|
||||
* @author jricher
|
||||
|
@ -82,22 +80,7 @@ public class DefaultOAuth2ProviderTokenService implements OAuth2TokenEntityServi
|
|||
token.setClient(client);
|
||||
|
||||
// inherit the scope from the auth
|
||||
// this lets us match which scope is requested
|
||||
if (client.isScoped()) {
|
||||
|
||||
// restrict granted scopes to a valid subset of those
|
||||
Set<String> validScopes = Sets.newHashSet();
|
||||
|
||||
for (String requested : clientAuth.getScope()) {
|
||||
if (client.getScope().contains(requested)) {
|
||||
validScopes.add(requested);
|
||||
} else {
|
||||
logger.warn("Client " + client.getClientId() + " requested out of permission scope: " + requested);
|
||||
}
|
||||
}
|
||||
|
||||
token.setScope(validScopes);
|
||||
}
|
||||
token.setScope(clientAuth.getScope());
|
||||
|
||||
// make it expire if necessary
|
||||
// TODO: pending upstream updates, check for 0 or -1 value here
|
||||
|
|
|
@ -18,23 +18,21 @@ package org.mitre.openid.connect.repository.impl;
|
|||
import static org.mitre.util.jpa.JpaUtil.saveOrUpdate;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||
import org.mitre.openid.connect.model.ApprovedSite;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
import org.mitre.openid.connect.repository.ApprovedSiteRepository;
|
||||
import org.mitre.util.jpa.JpaUtil;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* JPA ApprovedSite repository implementation
|
||||
*
|
||||
* @author Michael Joseph Walsh
|
||||
* @author Michael Joseph Walsh, aanganes
|
||||
*
|
||||
*/
|
||||
@Repository
|
||||
|
@ -50,20 +48,6 @@ public class JpaApprovedSiteRepository implements ApprovedSiteRepository {
|
|||
"ApprovedSite.getAll", ApprovedSite.class);
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Collection<ApprovedSite> getByClientDetails(
|
||||
ClientDetailsEntity clientDetails) {
|
||||
|
||||
TypedQuery<ApprovedSite> query = manager.createNamedQuery(
|
||||
"ApprovedSite.getByClientDetails", ApprovedSite.class);
|
||||
query.setParameter("approvedSiteClientDetails", clientDetails);
|
||||
|
||||
List<ApprovedSite> found = query.getResultList();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
|
@ -71,18 +55,6 @@ public class JpaApprovedSiteRepository implements ApprovedSiteRepository {
|
|||
return manager.find(ApprovedSite.class, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Collection<ApprovedSite> getByUserInfo(UserInfo userInfo) {
|
||||
TypedQuery<ApprovedSite> query = manager.createNamedQuery(
|
||||
"ApprovedSite.getByUserInfo", ApprovedSite.class);
|
||||
query.setParameter("approvedSiteUserInfo", userInfo.getUserId());
|
||||
|
||||
List<ApprovedSite> found = query.getResultList();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void remove(ApprovedSite approvedSite) {
|
||||
|
@ -109,4 +81,14 @@ public class JpaApprovedSiteRepository implements ApprovedSiteRepository {
|
|||
public ApprovedSite save(ApprovedSite approvedSite) {
|
||||
return saveOrUpdate(approvedSite.getId(), manager, approvedSite);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApprovedSite getByClientIdAndUserId(String clientId, String userId) {
|
||||
|
||||
TypedQuery<ApprovedSite> query = manager.createNamedQuery("ApprovedSite.getByClientIdAndUserId", ApprovedSite.class);
|
||||
query.setParameter("userId", userId);
|
||||
query.setParameter("clientId", clientId);
|
||||
|
||||
return JpaUtil.getSingleResult(query.getResultList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,13 +25,14 @@ import javax.persistence.TypedQuery;
|
|||
|
||||
import org.mitre.openid.connect.model.WhitelistedSite;
|
||||
import org.mitre.openid.connect.repository.WhitelistedSiteRepository;
|
||||
import org.mitre.util.jpa.JpaUtil;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* JPA WhitelistedSite repository implementation
|
||||
*
|
||||
* @author Michael Joseph Walsh
|
||||
* @author Michael Joseph Walsh, aanganes
|
||||
*
|
||||
*/
|
||||
@Repository
|
||||
|
@ -80,4 +81,21 @@ public class JpaWhitelistedSiteRepository implements WhitelistedSiteRepository {
|
|||
public WhitelistedSite save(WhitelistedSite whiteListedSite) {
|
||||
return saveOrUpdate(whiteListedSite.getId(), manager, whiteListedSite);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public WhitelistedSite getByClientId(String clientId) {
|
||||
TypedQuery<WhitelistedSite> query = manager.createNamedQuery("WhitelistedSite.getByClientId", WhitelistedSite.class);
|
||||
query.setParameter("clientId", clientId);
|
||||
return JpaUtil.getSingleResult(query.getResultList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Collection<WhitelistedSite> getByCreator(String creatorId) {
|
||||
TypedQuery<WhitelistedSite> query = manager.createNamedQuery("WhitelistedSite.getByCreaterUserId", WhitelistedSite.class);
|
||||
query.setParameter("userId", creatorId);
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,11 @@
|
|||
package org.mitre.openid.connect.service.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||
import org.mitre.openid.connect.model.ApprovedSite;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
import org.mitre.openid.connect.model.WhitelistedSite;
|
||||
import org.mitre.openid.connect.repository.ApprovedSiteRepository;
|
||||
import org.mitre.openid.connect.service.ApprovedSiteService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -29,7 +30,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
/**
|
||||
* Implementation of the ApprovedSiteService
|
||||
*
|
||||
* @author Michael Joseph Walsh
|
||||
* @author Michael Joseph Walsh, aanganes
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
|
@ -61,19 +62,8 @@ public class ApprovedSiteServiceImpl implements ApprovedSiteService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<ApprovedSite> getByClientDetails(
|
||||
ClientDetailsEntity clientDetails) {
|
||||
return approvedSiteRepository.getByClientDetails(clientDetails);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ApprovedSite> getByUserInfo(UserInfo userInfo) {
|
||||
return approvedSiteRepository.getByUserInfo(userInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(ApprovedSite approvedSite) {
|
||||
approvedSiteRepository.save(approvedSite);
|
||||
public ApprovedSite save(ApprovedSite approvedSite) {
|
||||
return approvedSiteRepository.save(approvedSite);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,4 +81,31 @@ public class ApprovedSiteServiceImpl implements ApprovedSiteService {
|
|||
approvedSiteRepository.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApprovedSite createApprovedSite(String clientId, String userId, Date timeoutDate, Set<String> allowedScopes,
|
||||
WhitelistedSite whitelistedSite) {
|
||||
|
||||
ApprovedSite as = new ApprovedSite();
|
||||
|
||||
Date now = new Date();
|
||||
as.setCreationDate(now);
|
||||
as.setAccessDate(now);
|
||||
as.setClientId(clientId);
|
||||
as.setUserId(userId);
|
||||
as.setTimeoutDate(timeoutDate);
|
||||
as.setAllowedScopes(allowedScopes);
|
||||
as.setWhitelistedSite(whitelistedSite);
|
||||
|
||||
return save(as);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApprovedSite getByClientIdAndUserId(String clientId,
|
||||
String userId) {
|
||||
|
||||
return approvedSiteRepository.getByClientIdAndUserId(clientId, userId);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
******************************************************************************/
|
||||
package org.mitre.openid.connect.service.impl;
|
||||
|
||||
import org.mitre.openid.connect.model.DefaultUserInfo;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
import org.mitre.openid.connect.repository.UserInfoRepository;
|
||||
import org.mitre.openid.connect.service.UserInfoService;
|
||||
|
@ -53,7 +52,7 @@ public class UserInfoServiceImpl implements UserInfoService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void save(DefaultUserInfo userInfo) {
|
||||
public void save(UserInfo userInfo) {
|
||||
userInfoRepository.save(userInfo);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
******************************************************************************/
|
||||
package org.mitre.openid.connect.service.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.mitre.openid.connect.model.WhitelistedSite;
|
||||
import org.mitre.openid.connect.repository.WhitelistedSiteRepository;
|
||||
import org.mitre.openid.connect.service.WhitelistedSiteService;
|
||||
|
@ -25,7 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
/**
|
||||
* Implementation of the WhitelistedSiteService
|
||||
*
|
||||
* @author Michael Joseph Walsh
|
||||
* @author Michael Joseph Walsh, aanganes
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
|
@ -71,4 +73,19 @@ public class WhitelistedSiteServiceImpl implements WhitelistedSiteService {
|
|||
return whitelistedSiteRepository.save(whitelistedSite);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<WhitelistedSite> getAll() {
|
||||
return whitelistedSiteRepository.getAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WhitelistedSite getByClientId(String clientId) {
|
||||
return whitelistedSiteRepository.getByClientId(clientId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<WhitelistedSite> getByCreator(String creatorId) {
|
||||
return whitelistedSiteRepository.getByCreator(creatorId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2012 The MITRE Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
package org.mitre.openid.connect.token;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.provider.AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
|
||||
|
||||
public class JdbcUserApprovalHandler implements UserApprovalHandler {
|
||||
|
||||
@Override
|
||||
public boolean isApproved(AuthorizationRequest authorizationRequest,
|
||||
Authentication userAuthentication) {
|
||||
|
||||
//Check database to see if the user identified by the userAuthentication has stored an approval decision
|
||||
userAuthentication.getPrincipal();
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2012 The MITRE Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
package org.mitre.openid.connect.token;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mitre.openid.connect.model.ApprovedSite;
|
||||
import org.mitre.openid.connect.model.WhitelistedSite;
|
||||
import org.mitre.openid.connect.service.ApprovedSiteService;
|
||||
import org.mitre.openid.connect.service.WhitelistedSiteService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
|
||||
import org.springframework.security.oauth2.provider.AuthorizationRequest;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.ClientDetailsService;
|
||||
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Custom User Approval Handler implementation which uses a concept of a whitelist,
|
||||
* blacklist, and greylist.
|
||||
*
|
||||
* Blacklisted sites will be caught and handled before this
|
||||
* point.
|
||||
*
|
||||
* Whitelisted sites will be automatically approved, and an ApprovedSite entry will
|
||||
* be created for the site the first time a given user access it.
|
||||
*
|
||||
* All other sites fall into the greylist - the user will be presented with the user
|
||||
* approval page upon their first visit
|
||||
* @author aanganes
|
||||
*
|
||||
*/
|
||||
public class TofuUserApprovalHandler implements UserApprovalHandler {
|
||||
|
||||
@Autowired
|
||||
ApprovedSiteService approvedSiteService;
|
||||
|
||||
@Autowired
|
||||
WhitelistedSiteService whitelistedSiteService;
|
||||
|
||||
@Autowired
|
||||
ClientDetailsService clientDetailsService;
|
||||
|
||||
|
||||
/**
|
||||
* Check if the user has already stored a positive approval decision for this site; or if the
|
||||
* site is whitelisted, approve it automatically.
|
||||
*
|
||||
* Otherwise, return false so that the user will see the approval page and can make their own decision.
|
||||
*
|
||||
* @param authorizationRequest the incoming authorization request
|
||||
* @param userAuthentication the Principal representing the currently-logged-in user
|
||||
*
|
||||
* @return true if the site is approved, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
|
||||
|
||||
//First, check database to see if the user identified by the userAuthentication has stored an approval decision
|
||||
|
||||
//getName may not be filled in? TODO: investigate
|
||||
String userId = userAuthentication.getName();
|
||||
String clientId = authorizationRequest.getClientId();
|
||||
ClientDetails client = clientDetailsService.loadClientByClientId(clientId);
|
||||
|
||||
String scopes = authorizationRequest.getAuthorizationParameters().get("scope");
|
||||
Set<String> authRequestScopes = Sets.newHashSet(Splitter.on(" ").split(scopes));
|
||||
|
||||
//lookup ApprovedSites by userId and clientId
|
||||
ApprovedSite ap = approvedSiteService.getByClientIdAndUserId(clientId, userId);
|
||||
|
||||
if (ap != null) {
|
||||
if (scopesMatch(authRequestScopes, ap.getAllowedScopes())) {
|
||||
|
||||
//We have a match; update the access date on the AP entry and return true.
|
||||
ap.setAccessDate(new Date());
|
||||
approvedSiteService.save(ap);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
WhitelistedSite ws = whitelistedSiteService.getByClientId(clientId);
|
||||
if (ws != null && scopesMatch(authRequestScopes, ws.getAllowedScopes())) {
|
||||
|
||||
//Create an approved site
|
||||
approvedSiteService.createApprovedSite(clientId, userId, null, ws.getAllowedScopes(), ws);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean approved = Boolean.parseBoolean(authorizationRequest.getApprovalParameters().get("user_oauth_approval"));
|
||||
|
||||
if (approved && !authorizationRequest.getApprovalParameters().isEmpty()) {
|
||||
|
||||
//Only store an ApprovedSite if the user has checked "remember this decision":
|
||||
if (authorizationRequest.getApprovalParameters().get("remember") != null) {
|
||||
|
||||
//TODO: Remember may eventually have an option to remember for a specific amount
|
||||
//of time; this would set the ApprovedSite.timeout.
|
||||
|
||||
Set<String> allowedScopes = Sets.newHashSet();
|
||||
Map<String,String> approvalParams = authorizationRequest.getApprovalParameters();
|
||||
|
||||
Set<String> keys = approvalParams.keySet();
|
||||
|
||||
for (String key : keys) {
|
||||
if (key.contains("scope")) {
|
||||
//This is a scope parameter from the approval page. The value sent back should
|
||||
//be the scope string. Check to make sure it is contained in the client's
|
||||
//registered allowed scopes.
|
||||
|
||||
String scope = approvalParams.get(key);
|
||||
|
||||
//Make sure this scope is allowed for the given client
|
||||
if (client.getScope().contains(scope)) {
|
||||
allowedScopes.add(scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME: inject the final allowedScopes set into the AuthorizationRequest. The requester may have
|
||||
//asked for many scopes and the user may have denied some of them.
|
||||
|
||||
approvedSiteService.createApprovedSite(clientId, userId, null, allowedScopes, null);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the requested scope set is a proper subset of the allowed scopes.
|
||||
*
|
||||
* @param requestedScopes
|
||||
* @param allowedScopes
|
||||
* @return
|
||||
*/
|
||||
private boolean scopesMatch(Set<String> requestedScopes, Set<String> allowedScopes) {
|
||||
|
||||
for (String scope : requestedScopes) {
|
||||
|
||||
if (!allowedScopes.contains(scope)) {
|
||||
throw new InvalidScopeException("Invalid scope: " + scope, allowedScopes);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,8 +18,6 @@ package org.mitre.openid.connect.web;
|
|||
import java.security.Principal;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||
import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
||||
import org.mitre.openid.connect.exception.UnknownUserInfoSchemaException;
|
||||
import org.mitre.openid.connect.model.DefaultUserInfo;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<class>org.mitre.openid.connect.model.IdToken</class>
|
||||
<class>org.mitre.openid.connect.model.IdTokenClaims</class>
|
||||
<class>org.mitre.openid.connect.model.DefaultUserInfo</class>
|
||||
<!-- <class>org.mitre.openid.connect.model.UserInfo</class> -->
|
||||
<class>org.mitre.openid.connect.model.WhitelistedSite</class>
|
||||
<shared-cache-mode>NONE</shared-cache-mode>
|
||||
</persistence-unit>
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
client-details-service-ref="defaultOAuth2ClientDetailsEntityService"
|
||||
authorization-request-factory-ref="authorizationRequestFactory"
|
||||
token-services-ref="defaultOAuth2ProviderTokenService"
|
||||
user-approval-handler-ref="userApprovalHandler"
|
||||
user-approval-handler-ref="jdbcUserApprovalHandler"
|
||||
authorization-endpoint-url="/authorize"
|
||||
token-endpoint-url="/token">
|
||||
|
||||
|
@ -80,8 +80,7 @@
|
|||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler" id="userApprovalHandler">
|
||||
<property name="tokenServices" ref="defaultOAuth2ProviderTokenService" />
|
||||
<bean class="org.mitre.openid.connect.token.TofuUserApprovalHandler" id="jdbcUserApprovalHandler">
|
||||
</bean>
|
||||
|
||||
<bean id="authCodeServices" class="org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices" />
|
||||
|
|
|
@ -62,16 +62,20 @@
|
|||
<div class="span4">
|
||||
<fieldset style="text-align:left" class="well">
|
||||
<legend style="margin-bottom: 0;">Access to:</legend>
|
||||
<label for="option1"></label>
|
||||
<input type="checkbox" name="option1" id="option1" checked="checked"> basic profile information
|
||||
<label for="option2"></label>
|
||||
<input type="checkbox" name="option1" id="option2" checked="checked"> email address
|
||||
<label for="option3"></label>
|
||||
<input type="checkbox" name="option3" id="option3" checked="checked"> address
|
||||
<label for="option4"></label>
|
||||
<input type="checkbox" name="option4" id="option4" checked="checked"> phone number
|
||||
<label for="option5"></label>
|
||||
<input type="checkbox" name="option5" id="option5" checked="checked"> offline access
|
||||
|
||||
<input type="hidden" name="scope_openid" id="scope_openid" value="openid"/>
|
||||
<input type="checkbox" name="scope_profile" id="scope_profile" value="profile" checked="checked"><label for="scope_profile">basic profile information</label>
|
||||
|
||||
<input type="checkbox" name="scope_email" id="scope_email" value="email" checked="checked"><label for="scope_email">email address</label>
|
||||
|
||||
<input type="checkbox" name="scope_address" id="scope_address" value="address" checked="checked"><label for="scope_address">address</label>
|
||||
|
||||
<input type="checkbox" name="scope_phone" id="scope_phone" value="phone" checked="checked"><label for="scope_phone">phone number</label>
|
||||
|
||||
<input type="checkbox" name="scope_offline" id="scope_offline" value="offline" checked="checked"><label for="scope_offline">offline access</label>
|
||||
|
||||
<input type="checkbox" name="remember" id="remember" value="true" checked="checked"><label for="remember">remember this decision</label>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in New Issue