Implementing user approval handler; made some modifications to ApprovedSite and WhitelistedSite models, repositories, and service layers.

pull/165/merge
Amanda Anganes 2012-06-27 13:24:35 -04:00
parent 7c33e19950
commit 4e10fce7ef
11 changed files with 214 additions and 37 deletions

View File

@ -47,7 +47,7 @@ public class ApprovedSite {
private Long id; private Long id;
// which user made the approval // which user made the approval
private String userInfo; private UserInfo userInfo;
// which OAuth2 client is this tied to // which OAuth2 client is this tied to
private ClientDetailsEntity clientDetails; private ClientDetailsEntity clientDetails;
@ -65,6 +65,9 @@ public class ApprovedSite {
// this should include all information for what data to access // this should include all information for what data to access
private Set<String> allowedScopes; 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? // TODO: should we store the OAuth2 tokens and IdTokens here?
/** /**
@ -93,15 +96,16 @@ public class ApprovedSite {
/** /**
* @return the userInfo * @return the userInfo
*/ */
@Basic @ManyToOne
public String getUserInfo() { @JoinColumn(name="userinfo_id")
public UserInfo getUserInfo() {
return userInfo; return userInfo;
} }
/** /**
* @param userInfo the userInfo to set * @param userInfo the userInfo to set
*/ */
public void setUserInfo(String userInfo) { public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo; this.userInfo = userInfo;
} }
@ -184,6 +188,24 @@ public class ApprovedSite {
this.timeoutDate = timeoutDate; this.timeoutDate = timeoutDate;
} }
/**
* Does this AP entry correspond to a WS?
* @return
*/
@Basic
public Boolean getIsWhitelisted() {
return (whitelistedSite != null);
}
@ManyToOne
@JoinColumn(name="whitelistedsite_id")
public WhitelistedSite getWhitelistedSite() {
return whitelistedSite;
}
public void setWhitelistedSite(WhitelistedSite whitelistedSite) {
this.whitelistedSite = whitelistedSite;
}
} }

View File

@ -17,7 +17,6 @@ package org.mitre.openid.connect.model;
import java.util.Set; import java.util.Set;
import javax.persistence.Basic;
import javax.persistence.ElementCollection; import javax.persistence.ElementCollection;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
@ -35,21 +34,23 @@ import org.mitre.oauth2.model.ClientDetailsEntity;
/** /**
* Indicator that login to a site should be automatically granted * Indicator that login to a site should be automatically granted
* without user interaction. * without user interaction.
* @author jricher * @author jricher, aanganes
* *
*/ */
@Entity @Entity
@Table(name="whitelistedsite") @Table(name="whitelistedsite")
@NamedQueries({ @NamedQueries({
@NamedQuery(name = "WhitelistedSite.getAll", query = "select w from WhitelistedSite w") @NamedQuery(name = "WhitelistedSite.getAll", query = "select w from WhitelistedSite w"),
@NamedQuery(name = "WhitelistedSite.getByClientDetails", query = "select w from WhitelistedSite w where w.clientDetails = :clientDetails"),
@NamedQuery(name = "WhitelistedSite.getByUserInfo", query = "select w from WhitelistedSite w where w.creator = :userInfo")
}) })
public class WhitelistedSite { public class WhitelistedSite {
// unique id // unique id
private Long id; private Long id;
// who added this site to the whitelist (should be an admin) // Reference to the admin user who created this entry
private String userInfo; private UserInfo creator;
// which OAuth2 client is this tied to // which OAuth2 client is this tied to
private ClientDetailsEntity clientDetails; private ClientDetailsEntity clientDetails;
@ -81,21 +82,6 @@ public class WhitelistedSite {
this.id = id; this.id = id;
} }
/**
* @return the userInfo
*/
@Basic
public String getUserInfo() {
return userInfo;
}
/**
* @param userInfo the userInfo to set
*/
public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
}
/** /**
* @return the clientDetails * @return the clientDetails
*/ */
@ -126,4 +112,14 @@ public class WhitelistedSite {
public void setAllowedScopes(Set<String> allowedScopes) { public void setAllowedScopes(Set<String> allowedScopes) {
this.allowedScopes = allowedScopes; this.allowedScopes = allowedScopes;
} }
@ManyToOne
@JoinColumn(name="userinfo_id")
public UserInfo getCreator() {
return creator;
}
public void setCreator(UserInfo creator) {
this.creator = creator;
}
} }

View File

@ -17,7 +17,9 @@ package org.mitre.openid.connect.repository;
import java.util.Collection; import java.util.Collection;
import org.mitre.openid.connect.model.UserInfo;
import org.mitre.openid.connect.model.WhitelistedSite; import org.mitre.openid.connect.model.WhitelistedSite;
import org.springframework.security.oauth2.provider.ClientDetails;
/** /**
* WhitelistedSite repository interface * WhitelistedSite repository interface
@ -43,6 +45,22 @@ public interface WhitelistedSiteRepository {
*/ */
public WhitelistedSite getById(Long id); 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 getByClientDetails(ClientDetails client);
/**
* Return a collection of the WhitelistedSites created by a given user
*
* @param creator the UserInfo representing an admin who may have made some WhitelistedSites
* @return the collection of corresponding WhitelistedSites, if any, or null
*/
public Collection<WhitelistedSite> getByCreator(UserInfo creator);
/** /**
* Removes the given IdToken from the repository * Removes the given IdToken from the repository
* *

View File

@ -15,7 +15,6 @@
******************************************************************************/ ******************************************************************************/
package org.mitre.openid.connect.service; package org.mitre.openid.connect.service;
import org.mitre.openid.connect.model.DefaultUserInfo;
import org.mitre.openid.connect.model.UserInfo; import org.mitre.openid.connect.model.UserInfo;
/** /**
@ -32,7 +31,7 @@ public interface UserInfoService {
* @param userInfo * @param userInfo
* the UserInfo to be saved * the UserInfo to be saved
*/ */
public void save(DefaultUserInfo userInfo); public void save(UserInfo userInfo);
/** /**
* Get UserInfo for user id * Get UserInfo for user id

View File

@ -15,7 +15,11 @@
******************************************************************************/ ******************************************************************************/
package org.mitre.openid.connect.service; package org.mitre.openid.connect.service;
import java.util.Collection;
import org.mitre.openid.connect.model.UserInfo;
import org.mitre.openid.connect.model.WhitelistedSite; import org.mitre.openid.connect.model.WhitelistedSite;
import org.springframework.security.oauth2.provider.ClientDetails;
/** /**
* Interface for WhitelistedSite service * Interface for WhitelistedSite service
@ -25,6 +29,13 @@ import org.mitre.openid.connect.model.WhitelistedSite;
*/ */
public interface WhitelistedSiteService { 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 * Returns the WhitelistedSite for the given id
* *
@ -34,6 +45,22 @@ public interface WhitelistedSiteService {
*/ */
public WhitelistedSite getById(Long id); 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 getByClientDetails(ClientDetails client);
/**
* Return a collection of the WhitelistedSites created by a given user
*
* @param creator the UserInfo representing an admin who may have made some WhitelistedSites
* @return the collection of corresponding WhitelistedSites, if any, or null
*/
public Collection<WhitelistedSite> getByCreator(UserInfo creator);
/** /**
* Removes the given WhitelistedSite from the repository * Removes the given WhitelistedSite from the repository
* *

View File

@ -4,5 +4,6 @@ CREATE TABLE approvedsite (
clientdetails_id VARCHAR(256), clientdetails_id VARCHAR(256),
creationDate DATE, creationDate DATE,
accessDate DATE, accessDate DATE,
timeoutDate DATE timeoutDate DATE,
whitelistedsite_id VARCHAR(256)
); );

View File

@ -23,8 +23,10 @@ import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import org.mitre.openid.connect.model.UserInfo;
import org.mitre.openid.connect.model.WhitelistedSite; import org.mitre.openid.connect.model.WhitelistedSite;
import org.mitre.openid.connect.repository.WhitelistedSiteRepository; import org.mitre.openid.connect.repository.WhitelistedSiteRepository;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -80,4 +82,22 @@ public class JpaWhitelistedSiteRepository implements WhitelistedSiteRepository {
public WhitelistedSite save(WhitelistedSite whiteListedSite) { public WhitelistedSite save(WhitelistedSite whiteListedSite) {
return saveOrUpdate(whiteListedSite.getId(), manager, whiteListedSite); return saveOrUpdate(whiteListedSite.getId(), manager, whiteListedSite);
} }
@Override
@Transactional
public WhitelistedSite getByClientDetails(ClientDetails client) {
TypedQuery<WhitelistedSite> query = manager.createNamedQuery("WhitelistedSite.getByClientDetails", WhitelistedSite.class);
query.setParameter("clientDetails", client);
return query.getSingleResult();
}
@Override
@Transactional
public Collection<WhitelistedSite> getByCreator(UserInfo creator) {
TypedQuery<WhitelistedSite> query = manager.createNamedQuery("WhitelistedSite.getByUserInfo", WhitelistedSite.class);
query.setParameter("userInfo", creator);
return query.getResultList();
}
} }

View File

@ -15,7 +15,6 @@
******************************************************************************/ ******************************************************************************/
package org.mitre.openid.connect.service.impl; 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.model.UserInfo;
import org.mitre.openid.connect.repository.UserInfoRepository; import org.mitre.openid.connect.repository.UserInfoRepository;
import org.mitre.openid.connect.service.UserInfoService; import org.mitre.openid.connect.service.UserInfoService;
@ -53,7 +52,7 @@ public class UserInfoServiceImpl implements UserInfoService {
} }
@Override @Override
public void save(DefaultUserInfo userInfo) { public void save(UserInfo userInfo) {
userInfoRepository.save(userInfo); userInfoRepository.save(userInfo);
} }

View File

@ -15,10 +15,14 @@
******************************************************************************/ ******************************************************************************/
package org.mitre.openid.connect.service.impl; package org.mitre.openid.connect.service.impl;
import java.util.Collection;
import org.mitre.openid.connect.model.UserInfo;
import org.mitre.openid.connect.model.WhitelistedSite; import org.mitre.openid.connect.model.WhitelistedSite;
import org.mitre.openid.connect.repository.WhitelistedSiteRepository; import org.mitre.openid.connect.repository.WhitelistedSiteRepository;
import org.mitre.openid.connect.service.WhitelistedSiteService; import org.mitre.openid.connect.service.WhitelistedSiteService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -71,4 +75,19 @@ public class WhitelistedSiteServiceImpl implements WhitelistedSiteService {
return whitelistedSiteRepository.save(whitelistedSite); return whitelistedSiteRepository.save(whitelistedSite);
} }
@Override
public Collection<WhitelistedSite> getAll() {
return whitelistedSiteRepository.getAll();
}
@Override
public WhitelistedSite getByClientDetails(ClientDetails client) {
return whitelistedSiteRepository.getByClientDetails(client);
}
@Override
public Collection<WhitelistedSite> getByCreator(UserInfo creator) {
return whitelistedSiteRepository.getByCreator(creator);
}
} }

View File

@ -15,19 +15,97 @@
******************************************************************************/ ******************************************************************************/
package org.mitre.openid.connect.token; package org.mitre.openid.connect.token;
import java.util.Date;
import java.util.Collection;
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.service.ApprovedSiteService;
import org.mitre.openid.connect.service.UserInfoService;
import org.mitre.openid.connect.service.WhitelistedSiteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.AuthorizationRequest; 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 org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
/**
* 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 JdbcUserApprovalHandler implements UserApprovalHandler { public class JdbcUserApprovalHandler implements UserApprovalHandler {
@Autowired
UserInfoService userInfoService;
@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 pre-approved, false otherwise
*/
@Override @Override
public boolean isApproved(AuthorizationRequest authorizationRequest, public boolean isApproved(AuthorizationRequest authorizationRequest, Authentication userAuthentication) {
Authentication userAuthentication) {
//Check database to see if the user identified by the userAuthentication has stored an approval decision //Check database to see if the user identified by the userAuthentication has stored an approval decision
userAuthentication.getPrincipal(); String userId = userAuthentication.getName();
ClientDetails client = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId());
//lookup ApprovedSites by userId
UserInfo user = userInfoService.getByUserId(userId);
Collection<ApprovedSite> approvedSites = approvedSiteService.getByUserInfo(user);
for (ApprovedSite ap : approvedSites) {
if (ap.getClientDetails().getClientId() == client.getClientId()) {
//TODO need to test more than just id
return true;
}
}
WhitelistedSite ws = whitelistedSiteService.getByClientDetails(client);
if (ws != null) {
//Create an approved site
ApprovedSite newAP = new ApprovedSite();
newAP.setAccessDate(new Date());
newAP.setWhitelistedSite(ws);
newAP.setAllowedScopes(ws.getAllowedScopes());
newAP.setCreationDate(new Date());
newAP.setUserInfo(user);
//TODO set timeout date?
approvedSiteService.save(newAP);
return true;
}
return false; return false;
} }

View File

@ -18,8 +18,6 @@ package org.mitre.openid.connect.web;
import java.security.Principal; import java.security.Principal;
import java.util.Set; 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.oauth2.service.OAuth2TokenEntityService;
import org.mitre.openid.connect.exception.UnknownUserInfoSchemaException; import org.mitre.openid.connect.exception.UnknownUserInfoSchemaException;
import org.mitre.openid.connect.model.DefaultUserInfo; import org.mitre.openid.connect.model.DefaultUserInfo;