diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java
index 7aab88860..35fd75f6f 100644
--- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java
+++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/ApprovedSite.java
@@ -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;
+	}
 	
 }
diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/WhitelistedSite.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/WhitelistedSite.java
index ce0b3564d..13af65712 100644
--- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/WhitelistedSite.java
+++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/WhitelistedSite.java
@@ -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;
+	}
 }
diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java
index 908cd7795..aa5448ae7 100644
--- a/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java
+++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/repository/WhitelistedSiteRepository.java
@@ -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
diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java
index ca8e766fe..365cfa9c0 100644
--- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java
+++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/UserInfoService.java
@@ -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
diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java
index bb0d67a0d..bb4568ae8 100644
--- a/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java
+++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/service/WhitelistedSiteService.java
@@ -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
 	 * 
diff --git a/openid-connect-server/db/tables/approvedsite.sql b/openid-connect-server/db/tables/approvedsite.sql
index 7b7897371..32b7fa629 100644
--- a/openid-connect-server/db/tables/approvedsite.sql
+++ b/openid-connect-server/db/tables/approvedsite.sql
@@ -4,5 +4,6 @@ CREATE TABLE approvedsite (
 	clientdetails_id VARCHAR(256),
 	creationDate DATE,
 	accessDate DATE,
-	timeoutDate DATE
+	timeoutDate DATE,
+	whitelistedsite_id VARCHAR(256)
 );
\ No newline at end of file
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java
index 5880622b3..00a51f3e1 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/repository/impl/JpaWhitelistedSiteRepository.java
@@ -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();
+	}
 }
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UserInfoServiceImpl.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UserInfoServiceImpl.java
index 6f7801af6..45c31fd60 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UserInfoServiceImpl.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/UserInfoServiceImpl.java
@@ -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);
 	}
 
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/WhitelistedSiteServiceImpl.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/WhitelistedSiteServiceImpl.java
index fb20cb05b..17a060ea5 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/WhitelistedSiteServiceImpl.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/service/impl/WhitelistedSiteServiceImpl.java
@@ -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);
+	}
+
 }
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/JdbcUserApprovalHandler.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/JdbcUserApprovalHandler.java
index d3597dca1..c4f6cf656 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/JdbcUserApprovalHandler.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/JdbcUserApprovalHandler.java
@@ -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;
 	}
 
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java
index 3c5f1ff4c..19ff70b90 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java
@@ -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;