added webfinger discovery to server, addresses #279
							parent
							
								
									9c6b08d919
								
							
						
					
					
						commit
						895690df54
					
				|  | @ -0,0 +1,97 @@ | |||
| /** | ||||
|  *  | ||||
|  */ | ||||
| package org.mitre.discovery.view; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| import java.io.Writer; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| 
 | ||||
| import org.mitre.openid.connect.view.JsonEntityView; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.springframework.stereotype.Component; | ||||
| import org.springframework.validation.BeanPropertyBindingResult; | ||||
| import org.springframework.web.servlet.view.AbstractView; | ||||
| 
 | ||||
| import com.google.gson.ExclusionStrategy; | ||||
| import com.google.gson.FieldAttributes; | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.GsonBuilder; | ||||
| import com.google.gson.JsonArray; | ||||
| import com.google.gson.JsonObject; | ||||
| 
 | ||||
| /** | ||||
|  * @author jricher | ||||
|  * | ||||
|  */ | ||||
| @Component("webfingerView") | ||||
| public class WebfingerView extends AbstractView { | ||||
| 
 | ||||
| 	private static Logger logger = LoggerFactory.getLogger(WebfingerView.class); | ||||
| 
 | ||||
| 	private Gson gson = new GsonBuilder() | ||||
| 	    .setExclusionStrategies(new ExclusionStrategy() { | ||||
| 	 | ||||
| 	        public boolean shouldSkipField(FieldAttributes f) { | ||||
| 	 | ||||
| 	            return false; | ||||
| 	        } | ||||
| 	 | ||||
| 	        public boolean shouldSkipClass(Class<?> clazz) { | ||||
| 	            // skip the JPA binding wrapper
 | ||||
| 	            if (clazz.equals(BeanPropertyBindingResult.class)) { | ||||
| 	                return true; | ||||
| 	            } | ||||
| 	            return false; | ||||
| 	        } | ||||
| 	 | ||||
| 	    }) | ||||
| 	    .serializeNulls() | ||||
| 	    .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") | ||||
| 	    .create(); | ||||
| 
 | ||||
| 	protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) { | ||||
| 
 | ||||
| 		response.setContentType("application/jrd+json"); | ||||
| 
 | ||||
|          | ||||
| 		HttpStatus code = (HttpStatus) model.get("code"); | ||||
| 		if (code == null) { | ||||
| 			code = HttpStatus.OK; // default to 200
 | ||||
| 		} | ||||
| 		 | ||||
| 		response.setStatus(code.value()); | ||||
| 		 | ||||
| 		try { | ||||
| 			 | ||||
| 			String resource = (String)model.get("resource"); | ||||
| 			String issuer = (String)model.get("issuer"); | ||||
| 			 | ||||
| 			JsonObject obj = new JsonObject(); | ||||
| 			obj.addProperty("subject", resource); | ||||
| 			 | ||||
| 			JsonArray links = new JsonArray(); | ||||
| 			JsonObject link = new JsonObject(); | ||||
| 			link.addProperty("rel", "http://openid.net/specs/connect/1.0/issuer"); | ||||
| 			link.addProperty("href", issuer); | ||||
| 			links.add(link); | ||||
| 			 | ||||
| 			obj.add("links", links); | ||||
| 			 | ||||
| 			Writer out = response.getWriter(); | ||||
| 	        gson.toJson(obj, out); | ||||
| 	         | ||||
| 		} catch (IOException e) { | ||||
| 			 | ||||
| 			//TODO: Error Handling
 | ||||
| 			logger.error("IOException in JsonEntityView.java: ", e); | ||||
| 			 | ||||
| 		} | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -15,21 +15,29 @@ | |||
|  ******************************************************************************/ | ||||
| package org.mitre.discovery.web; | ||||
| 
 | ||||
| import java.net.URI; | ||||
| import java.net.URISyntaxException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.mitre.jwt.signer.service.JwtSigningAndValidationService; | ||||
| import org.mitre.oauth2.service.SystemScopeService; | ||||
| import org.mitre.openid.connect.config.ConfigurationPropertiesBean; | ||||
| import org.mitre.openid.connect.model.UserInfo; | ||||
| import org.mitre.openid.connect.service.UserInfoService; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.http.HttpStatus; | ||||
| import org.springframework.stereotype.Controller; | ||||
| import org.springframework.ui.Model; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RequestParam; | ||||
| 
 | ||||
| import com.google.common.base.Splitter; | ||||
| import com.google.common.collect.Lists; | ||||
| import com.google.gson.JsonObject; | ||||
| 
 | ||||
| /** | ||||
|  *  | ||||
|  | @ -52,20 +60,56 @@ public class DiscoveryEndpoint { | |||
| 	@Autowired | ||||
| 	private JwtSigningAndValidationService jwtService; | ||||
| 	 | ||||
| 	//TODO: rewrite, see issue #279, Webfinger
 | ||||
| //	@RequestMapping(value={"/.well-known/host-meta", "/.well-known/host-meta.json"},
 | ||||
| //			params={"resource", "rel=http://openid.net/specs/connect/1.0/issuer"}, produces = "application/json")
 | ||||
| //	public ModelAndView xrdDiscovery(@RequestParam("resource") String resource, ModelAndView modelAndView) {
 | ||||
| //		
 | ||||
| //		Map<String, String> relMap = new HashMap<String, String>();
 | ||||
| //		relMap.put("http://openid.net/specs/connect/1.0/issuer", config.getIssuer());
 | ||||
| //		
 | ||||
| //		modelAndView.getModel().put("links", relMap);
 | ||||
| //		
 | ||||
| //		modelAndView.setViewName("jsonXrdResponseView");
 | ||||
| //		
 | ||||
| //		return modelAndView;
 | ||||
| //	}
 | ||||
| 	@Autowired | ||||
| 	private UserInfoService userService; | ||||
| 	 | ||||
| 	@RequestMapping(value={"/.well-known/webfinger"}, | ||||
| 			params={"resource", "rel=http://openid.net/specs/connect/1.0/issuer"}, produces = "application/json") | ||||
| 	public String webfinger(@RequestParam("resource") String resource, Model model) { | ||||
| 
 | ||||
| 		if (!resource.equals(config.getIssuer())) { | ||||
| 			// it's not the issuer directly, need to check other methods
 | ||||
| 
 | ||||
| 			try { | ||||
| 				URI resourceUri = new URI(resource); | ||||
| 				if (resourceUri != null | ||||
| 						&& resourceUri.getScheme() != null  | ||||
| 						&& resourceUri.getScheme().equals("acct")) { | ||||
| 					// acct: URI
 | ||||
| 					 | ||||
| 					// split out the user and host parts
 | ||||
| 					List<String> parts = Lists.newArrayList(Splitter.on("@").split(resourceUri.getSchemeSpecificPart())); | ||||
| 
 | ||||
| 					UserInfo user = null; | ||||
| 					if (parts.size() > 0) { | ||||
| 						user = userService.getByUsername(parts.get(0)); // first part is the username
 | ||||
| 					} | ||||
| 					 | ||||
| 					if (user == null) { | ||||
| 						logger.info("User not found: " + resource); | ||||
| 						model.addAttribute("code", HttpStatus.NOT_FOUND); | ||||
| 						return "httpCodeView"; | ||||
| 					} | ||||
| 					// TODO: check the "host" part against our issuer 
 | ||||
| 					 | ||||
| 				} else { | ||||
| 					logger.info("Unknown URI format: " + resource); | ||||
| 					model.addAttribute("code", HttpStatus.NOT_FOUND); | ||||
| 					return "httpCodeView"; | ||||
| 				} | ||||
| 			} catch (URISyntaxException e) { | ||||
| 				logger.info("URI parsing exception: " + resource, e); | ||||
| 				model.addAttribute("code", HttpStatus.NOT_FOUND); | ||||
| 				return "httpCodeView"; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		// if we got here, then we're good
 | ||||
| 		model.addAttribute("resource", resource); | ||||
| 		model.addAttribute("issuer", config.getIssuer()); | ||||
| 		 | ||||
| 		return "webfingerView"; | ||||
| 	} | ||||
| 
 | ||||
| 	@RequestMapping("/.well-known/openid-configuration") | ||||
| 	public String providerConfiguration(Model model) { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Justin Richer
						Justin Richer