diff --git a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java
index 822d72112..6bf6111ef 100644
--- a/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java
+++ b/openid-connect-common/src/main/java/org/mitre/oauth2/model/OAuth2AccessTokenEntity.java
@@ -43,13 +43,12 @@ import javax.persistence.Table;
 import javax.persistence.Temporal;
 import javax.persistence.Transient;
 
+import org.mitre.openid.connect.model.ApprovedSite;
 import org.springframework.security.oauth2.common.OAuth2AccessToken;
 import org.springframework.security.oauth2.common.OAuth2RefreshToken;
 
 import com.nimbusds.jwt.JWT;
-import com.nimbusds.jwt.JWTClaimsSet;
 import com.nimbusds.jwt.JWTParser;
-import com.nimbusds.jwt.PlainJWT;
 
 /**
  * @author jricher
@@ -92,6 +91,8 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
 
 	private Set<String> scope;
 	
+	private ApprovedSite approvedSite; //Back-reference for one-to-many relationship
+	
 	/**
 	 * Create a new, blank access token
 	 */
@@ -284,4 +285,20 @@ public class OAuth2AccessTokenEntity implements OAuth2AccessToken {
 		// TODO Auto-generated method stub
 		return 0;
 	}
+
+	/**
+	 * @return the approvedSite
+	 */
+	@ManyToOne(fetch=FetchType.EAGER)
+	@JoinColumn(name="approved_site_id", referencedColumnName="id")
+	public ApprovedSite getApprovedSite() {
+		return approvedSite;
+	}
+
+	/**
+	 * @param approvedSite the approvedSite to set
+	 */
+	public void setApprovedSite(ApprovedSite approvedSite) {
+		this.approvedSite = approvedSite;
+	}
 }
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 cbf19b2c9..245ded4df 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
@@ -15,10 +15,12 @@
  ******************************************************************************/
 package org.mitre.openid.connect.model;
 
+import java.io.Serializable;
 import java.util.Date;
 import java.util.Set;
 
 import javax.persistence.Basic;
+import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -31,10 +33,15 @@ import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.NamedQueries;
 import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.persistence.Temporal;
 import javax.persistence.Transient;
 
+import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
+
+import com.google.common.collect.Sets;
+
 @Entity
 @Table(name="approved_site")
 @NamedQueries({
@@ -43,9 +50,11 @@ import javax.persistence.Transient;
 	@NamedQuery(name = "ApprovedSite.getByClientId", query = "select a from ApprovedSite a where a.clientId = :clientId"),
 	@NamedQuery(name = "ApprovedSite.getByClientIdAndUserId", query = "select a from ApprovedSite a where a.clientId = :clientId and a.userId = :userId")
 })
-public class ApprovedSite {
+public class ApprovedSite implements Serializable {
 
-    // unique id
+	private static final long serialVersionUID = 1L;
+
+	// unique id
     private Long id;
     
     // which user made the approval
@@ -70,7 +79,8 @@ public class ApprovedSite {
 	// If this AP is a WS, link to the WS
 	private WhitelistedSite whitelistedSite;
 	
-	// TODO: should we store the OAuth2 tokens and IdTokens here?
+	//Link to any access tokens approved through this stored decision
+	private Set<OAuth2AccessTokenEntity> approvedAccessTokens = Sets.newHashSet();
 	
 	/**
 	 * Empty constructor
@@ -235,5 +245,123 @@ public class ApprovedSite {
 			return false;
 		}
     }
+
+	/**
+	 * @return the approvedAccessTokens
+	 */
+	@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="approvedSite")
+	public Set<OAuth2AccessTokenEntity> getApprovedAccessTokens() {
+		return approvedAccessTokens;
+	}
+
+	/**
+	 * @param approvedAccessTokens the approvedAccessTokens to set
+	 */
+	public void setApprovedAccessTokens(Set<OAuth2AccessTokenEntity> approvedAccessTokens) {
+		this.approvedAccessTokens = approvedAccessTokens;
+	}
+
+	public void addApprovedAccessToken(OAuth2AccessTokenEntity token) {
+		this.getApprovedAccessTokens();
+		this.approvedAccessTokens.add(token);
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#hashCode()
+	 */
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((accessDate == null) ? 0 : accessDate.hashCode());
+		result = prime * result
+				+ ((allowedScopes == null) ? 0 : allowedScopes.hashCode());
+		result = prime * result
+				+ ((clientId == null) ? 0 : clientId.hashCode());
+		result = prime * result
+				+ ((creationDate == null) ? 0 : creationDate.hashCode());
+		result = prime * result + ((id == null) ? 0 : id.hashCode());
+		result = prime * result
+				+ ((timeoutDate == null) ? 0 : timeoutDate.hashCode());
+		result = prime * result + ((userId == null) ? 0 : userId.hashCode());
+		result = prime * result
+				+ ((whitelistedSite == null) ? 0 : whitelistedSite.hashCode());
+		return result;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (obj == null) {
+			return false;
+		}
+		if (!(obj instanceof ApprovedSite)) {
+			return false;
+		}
+		ApprovedSite other = (ApprovedSite) obj;
+		if (accessDate == null) {
+			if (other.accessDate != null) {
+				return false;
+			}
+		} else if (!accessDate.equals(other.accessDate)) {
+			return false;
+		}
+		if (allowedScopes == null) {
+			if (other.allowedScopes != null) {
+				return false;
+			}
+		} else if (!allowedScopes.equals(other.allowedScopes)) {
+			return false;
+		}
+		if (clientId == null) {
+			if (other.clientId != null) {
+				return false;
+			}
+		} else if (!clientId.equals(other.clientId)) {
+			return false;
+		}
+		if (creationDate == null) {
+			if (other.creationDate != null) {
+				return false;
+			}
+		} else if (!creationDate.equals(other.creationDate)) {
+			return false;
+		}
+		if (id == null) {
+			if (other.id != null) {
+				return false;
+			}
+		} else if (!id.equals(other.id)) {
+			return false;
+		}
+		if (timeoutDate == null) {
+			if (other.timeoutDate != null) {
+				return false;
+			}
+		} else if (!timeoutDate.equals(other.timeoutDate)) {
+			return false;
+		}
+		if (userId == null) {
+			if (other.userId != null) {
+				return false;
+			}
+		} else if (!userId.equals(other.userId)) {
+			return false;
+		}
+		if (whitelistedSite == null) {
+			if (other.whitelistedSite != null) {
+				return false;
+			}
+		} else if (!whitelistedSite.equals(other.whitelistedSite)) {
+			return false;
+		}
+		return true;
+	}
 	
 }
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 50dd016d7..a007dd102 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
@@ -15,6 +15,7 @@
  ******************************************************************************/
 package org.mitre.openid.connect.model;
 
+import java.io.Serializable;
 import java.util.Set;
 
 import javax.persistence.Basic;
@@ -44,9 +45,11 @@ import javax.persistence.Table;
 	@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 {
+public class WhitelistedSite implements Serializable {
 
-    // unique id
+	private static final long serialVersionUID = 1L;
+
+	// unique id
     private Long id;
     
     // Reference to the admin user who created this entry
@@ -127,4 +130,67 @@ public class WhitelistedSite {
 	public void setCreatorUserId(String creatorUserId) {
 		this.creatorUserId = creatorUserId;
 	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#hashCode()
+	 */
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((allowedScopes == null) ? 0 : allowedScopes.hashCode());
+		result = prime * result
+				+ ((clientId == null) ? 0 : clientId.hashCode());
+		result = prime * result
+				+ ((creatorUserId == null) ? 0 : creatorUserId.hashCode());
+		result = prime * result + ((id == null) ? 0 : id.hashCode());
+		return result;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) {
+			return true;
+		}
+		if (obj == null) {
+			return false;
+		}
+		if (!(obj instanceof WhitelistedSite)) {
+			return false;
+		}
+		WhitelistedSite other = (WhitelistedSite) obj;
+		if (allowedScopes == null) {
+			if (other.allowedScopes != null) {
+				return false;
+			}
+		} else if (!allowedScopes.equals(other.allowedScopes)) {
+			return false;
+		}
+		if (clientId == null) {
+			if (other.clientId != null) {
+				return false;
+			}
+		} else if (!clientId.equals(other.clientId)) {
+			return false;
+		}
+		if (creatorUserId == null) {
+			if (other.creatorUserId != null) {
+				return false;
+			}
+		} else if (!creatorUserId.equals(other.creatorUserId)) {
+			return false;
+		}
+		if (id == null) {
+			if (other.id != null) {
+				return false;
+			}
+		} else if (!id.equals(other.id)) {
+			return false;
+		}
+		return true;
+	}
 }
diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java
index 6dfb448ac..57f38db77 100644
--- a/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java
+++ b/openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ProviderTokenService.java
@@ -18,16 +18,12 @@
  */
 package org.mitre.oauth2.service.impl;
 
-import java.util.Collection;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
 
-import org.joda.time.DateTime;
-import org.joda.time.Period;
-import org.mitre.oauth2.exception.NonceReuseException;
 import org.mitre.oauth2.model.AuthenticationHolderEntity;
 import org.mitre.oauth2.model.ClientDetailsEntity;
 import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
@@ -36,8 +32,6 @@ import org.mitre.oauth2.repository.AuthenticationHolderRepository;
 import org.mitre.oauth2.repository.OAuth2TokenRepository;
 import org.mitre.oauth2.service.ClientDetailsEntityService;
 import org.mitre.oauth2.service.OAuth2TokenEntityService;
-import org.mitre.openid.connect.model.Nonce;
-import org.mitre.openid.connect.service.NonceService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java
index 8693e6569..cee14e312 100644
--- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java
+++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/IntrospectionEndpoint.java
@@ -64,7 +64,7 @@ public class IntrospectionEndpoint {
 		Map<String, Object> model = new HashMap<String, Object>();
 		model.put("entity", e);
 		
-		logger.error("InvalidTokenException: " + ex.getStackTrace().toString());
+		logger.error("InvalidTokenException: ", ex);
 		
 		model.put("code", HttpStatus.BAD_REQUEST);
 		
@@ -106,7 +106,7 @@ public class IntrospectionEndpoint {
 		try {
 			token = tokenServices.readAccessToken(tokenValue);		
 		} catch (AuthenticationException e) {
-			logger.error("Verify failed; AuthenticationException: " + e.getStackTrace().toString());
+			logger.error("Verify failed; AuthenticationException: ", e);
 			modelAndView.addObject("code", HttpStatus.FORBIDDEN);
 			modelAndView.setViewName("httpCodeView");
 			return modelAndView;
diff --git a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java
index bfffc158a..5d11d5465 100644
--- a/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java
+++ b/openid-connect-server/src/main/java/org/mitre/oauth2/web/OAuthConfirmationController.java
@@ -77,12 +77,12 @@ public class OAuthConfirmationController {
 			client = clientService.loadClientByClientId(clientAuth.getClientId());
 		} catch (OAuth2Exception e) {	
 			logger.error("confirmAccess: OAuth2Exception was thrown when attempting to load client: "
-					+ e.getStackTrace().toString());
+					, e);
 			model.put("code", HttpStatus.BAD_REQUEST);
 			return new ModelAndView("httpCodeView");
 		} catch (IllegalArgumentException e) {
 			logger.error("confirmAccess: IllegalArgumentException was thrown when attempting to load client: "
-					+ e.getStackTrace().toString());
+					, e);
 			model.put("code", HttpStatus.BAD_REQUEST);
 			return new ModelAndView("httpCodeView");
 		}
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java
index a56ae20f6..586d4e721 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/ConnectTokenEnhancer.java
@@ -24,10 +24,12 @@ import org.mitre.oauth2.model.ClientDetailsEntity;
 import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
 import org.mitre.oauth2.service.ClientDetailsEntityService;
 import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
+import org.mitre.openid.connect.model.ApprovedSite;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.provider.AuthorizationRequest;
 import org.springframework.security.oauth2.provider.OAuth2Authentication;
 import org.springframework.security.oauth2.provider.token.TokenEnhancer;
 import org.springframework.stereotype.Service;
@@ -57,8 +59,16 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
 	public OAuth2AccessToken enhance(OAuth2AccessToken accessToken,	OAuth2Authentication authentication) {
 		
 		OAuth2AccessTokenEntity token = (OAuth2AccessTokenEntity) accessToken;
+		AuthorizationRequest originalAuthRequest = authentication.getAuthorizationRequest();
 		
-		String clientId = authentication.getAuthorizationRequest().getClientId();
+		if (originalAuthRequest.getExtensionProperties().containsKey("approved_site")) {
+			//Add the token to the approved site reference, if there is one
+			ApprovedSite ap = (ApprovedSite)originalAuthRequest.getExtensionProperties().get("approved_site");
+			//ap.addApprovedAccessToken(token);
+			token.setApprovedSite(ap);
+		}
+		
+		String clientId = originalAuthRequest.getClientId();
 		ClientDetailsEntity client = clientService.loadClientByClientId(clientId);
 		
 		JWTClaimsSet claims = new JWTClaimsSet();
@@ -87,7 +97,7 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
 		 * has the proper scope, we can consider this a valid OpenID Connect request. Otherwise,
 		 * we consider it to be a vanilla OAuth2 request. 
 		 */
-		if (authentication.getAuthorizationRequest().getScope().contains("openid")) {
+		if (originalAuthRequest.getScope().contains("openid")) {
 
 			// TODO: maybe id tokens need a service layer
 			
@@ -114,7 +124,7 @@ public class ConnectTokenEnhancer implements TokenEnhancer {
 			idClaims.setAudience(Lists.newArrayList(clientId));
 			
 			
-			String nonce = authentication.getAuthorizationRequest().getAuthorizationParameters().get("nonce");
+			String nonce = originalAuthRequest.getAuthorizationParameters().get("nonce");
 			if (!Strings.isNullOrEmpty(nonce)) {
 				idClaims.setCustomClaim("nonce", nonce);
 			}
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java
index 6eabfab76..ddbb3539d 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/token/TofuUserApprovalHandler.java
@@ -117,6 +117,7 @@ public class TofuUserApprovalHandler implements UserApprovalHandler {
 					ap.setAccessDate(new Date());
 					approvedSiteService.save(ap);
 	
+					authorizationRequest.getExtensionProperties().put("approved_site", ap);
 					authorizationRequest.setApproved(true);					
 					alreadyApproved = true;
 				}
@@ -128,7 +129,8 @@ public class TofuUserApprovalHandler implements UserApprovalHandler {
 			if (ws != null && scopesMatch(authorizationRequest.getScope(), ws.getAllowedScopes())) {
 				
 				//Create an approved site
-				approvedSiteService.createApprovedSite(clientId, userId, null, ws.getAllowedScopes(), ws);				
+				ApprovedSite newSite = approvedSiteService.createApprovedSite(clientId, userId, null, ws.getAllowedScopes(), ws);	
+				authorizationRequest.getExtensionProperties().put("approved_site", newSite);
 				authorizationRequest.setApproved(true);
 			}
 		}
@@ -189,7 +191,8 @@ public class TofuUserApprovalHandler implements UserApprovalHandler {
 					timeout = cal.getTime();
 				}
 				
-				approvedSiteService.createApprovedSite(clientId, userId, timeout, allowedScopes, null);
+				ApprovedSite newSite = approvedSiteService.createApprovedSite(clientId, userId, timeout, allowedScopes, null);
+				authorizationRequest.getExtensionProperties().put("approved_site", newSite);
 			}
 			
 		}
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java
index 8c3ff9c01..5c3907165 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ApprovedSiteAPI.java
@@ -5,7 +5,10 @@ package org.mitre.openid.connect.web;
 
 import java.security.Principal;
 import java.util.Collection;
+import java.util.Set;
 
+import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
+import org.mitre.oauth2.service.OAuth2TokenEntityService;
 import org.mitre.openid.connect.model.ApprovedSite;
 import org.mitre.openid.connect.service.ApprovedSiteService;
 import org.slf4j.Logger;
@@ -31,6 +34,9 @@ public class ApprovedSiteAPI {
 	@Autowired
 	private ApprovedSiteService approvedSiteService;
 	
+	@Autowired
+	OAuth2TokenEntityService tokenServices;
+	
 	private static Logger logger = LoggerFactory.getLogger(ApprovedSiteAPI.class);
 
 	/**
@@ -69,7 +75,19 @@ public class ApprovedSiteAPI {
 			return "jsonErrorView";
 		} else {
 			m.put("code", HttpStatus.OK);
+			
+			Set<OAuth2AccessTokenEntity> accessTokens = approvedSite.getApprovedAccessTokens();
+
+			for (OAuth2AccessTokenEntity token : accessTokens) {
+				if (token.getRefreshToken() != null) {
+					//TODO: how should refresh tokens be handled if you delete an approved site?
+					//tokenServices.revokeRefreshToken(token.getRefreshToken());
+				}
+				tokenServices.revokeAccessToken(token);
+			}
+			
 			approvedSiteService.remove(approvedSite);
+			
 		}		
 		
 		return "httpCodeView";
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java
index 85683c013..f535c6e14 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/BlacklistAPI.java
@@ -80,12 +80,12 @@ public class BlacklistAPI {
 			
 		} 
 		catch (JsonSyntaxException e) {
-			logger.error("addNewBlacklistedSite failed due to JsonSyntaxException: " + e.getStackTrace().toString());
+			logger.error("addNewBlacklistedSite failed due to JsonSyntaxException: " , e);
 			m.put("code", HttpStatus.BAD_REQUEST);
 			m.put("errorMessage", "Could not save new blacklisted site. The server encountered a JSON syntax exception. Contact a system administrator for assistance.");
 			return "jsonErrorView";
 		} catch (IllegalStateException e) {
-			logger.error("addNewBlacklistedSite failed due to IllegalStateException: " + e.getStackTrace().toString());
+			logger.error("addNewBlacklistedSite failed due to IllegalStateException: " , e);
 			m.put("code", HttpStatus.BAD_REQUEST);
 			m.put("errorMessage", "Could not save new blacklisted site. The server encountered an IllegalStateException. Refresh and try again - if the problem persists, contact a system administrator for assistance.");
 			return "jsonErrorView";
@@ -112,12 +112,12 @@ public class BlacklistAPI {
 			
 		} 
 		catch (JsonSyntaxException e) {
-			logger.error("updateBlacklistedSite failed due to JsonSyntaxException: " + e.getStackTrace().toString());
+			logger.error("updateBlacklistedSite failed due to JsonSyntaxException: " , e);
 			m.put("code", HttpStatus.BAD_REQUEST);
 			m.put("errorMessage", "Could not update blacklisted site. The server encountered a JSON syntax exception. Contact a system administrator for assistance.");
 			return "jsonErrorView";
 		} catch (IllegalStateException e) {
-			logger.error("updateBlacklistedSite failed due to IllegalStateException: " + e.getStackTrace().toString());
+			logger.error("updateBlacklistedSite failed due to IllegalStateException: " , e);
 			m.put("code", HttpStatus.BAD_REQUEST);
 			m.put("errorMessage", "Could not update blacklisted site. The server encountered an IllegalStateException. Refresh and try again - if the problem persists, contact a system administrator for assistance.");
 			return "jsonErrorView";
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java
index 432af2ac6..09b73e789 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/ClientAPI.java
@@ -136,12 +136,12 @@ public class ClientAPI {
     		client = gson.fromJson(json, ClientDetailsEntity.class);
     	} 
     	catch (JsonSyntaxException e) {
-    		logger.error("apiAddClient failed due to JsonSyntaxException: " + e.getStackTrace().toString());
+    		logger.error("apiAddClient failed due to JsonSyntaxException: " , e);
     		m.addAttribute("code", HttpStatus.BAD_REQUEST);
     		m.addAttribute("errorMessage", "Could not save new client. The server encountered a JSON syntax exception. Contact a system administrator for assistance.");
 			return "jsonErrorView";
     	} catch (IllegalStateException e) {
-    		logger.error("apiAddClient failed due to IllegalStateException: " + e.getStackTrace().toString());
+    		logger.error("apiAddClient failed due to IllegalStateException: " , e);
     		m.addAttribute("code", HttpStatus.BAD_REQUEST);
     		m.addAttribute("errorMessage", "Could not save new client. The server encountered an IllegalStateException. Refresh and try again - if the problem persists, contact a system administrator for assistance.");
 			return "jsonErrorView";
@@ -193,12 +193,12 @@ public class ClientAPI {
     		client = gson.fromJson(json, ClientDetailsEntity.class);
     	} 
     	catch (JsonSyntaxException e) {
-    		logger.error("apiUpdateClient failed due to JsonSyntaxException: " + e.getStackTrace().toString());
+    		logger.error("apiUpdateClient failed due to JsonSyntaxException: " , e);
     		m.addAttribute("code", HttpStatus.BAD_REQUEST);
     		m.addAttribute("errorMessage", "Could not update client. The server encountered a JSON syntax exception. Contact a system administrator for assistance.");
 			return "jsonErrorView";
     	} catch (IllegalStateException e) {
-    		logger.error("apiUpdateClient failed due to IllegalStateException: " + e.getStackTrace().toString());
+    		logger.error("apiUpdateClient failed due to IllegalStateException: " , e);
     		m.addAttribute("code", HttpStatus.BAD_REQUEST);
     		m.addAttribute("errorMessage", "Could not update client. The server encountered an IllegalStateException. Refresh and try again - if the problem persists, contact a system administrator for assistance.");
 			return "jsonErrorView";
diff --git a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java
index f28bf8040..43a8ed21d 100644
--- a/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java
+++ b/openid-connect-server/src/main/java/org/mitre/openid/connect/web/WhitelistAPI.java
@@ -76,12 +76,12 @@ public class WhitelistAPI {
 			whitelist = gson.fromJson(json, WhitelistedSite.class);
 
 		} catch (JsonParseException e) {
-			logger.error("addNewWhitelistedSite failed due to JsonParseException: " + e.getStackTrace().toString());
+			logger.error("addNewWhitelistedSite failed due to JsonParseException: " , e);
 			m.addAttribute("code", HttpStatus.BAD_REQUEST);
 			m.addAttribute("errorMessage", "Could not save new whitelisted site. The server encountered a JSON syntax exception. Contact a system administrator for assistance.");
 			return "jsonErrorView";
 		} catch (IllegalStateException e) {
-			logger.error("addNewWhitelistedSite failed due to IllegalStateException: " + e.getStackTrace().toString());
+			logger.error("addNewWhitelistedSite failed due to IllegalStateException: " , e);
 			m.addAttribute("code", HttpStatus.BAD_REQUEST);
 			m.addAttribute("errorMessage", "Could not save new whitelisted site. The server encountered an IllegalStateException. Refresh and try again - if the problem persists, contact a system administrator for assistance.");
 			return "jsonErrorView";
@@ -113,12 +113,12 @@ public class WhitelistAPI {
 			whitelist = gson.fromJson(json, WhitelistedSite.class);
 
 		} catch (JsonParseException e) {
-			logger.error("updateWhitelistedSite failed due to JsonParseException: " + e.getStackTrace().toString());
+			logger.error("updateWhitelistedSite failed due to JsonParseException: " , e);
 			m.put("code", HttpStatus.BAD_REQUEST);
 			m.put("errorMessage", "Could not update whitelisted site. The server encountered a JSON syntax exception. Contact a system administrator for assistance.");
 			return "jsonErrorView";
 		} catch (IllegalStateException e) {
-			logger.error("updateWhitelistedSite failed due to IllegalStateException: " + e.getStackTrace().toString());
+			logger.error("updateWhitelistedSite failed due to IllegalStateException: " , e);
 			m.put("code", HttpStatus.BAD_REQUEST);
 			m.put("errorMessage", "Could not update whitelisted site. The server encountered an IllegalStateException. Refresh and try again - if the problem persists, contact a system administrator for assistance.");
 			return "jsonErrorView";
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 17ac3e443..b1230acc6 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
@@ -10,7 +10,8 @@ CREATE TABLE IF NOT EXISTS access_token (
 	refresh_token_id BIGINT,
 	client_id VARCHAR(256),
 	auth_holder_id BIGINT,
-	id_token_id BIGINT
+	id_token_id BIGINT,
+	approved_site_id BIGINT
 );
 
 CREATE TABLE IF NOT EXISTS address (
diff --git a/spring-security-oauth b/spring-security-oauth
index 570f83ff8..24b8229e5 160000
--- a/spring-security-oauth
+++ b/spring-security-oauth
@@ -1 +1 @@
-Subproject commit 570f83ff8a9d27022cb0f2a17f72a26f019120bb
+Subproject commit 24b8229e5cc34504d5854ec41e3c4b7248981dc2