added scope-based filter for userinfo

pull/105/merge
Justin Richer 2012-07-05 17:14:51 -04:00
parent c24a2206e9
commit f0c949fd09
5 changed files with 133 additions and 118 deletions

View File

@ -20,8 +20,10 @@ import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType; import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Table;
@Entity @Entity
@Table(name="address")
public class Address { public class Address {

View File

@ -17,6 +17,8 @@ package org.mitre.openid.connect.model;
import javax.persistence.Basic; import javax.persistence.Basic;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.Inheritance; import javax.persistence.Inheritance;
import javax.persistence.InheritanceType; import javax.persistence.InheritanceType;
@ -54,43 +56,12 @@ public class DefaultUserInfo implements UserInfo {
private String updatedTime; private String updatedTime;
public JsonObject toJson() {
JsonObject obj = new JsonObject();
obj.addProperty("user_id", getUserId());
obj.addProperty("name", getName());
obj.addProperty("given_name", getGivenName());
obj.addProperty("family_name", getFamilyName());
obj.addProperty("middle_name", getMiddleName());
obj.addProperty("nickname", getNickname());
obj.addProperty("profile", getProfile());
obj.addProperty("picture", getPicture());
obj.addProperty("website", getWebsite());
obj.addProperty("verified", getVerified());
obj.addProperty("gender", getGender());
obj.addProperty("zone_info", getZoneinfo());
obj.addProperty("locale", getLocale());
obj.addProperty("phone_number", getPhoneNumber());
obj.addProperty("updated_time", getUpdatedTime());
JsonObject addr = new JsonObject();
addr.addProperty("formatted", getAddress().getFormatted());
addr.addProperty("street_address", getAddress().getStreetAddress());
addr.addProperty("locality", getAddress().getLocality());
addr.addProperty("region", getAddress().getRegion());
addr.addProperty("postal_code", getAddress().getPostalCode());
addr.addProperty("country", getAddress().getCountry());
obj.add("address", addr);
return obj;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.mitre.openid.connect.model.UserInfo#getUserId() * @see org.mitre.openid.connect.model.UserInfo#getUserId()
*/ */
@Override @Override
@Id @Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
public String getUserId() { public String getUserId() {
return userId; return userId;
} }

View File

@ -17,6 +17,7 @@ package org.mitre.openid.connect.view;
import java.io.Writer; import java.io.Writer;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -42,6 +43,8 @@ public class JSONUserInfoView extends AbstractView{
UserInfo userInfo = (UserInfo) model.get("userInfo"); UserInfo userInfo = (UserInfo) model.get("userInfo");
Set<String> scope = (Set<String>) model.get("scope");
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() { .setExclusionStrategies(new ExclusionStrategy() {
@ -62,31 +65,42 @@ public class JSONUserInfoView extends AbstractView{
response.setContentType("application/json"); response.setContentType("application/json");
Writer out = response.getWriter(); Writer out = response.getWriter();
gson.toJson(toJson(userInfo),out); gson.toJson(toJson(userInfo, scope), out);
} }
private JsonObject toJson(UserInfo ui) { private JsonObject toJson(UserInfo ui, Set<String> scope) {
JsonObject obj = new JsonObject(); JsonObject obj = new JsonObject();
obj.addProperty("user_id", ui.getUserId()); if (scope.contains("openid")) {
obj.addProperty("name", ui.getName()); obj.addProperty("user_id", ui.getUserId());
obj.addProperty("given_name", ui.getGivenName()); }
obj.addProperty("family_name", ui.getFamilyName());
obj.addProperty("middle_name", ui.getMiddleName());
obj.addProperty("nickname", ui.getNickname());
obj.addProperty("email", ui.getEmail());
obj.addProperty("profile", ui.getProfile());
obj.addProperty("picture", ui.getPicture());
obj.addProperty("email", ui.getEmail());
obj.addProperty("website", ui.getWebsite());
obj.addProperty("verified", ui.getVerified());
obj.addProperty("gender", ui.getGender());
obj.addProperty("zone_info", ui.getZoneinfo());
obj.addProperty("locale", ui.getLocale());
obj.addProperty("phone_number", ui.getPhoneNumber());
obj.addProperty("updated_time", ui.getUpdatedTime());
if (ui.getAddress() != null) { if (scope.contains("profile")) {
obj.addProperty("name", ui.getName());
obj.addProperty("given_name", ui.getGivenName());
obj.addProperty("family_name", ui.getFamilyName());
obj.addProperty("middle_name", ui.getMiddleName());
obj.addProperty("nickname", ui.getNickname());
obj.addProperty("profile", ui.getProfile());
obj.addProperty("picture", ui.getPicture());
obj.addProperty("website", ui.getWebsite());
obj.addProperty("gender", ui.getGender());
obj.addProperty("zone_info", ui.getZoneinfo());
obj.addProperty("locale", ui.getLocale());
obj.addProperty("updated_time", ui.getUpdatedTime());
// TODO: preferred_username
}
if (scope.contains("email")) {
obj.addProperty("email", ui.getEmail());
obj.addProperty("verified", ui.getVerified());
}
if (scope.contains("phone")) {
obj.addProperty("phone_number", ui.getPhoneNumber());
}
if (scope.contains("address") && ui.getAddress() != null) {
JsonObject addr = new JsonObject(); JsonObject addr = new JsonObject();
addr.addProperty("formatted", ui.getAddress().getFormatted()); addr.addProperty("formatted", ui.getAddress().getFormatted());

View File

@ -17,6 +17,7 @@ package org.mitre.openid.connect.view;
import java.io.Writer; import java.io.Writer;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -43,6 +44,8 @@ public class POCOUserInfoView extends AbstractView{
UserInfo userInfo = (UserInfo) model.get("userInfo"); UserInfo userInfo = (UserInfo) model.get("userInfo");
Set<String> scope = (Set<String>) model.get("scope");
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() { .setExclusionStrategies(new ExclusionStrategy() {
@ -63,10 +66,10 @@ public class POCOUserInfoView extends AbstractView{
response.setContentType("application/json"); response.setContentType("application/json");
Writer out = response.getWriter(); Writer out = response.getWriter();
gson.toJson(toPoco(userInfo),out); gson.toJson(toPoco(userInfo, scope), out);
} }
private JsonObject toPoco(UserInfo ui) { private JsonObject toPoco(UserInfo ui, Set<String> scope) {
JsonObject poco = new JsonObject(); JsonObject poco = new JsonObject();
// Envelope Info // Envelope Info
@ -76,74 +79,88 @@ public class POCOUserInfoView extends AbstractView{
// Build the entry for this userInfo, then add it to entries, then add it to poco // Build the entry for this userInfo, then add it to entries, then add it to poco
JsonObject entry = new JsonObject(); JsonObject entry = new JsonObject();
entry.addProperty("id", ui.getUserId());
entry.addProperty("displayName", ui.getNickname());
if(ui.getFamilyName() != null if (scope.contains("openid")) {
|| ui.getGivenName() != null entry.addProperty("id", ui.getUserId());
|| ui.getMiddleName() != null
|| ui.getName() != null) {
JsonObject name = new JsonObject();
name.addProperty("familyName", ui.getFamilyName());
name.addProperty("givenName", ui.getGivenName());
name.addProperty("middleName", ui.getMiddleName());
name.addProperty("formatted", ui.getName());
entry.add("name", name);
} }
entry.addProperty("gender", ui.getGender()); if (scope.contains("profile")) {
entry.addProperty("displayName", ui.getNickname());
if(ui.getEmail() != null) {
JsonObject email = new JsonObject();
email.addProperty("value", ui.getEmail());
JsonArray emailArray = new JsonArray(); if(ui.getFamilyName() != null
emailArray.add(email); || ui.getGivenName() != null
entry.add("emails", emailArray); || ui.getMiddleName() != null
} || ui.getName() != null) {
JsonObject name = new JsonObject();
name.addProperty("familyName", ui.getFamilyName());
name.addProperty("givenName", ui.getGivenName());
name.addProperty("middleName", ui.getMiddleName());
name.addProperty("formatted", ui.getName());
entry.add("name", name);
}
if(ui.getPhoneNumber() != null){ entry.addProperty("gender", ui.getGender());
JsonObject phone = new JsonObject(); // TODO: preferred_username
phone.addProperty("value", ui.getPhoneNumber()); if(ui.getPicture() != null){
JsonObject photo = new JsonObject();
photo.addProperty("value", ui.getPicture());
JsonArray photoArray = new JsonArray();
photoArray.add(photo);
entry.add("photos", photoArray);
}
JsonArray phoneArray = new JsonArray(); if(ui.getWebsite() != null) {
phoneArray.add(phone); JsonObject website = new JsonObject();
entry.add("phoneNumbers", phoneArray); website.addProperty("value", ui.getWebsite());
}
JsonArray websiteArray = new JsonArray();
if(ui.getPicture() != null){ websiteArray.add(website);
JsonObject photo = new JsonObject(); entry.add("urls", websiteArray);
photo.addProperty("value", ui.getPicture()); }
entry.addProperty("updated", ui.getUpdatedTime());
JsonArray photoArray = new JsonArray();
photoArray.add(photo);
entry.add("photos", photoArray);
} }
if(ui.getWebsite() != null) { if (scope.contains("email")) {
JsonObject website = new JsonObject(); if(ui.getEmail() != null) {
website.addProperty("value", ui.getWebsite()); JsonObject email = new JsonObject();
email.addProperty("value", ui.getEmail());
JsonArray websiteArray = new JsonArray();
websiteArray.add(website); JsonArray emailArray = new JsonArray();
entry.add("urls", websiteArray); emailArray.add(email);
entry.add("emails", emailArray);
}
} }
if(ui.getAddress() != null) { if (scope.contains("phone")) {
JsonObject addr = new JsonObject(); if(ui.getPhoneNumber() != null){
addr.addProperty("formatted", ui.getAddress().getFormatted()); JsonObject phone = new JsonObject();
addr.addProperty("streetAddress", ui.getAddress().getStreetAddress()); phone.addProperty("value", ui.getPhoneNumber());
addr.addProperty("locality", ui.getAddress().getLocality());
addr.addProperty("region", ui.getAddress().getRegion()); JsonArray phoneArray = new JsonArray();
addr.addProperty("postalCode", ui.getAddress().getPostalCode()); phoneArray.add(phone);
addr.addProperty("country", ui.getAddress().getCountry()); entry.add("phoneNumbers", phoneArray);
}
JsonArray addrArray = new JsonArray();
addrArray.add(addr);
entry.add("addresses", addrArray);
} }
entry.addProperty("updated", ui.getUpdatedTime()); if (scope.contains("address")) {
if(ui.getAddress() != null) {
JsonObject addr = new JsonObject();
addr.addProperty("formatted", ui.getAddress().getFormatted());
addr.addProperty("streetAddress", ui.getAddress().getStreetAddress());
addr.addProperty("locality", ui.getAddress().getLocality());
addr.addProperty("region", ui.getAddress().getRegion());
addr.addProperty("postalCode", ui.getAddress().getPostalCode());
addr.addProperty("country", ui.getAddress().getCountry());
JsonArray addrArray = new JsonArray();
addrArray.add(addr);
entry.add("addresses", addrArray);
}
}
JsonArray entryArray = new JsonArray(); JsonArray entryArray = new JsonArray();
entryArray.add(entry); entryArray.add(entry);

View File

@ -16,16 +16,21 @@
package org.mitre.openid.connect.web; package org.mitre.openid.connect.web;
import java.security.Principal; import java.security.Principal;
import java.util.Set;
import org.mitre.oauth2.model.ClientDetailsEntity; import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.model.OAuth2AccessTokenEntity; 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.UserInfo; import org.mitre.openid.connect.model.UserInfo;
import org.mitre.openid.connect.service.UserInfoService; import org.mitre.openid.connect.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
@ -55,21 +60,17 @@ public class UserInfoEndpoint {
/** /**
* Get information about the user as specified in the accessToken->idToken included in this request * Get information about the user as specified in the accessToken->idToken included in this request
* *
* @param accessToken the Access Token associated with this request
* @param schema the data schema to use, default is openid
* @param mav the ModelAndView object associated with this request
* @return JSON or JWT response containing UserInfo data
* @throws UsernameNotFoundException if the user does not exist or cannot be found * @throws UsernameNotFoundException if the user does not exist or cannot be found
* @throws UnknownUserInfoSchemaException if an unknown schema is used * @throws UnknownUserInfoSchemaException if an unknown schema is used
*/ */
@PreAuthorize("hasRole('ROLE_USER')") // TODO: need to add the check for the "openid" scope, which is REQUIRED
@RequestMapping(value="/userinfo", method= {RequestMethod.GET, RequestMethod.POST}) @RequestMapping(value="/userinfo", method= {RequestMethod.GET, RequestMethod.POST})
public ModelAndView getInfo(Principal p, @RequestParam("schema") String schema, ModelAndView mav) { public String getInfo(Principal p, @RequestParam("schema") String schema, Model model) {
if (p == null) { if (p == null) {
throw new UsernameNotFoundException("Invalid User"); throw new UsernameNotFoundException("Invalid User");
} }
String viewName = null; String viewName = null;
if (schema.equalsIgnoreCase( openIdSchema )){ if (schema.equalsIgnoreCase( openIdSchema )){
viewName = jsonUserInfoViewName; viewName = jsonUserInfoViewName;
@ -85,8 +86,18 @@ public class UserInfoEndpoint {
throw new UsernameNotFoundException("Invalid User"); throw new UsernameNotFoundException("Invalid User");
} }
return new ModelAndView(viewName, "userInfo", userInfo); if (p instanceof OAuth2Authentication) {
OAuth2Authentication authentication = (OAuth2Authentication)p;
model.addAttribute("scope", authentication.getAuthorizationRequest().getScope());
}
model.addAttribute("userInfo", userInfo);
//return new ModelAndView(viewName, "userInfo", userInfo);
return viewName;
} }
} }