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;
// which user made the approval
private String userInfo;
private UserInfo userInfo;
// which OAuth2 client is this tied to
private ClientDetailsEntity clientDetails;
@ -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?
/**
@ -93,15 +96,16 @@ public class ApprovedSite {
/**
* @return the userInfo
*/
@Basic
public String getUserInfo() {
@ManyToOne
@JoinColumn(name="userinfo_id")
public UserInfo getUserInfo() {
return userInfo;
}
/**
* @param userInfo the userInfo to set
*/
public void setUserInfo(String userInfo) {
public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo;
}
@ -183,7 +187,25 @@ public class ApprovedSite {
public void setTimeoutDate(Date 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 javax.persistence.Basic;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@ -35,22 +34,24 @@ 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.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 {
// 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 UserInfo creator;
// which OAuth2 client is this tied to
private ClientDetailsEntity clientDetails;
@ -81,21 +82,6 @@ public class WhitelistedSite {
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
*/
@ -126,4 +112,14 @@ public class WhitelistedSite {
public void setAllowedScopes(Set<String> 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 org.mitre.openid.connect.model.UserInfo;
import org.mitre.openid.connect.model.WhitelistedSite;
import org.springframework.security.oauth2.provider.ClientDetails;
/**
* WhitelistedSite repository interface
@ -42,6 +44,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 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

View File

@ -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

View File

@ -15,7 +15,11 @@
******************************************************************************/
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.springframework.security.oauth2.provider.ClientDetails;
/**
* Interface for WhitelistedSite service
@ -25,6 +29,13 @@ import org.mitre.openid.connect.model.WhitelistedSite;
*/
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 +45,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 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
*

View File

@ -4,5 +4,6 @@ CREATE TABLE approvedsite (
clientdetails_id VARCHAR(256),
creationDate 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.TypedQuery;
import org.mitre.openid.connect.model.UserInfo;
import org.mitre.openid.connect.model.WhitelistedSite;
import org.mitre.openid.connect.repository.WhitelistedSiteRepository;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
@ -80,4 +82,22 @@ public class JpaWhitelistedSiteRepository implements WhitelistedSiteRepository {
public WhitelistedSite save(WhitelistedSite 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;
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);
}

View File

@ -15,10 +15,14 @@
******************************************************************************/
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.repository.WhitelistedSiteRepository;
import org.mitre.openid.connect.service.WhitelistedSiteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -71,4 +75,19 @@ public class WhitelistedSiteServiceImpl implements WhitelistedSiteService {
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,20 +15,98 @@
******************************************************************************/
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.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;
/**
* 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 {
@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
public boolean isApproved(AuthorizationRequest authorizationRequest,
Authentication userAuthentication) {
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();
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;
}

View File

@ -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;