diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java
index a55e3f9c1..c6d8d9692 100644
--- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java
+++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/DefaultUserInfo.java
@@ -67,6 +67,7 @@ public class DefaultUserInfo implements UserInfo {
 	private Address address;
 	private String updatedTime;
 	private String birthdate;
+	private JsonObject src; // source JSON if this is loaded remotely
 
 
 	/**
@@ -408,45 +409,52 @@ public class DefaultUserInfo implements UserInfo {
 
 	@Override
 	public JsonObject toJson() {
-		JsonObject obj = new JsonObject();
-
-		obj.addProperty("sub", this.getSub());
-
-		obj.addProperty("name", this.getName());
-		obj.addProperty("preferred_username", this.getPreferredUsername());
-		obj.addProperty("given_name", this.getGivenName());
-		obj.addProperty("family_name", this.getFamilyName());
-		obj.addProperty("middle_name", this.getMiddleName());
-		obj.addProperty("nickname", this.getNickname());
-		obj.addProperty("profile", this.getProfile());
-		obj.addProperty("picture", this.getPicture());
-		obj.addProperty("website", this.getWebsite());
-		obj.addProperty("gender", this.getGender());
-		obj.addProperty("zone_info", this.getZoneinfo());
-		obj.addProperty("locale", this.getLocale());
-		obj.addProperty("updated_time", this.getUpdatedTime());
-		obj.addProperty("birthdate", this.getBirthdate());
-
-		obj.addProperty("email", this.getEmail());
-		obj.addProperty("email_verified", this.getEmailVerified());
-
-		obj.addProperty("phone_number", this.getPhoneNumber());
-		obj.addProperty("phone_number_verified", this.getPhoneNumberVerified());
-
-		if (this.getAddress() != null) {
-
-			JsonObject addr = new JsonObject();
-			addr.addProperty("formatted", this.getAddress().getFormatted());
-			addr.addProperty("street_address", this.getAddress().getStreetAddress());
-			addr.addProperty("locality", this.getAddress().getLocality());
-			addr.addProperty("region", this.getAddress().getRegion());
-			addr.addProperty("postal_code", this.getAddress().getPostalCode());
-			addr.addProperty("country", this.getAddress().getCountry());
-
-			obj.add("address", addr);
+		
+		if (src == null) {
+		
+			JsonObject obj = new JsonObject();
+	
+			obj.addProperty("sub", this.getSub());
+	
+			obj.addProperty("name", this.getName());
+			obj.addProperty("preferred_username", this.getPreferredUsername());
+			obj.addProperty("given_name", this.getGivenName());
+			obj.addProperty("family_name", this.getFamilyName());
+			obj.addProperty("middle_name", this.getMiddleName());
+			obj.addProperty("nickname", this.getNickname());
+			obj.addProperty("profile", this.getProfile());
+			obj.addProperty("picture", this.getPicture());
+			obj.addProperty("website", this.getWebsite());
+			obj.addProperty("gender", this.getGender());
+			obj.addProperty("zone_info", this.getZoneinfo());
+			obj.addProperty("locale", this.getLocale());
+			obj.addProperty("updated_time", this.getUpdatedTime());
+			obj.addProperty("birthdate", this.getBirthdate());
+	
+			obj.addProperty("email", this.getEmail());
+			obj.addProperty("email_verified", this.getEmailVerified());
+	
+			obj.addProperty("phone_number", this.getPhoneNumber());
+			obj.addProperty("phone_number_verified", this.getPhoneNumberVerified());
+	
+			if (this.getAddress() != null) {
+	
+				JsonObject addr = new JsonObject();
+				addr.addProperty("formatted", this.getAddress().getFormatted());
+				addr.addProperty("street_address", this.getAddress().getStreetAddress());
+				addr.addProperty("locality", this.getAddress().getLocality());
+				addr.addProperty("region", this.getAddress().getRegion());
+				addr.addProperty("postal_code", this.getAddress().getPostalCode());
+				addr.addProperty("country", this.getAddress().getCountry());
+	
+				obj.add("address", addr);
+			}
+	
+			return obj;
+		} else {
+			return src;
 		}
 
-		return obj;
 	}
 
 	/**
@@ -456,6 +464,7 @@ public class DefaultUserInfo implements UserInfo {
 	 */
 	public static UserInfo fromJson(JsonObject obj) {
 		DefaultUserInfo ui = new DefaultUserInfo();
+		ui.setSource(obj);
 
 		ui.setSub(nullSafeGetString(obj, "sub"));
 
@@ -497,6 +506,22 @@ public class DefaultUserInfo implements UserInfo {
 		return ui;
 
 	}
+	/**
+	 * @return the jsonString
+	 */
+	@Override
+	public JsonObject getSource() {
+		return src;
+	}
+
+	/**
+	 * @param jsonString the jsonString to set
+	 */
+	public void setSource(JsonObject src) {
+		this.src = src;
+	}
+	
+	
 	private static String nullSafeGetString(JsonObject obj, String field) {
 		return obj.has(field) && obj.get(field).isJsonPrimitive() ? obj.get(field).getAsString() : null;
 	}
diff --git a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java
index ec9326020..47f13b794 100644
--- a/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java
+++ b/openid-connect-common/src/main/java/org/mitre/openid/connect/model/UserInfo.java
@@ -26,212 +26,218 @@ public interface UserInfo extends Serializable {
 	/**
 	 * @return the userId
 	 */
-	public abstract String getSub();
+	public String getSub();
 
 	/**
 	 * @param sub the userId to set
 	 */
-	public abstract void setSub(String sub);
+	public void setSub(String sub);
 
 	/**
 	 * @return the preferred username
 	 */
-	public abstract String getPreferredUsername();
+	public String getPreferredUsername();
 
 	/**
 	 * @param preferredUsername the preferredUsername to set
 	 */
-	public abstract void setPreferredUsername(String preferredUsername);
+	public void setPreferredUsername(String preferredUsername);
 
 	/**
 	 * @return the name
 	 */
-	public abstract String getName();
+	public String getName();
 
 	/**
 	 * @param name the name to set
 	 */
-	public abstract void setName(String name);
+	public void setName(String name);
 
 	/**
 	 * @return the givenName
 	 */
-	public abstract String getGivenName();
+	public String getGivenName();
 
 	/**
 	 * @param givenName the givenName to set
 	 */
-	public abstract void setGivenName(String givenName);
+	public void setGivenName(String givenName);
 
 	/**
 	 * @return the familyName
 	 */
-	public abstract String getFamilyName();
+	public String getFamilyName();
 
 	/**
 	 * @param familyName the familyName to set
 	 */
-	public abstract void setFamilyName(String familyName);
+	public void setFamilyName(String familyName);
 
 	/**
 	 * @return the middleName
 	 */
-	public abstract String getMiddleName();
+	public String getMiddleName();
 
 	/**
 	 * @param middleName the middleName to set
 	 */
-	public abstract void setMiddleName(String middleName);
+	public void setMiddleName(String middleName);
 
 	/**
 	 * @return the nickname
 	 */
-	public abstract String getNickname();
+	public String getNickname();
 
 	/**
 	 * @param nickname the nickname to set
 	 */
-	public abstract void setNickname(String nickname);
+	public void setNickname(String nickname);
 
 	/**
 	 * @return the profile
 	 */
-	public abstract String getProfile();
+	public String getProfile();
 
 	/**
 	 * @param profile the profile to set
 	 */
-	public abstract void setProfile(String profile);
+	public void setProfile(String profile);
 
 	/**
 	 * @return the picture
 	 */
-	public abstract String getPicture();
+	public String getPicture();
 
 	/**
 	 * @param picture the picture to set
 	 */
-	public abstract void setPicture(String picture);
+	public void setPicture(String picture);
 
 	/**
 	 * @return the website
 	 */
-	public abstract String getWebsite();
+	public String getWebsite();
 
 	/**
 	 * @param website the website to set
 	 */
-	public abstract void setWebsite(String website);
+	public void setWebsite(String website);
 
 	/**
 	 * @return the email
 	 */
-	public abstract String getEmail();
+	public String getEmail();
 
 	/**
 	 * @param email the email to set
 	 */
-	public abstract void setEmail(String email);
+	public void setEmail(String email);
 
 	/**
 	 * @return the verified
 	 */
-	public abstract Boolean getEmailVerified();
+	public Boolean getEmailVerified();
 
 	/**
 	 * @param verified the verified to set
 	 */
-	public abstract void setEmailVerified(Boolean emailVerified);
+	public void setEmailVerified(Boolean emailVerified);
 
 	/**
 	 * @return the gender
 	 */
-	public abstract String getGender();
+	public String getGender();
 
 	/**
 	 * @param gender the gender to set
 	 */
-	public abstract void setGender(String gender);
+	public void setGender(String gender);
 
 	/**
 	 * @return the zoneinfo
 	 */
-	public abstract String getZoneinfo();
+	public String getZoneinfo();
 
 	/**
 	 * @param zoneinfo the zoneinfo to set
 	 */
-	public abstract void setZoneinfo(String zoneinfo);
+	public void setZoneinfo(String zoneinfo);
 
 	/**
 	 * @return the locale
 	 */
-	public abstract String getLocale();
+	public String getLocale();
 
 	/**
 	 * @param locale the locale to set
 	 */
-	public abstract void setLocale(String locale);
+	public void setLocale(String locale);
 
 	/**
 	 * @return the phoneNumber
 	 */
-	public abstract String getPhoneNumber();
+	public String getPhoneNumber();
 
 	/**
 	 * @param phoneNumber the phoneNumber to set
 	 */
-	public abstract void setPhoneNumber(String phoneNumber);
+	public void setPhoneNumber(String phoneNumber);
 
 	/**
 	 * 
 	 */
-	public abstract Boolean getPhoneNumberVerified();
+	public Boolean getPhoneNumberVerified();
 
 	/**
 	 * 
 	 * @param phoneNumberVerified
 	 */
-	public abstract void setPhoneNumberVerified(Boolean phoneNumberVerified);
+	public void setPhoneNumberVerified(Boolean phoneNumberVerified);
 
 	/**
 	 * @return the address
 	 */
-	public abstract Address getAddress();
+	public Address getAddress();
 
 	/**
 	 * @param address the address to set
 	 */
-	public abstract void setAddress(Address address);
+	public void setAddress(Address address);
 
 	/**
 	 * @return the updatedTime
 	 */
-	public abstract String getUpdatedTime();
+	public String getUpdatedTime();
 
 	/**
 	 * @param updatedTime the updatedTime to set
 	 */
-	public abstract void setUpdatedTime(String updatedTime);
+	public void setUpdatedTime(String updatedTime);
 
 
 	/**
 	 * 
 	 * @return
 	 */
-	public abstract String getBirthdate();
+	public String getBirthdate();
 
 	/**
 	 * 
 	 * @param birthdate
 	 */
-	public abstract void setBirthdate(String birthdate);
+	public void setBirthdate(String birthdate);
 
 	/**
-	 * Serialize this UserInfo object to JSON
+	 * Serialize this UserInfo object to JSON.
 	 * 
 	 * @return
 	 */
-	public abstract JsonObject toJson();
+	public JsonObject toJson();
+	
+	/**
+	 * The JSON source of this UserInfo (if it was fetched), or null if it's local.
+	 * @return
+	 */
+	public JsonObject getSource();
 
 }