PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/openid-connect-server/src/main/java/org/mitre/openid/connect/web/UserInfoEndpoint.java

https://gitlab.com/jslee1/OpenID-Connect-Java-Spring-Server
Java | 142 lines | 84 code | 24 blank | 34 comment | 24 complexity | 34c5204b83a23e87bb0788dc05c7db37 MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright 2016 The MITRE Corporation
  3. * and the MIT Internet Trust Consortium
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *******************************************************************************/
  17. package org.mitre.openid.connect.web;
  18. import java.util.List;
  19. import org.mitre.oauth2.model.ClientDetailsEntity;
  20. import org.mitre.oauth2.service.ClientDetailsEntityService;
  21. import org.mitre.oauth2.service.SystemScopeService;
  22. import org.mitre.openid.connect.model.UserInfo;
  23. import org.mitre.openid.connect.service.UserInfoService;
  24. import org.mitre.openid.connect.view.HttpCodeView;
  25. import org.mitre.openid.connect.view.UserInfoJWTView;
  26. import org.mitre.openid.connect.view.UserInfoView;
  27. import org.slf4j.Logger;
  28. import org.slf4j.LoggerFactory;
  29. import org.springframework.beans.factory.annotation.Autowired;
  30. import org.springframework.http.HttpHeaders;
  31. import org.springframework.http.HttpStatus;
  32. import org.springframework.http.MediaType;
  33. import org.springframework.security.access.prepost.PreAuthorize;
  34. import org.springframework.security.oauth2.provider.OAuth2Authentication;
  35. import org.springframework.stereotype.Controller;
  36. import org.springframework.ui.Model;
  37. import org.springframework.web.bind.annotation.RequestHeader;
  38. import org.springframework.web.bind.annotation.RequestMapping;
  39. import org.springframework.web.bind.annotation.RequestMethod;
  40. import org.springframework.web.bind.annotation.RequestParam;
  41. import com.google.common.base.Strings;
  42. /**
  43. * OpenID Connect UserInfo endpoint, as specified in Standard sec 5 and Messages sec 2.4.
  44. *
  45. * @author AANGANES
  46. *
  47. */
  48. @Controller
  49. @RequestMapping("/" + UserInfoEndpoint.URL)
  50. public class UserInfoEndpoint {
  51. public static final String URL = "userinfo";
  52. @Autowired
  53. private UserInfoService userInfoService;
  54. @Autowired
  55. private ClientDetailsEntityService clientService;
  56. /**
  57. * Logger for this class
  58. */
  59. private static final Logger logger = LoggerFactory.getLogger(UserInfoEndpoint.class);
  60. /**
  61. * Get information about the user as specified in the accessToken included in this request
  62. */
  63. @PreAuthorize("hasRole('ROLE_USER') and #oauth2.hasScope('" + SystemScopeService.OPENID_SCOPE + "')")
  64. @RequestMapping(method= {RequestMethod.GET, RequestMethod.POST}, produces = {MediaType.APPLICATION_JSON_VALUE, UserInfoJWTView.JOSE_MEDIA_TYPE_VALUE})
  65. public String getInfo(@RequestParam(value="claims", required=false) String claimsRequestJsonString,
  66. @RequestHeader(value=HttpHeaders.ACCEPT, required=false) String acceptHeader,
  67. OAuth2Authentication auth, Model model) {
  68. if (auth == null) {
  69. logger.error("getInfo failed; no principal. Requester is not authorized.");
  70. model.addAttribute(HttpCodeView.CODE, HttpStatus.FORBIDDEN);
  71. return HttpCodeView.VIEWNAME;
  72. }
  73. String username = auth.getName();
  74. UserInfo userInfo = userInfoService.getByUsernameAndClientId(username, auth.getOAuth2Request().getClientId());
  75. if (userInfo == null) {
  76. logger.error("getInfo failed; user not found: " + username);
  77. model.addAttribute(HttpCodeView.CODE, HttpStatus.NOT_FOUND);
  78. return HttpCodeView.VIEWNAME;
  79. }
  80. model.addAttribute(UserInfoView.SCOPE, auth.getOAuth2Request().getScope());
  81. model.addAttribute(UserInfoView.AUTHORIZED_CLAIMS, auth.getOAuth2Request().getExtensions().get("claims"));
  82. if (!Strings.isNullOrEmpty(claimsRequestJsonString)) {
  83. model.addAttribute(UserInfoView.REQUESTED_CLAIMS, claimsRequestJsonString);
  84. }
  85. model.addAttribute(UserInfoView.USER_INFO, userInfo);
  86. // content negotiation
  87. // start off by seeing if the client has registered for a signed/encrypted JWT from here
  88. ClientDetailsEntity client = clientService.loadClientByClientId(auth.getOAuth2Request().getClientId());
  89. model.addAttribute(UserInfoJWTView.CLIENT, client);
  90. List<MediaType> mediaTypes = MediaType.parseMediaTypes(acceptHeader);
  91. MediaType.sortBySpecificityAndQuality(mediaTypes);
  92. if (client.getUserInfoSignedResponseAlg() != null
  93. || client.getUserInfoEncryptedResponseAlg() != null
  94. || client.getUserInfoEncryptedResponseEnc() != null) {
  95. // client has a preference, see if they ask for plain JSON specifically on this request
  96. for (MediaType m : mediaTypes) {
  97. if (!m.isWildcardType() && m.isCompatibleWith(UserInfoJWTView.JOSE_MEDIA_TYPE)) {
  98. return UserInfoJWTView.VIEWNAME;
  99. } else if (!m.isWildcardType() && m.isCompatibleWith(MediaType.APPLICATION_JSON)) {
  100. return UserInfoView.VIEWNAME;
  101. }
  102. }
  103. // otherwise return JWT
  104. return UserInfoJWTView.VIEWNAME;
  105. } else {
  106. // client has no preference, see if they asked for JWT specifically on this request
  107. for (MediaType m : mediaTypes) {
  108. if (!m.isWildcardType() && m.isCompatibleWith(MediaType.APPLICATION_JSON)) {
  109. return UserInfoView.VIEWNAME;
  110. } else if (!m.isWildcardType() && m.isCompatibleWith(UserInfoJWTView.JOSE_MEDIA_TYPE)) {
  111. return UserInfoJWTView.VIEWNAME;
  112. }
  113. }
  114. // otherwise return JSON
  115. return UserInfoView.VIEWNAME;
  116. }
  117. }
  118. }