001 package com.nimbusds.openid.connect.sdk; 002 003 004 import java.net.URL; 005 import java.util.Map; 006 007 import net.jcip.annotations.Immutable; 008 009 import com.nimbusds.oauth2.sdk.ParseException; 010 import com.nimbusds.oauth2.sdk.Request; 011 import com.nimbusds.oauth2.sdk.SerializeException; 012 import com.nimbusds.oauth2.sdk.http.CommonContentTypes; 013 import com.nimbusds.oauth2.sdk.http.HTTPRequest; 014 import com.nimbusds.oauth2.sdk.token.AccessToken; 015 016 017 /** 018 * UserInfo request. Used to retrieve requested claims about the end-user. This 019 * class is immutable. 020 * 021 * <p>Example HTTP GET request: 022 * 023 * <pre> 024 * GET /userinfo?schema=openid HTTP/1.1 025 * Host: server.example.com 026 * Authorization: Bearer mF_9.B5f-4.1JqM 027 * </pre> 028 * 029 * <p>Example HTTP POST request: 030 * 031 * <pre> 032 * POST /userinfo HTTP/1.1 033 * Host: server.example.com 034 * Content-Type: application/x-www-form-urlencoded 035 * 036 * schema=openid&access_token=mF_9.B5f-4.1JqM 037 * </pre> 038 * 039 * <p>Related specifications: 040 * 041 * <ul> 042 * <li>OpenID Connect Messages 1.0, section 2.3.1. 043 * <li>OpenID Connect Standard 1.0, section 4.1. 044 * <li>OAuth 2.0 Bearer Token Usage (RFC6750), section 2. 045 * </ul> 046 * 047 * @author Vladimir Dzhuvinov 048 * @version $version$ (2013-05-10) 049 */ 050 @Immutable 051 public final class UserInfoRequest implements Request { 052 053 054 /** 055 * The HTTP method. 056 */ 057 private final HTTPRequest.Method httpMethod; 058 059 060 /** 061 * The UserInfo access token. 062 */ 063 private final AccessToken accessToken; 064 065 066 /** 067 * Creates a new UserInfo HTTP GET request. 068 * 069 * @param accessToken The UserInfo access token. Must not be 070 * {@code null}. 071 */ 072 public UserInfoRequest(final AccessToken accessToken) { 073 074 this(HTTPRequest.Method.GET, accessToken); 075 } 076 077 078 /** 079 * Creates a new UserInfo request. 080 * 081 * @param httpMethod The HTTP method. Must be HTTP GET or POST and not 082 * {@code null}. 083 * @param accessToken The UserInfo access token. Must not be 084 * {@code null}. 085 */ 086 public UserInfoRequest(final HTTPRequest.Method httpMethod, final AccessToken accessToken) { 087 088 if (httpMethod == null) 089 throw new IllegalArgumentException("The HTTP method must not be null"); 090 091 this.httpMethod = httpMethod; 092 093 094 if (accessToken == null) 095 throw new IllegalArgumentException("The access token must not be null"); 096 097 this.accessToken = accessToken; 098 } 099 100 101 /** 102 * Gets the HTTP method for this UserInfo request. 103 * 104 * @return The HTTP method. 105 */ 106 public HTTPRequest.Method getMethod() { 107 108 return httpMethod; 109 } 110 111 112 /** 113 * Gets the UserInfo access token. 114 * 115 * @return The UserInfo access token. 116 */ 117 public AccessToken getAccessToken() { 118 119 return accessToken; 120 } 121 122 123 @Override 124 public HTTPRequest toHTTPRequest(final URL url) 125 throws SerializeException { 126 127 HTTPRequest httpRequest = new HTTPRequest(httpMethod, url); 128 129 switch (httpMethod) { 130 131 case GET: 132 httpRequest.setAuthorization(accessToken.toAuthorizationHeader()); 133 httpRequest.setQuery("schema=openid"); 134 break; 135 136 case POST: 137 httpRequest.setContentType(CommonContentTypes.APPLICATION_URLENCODED); 138 httpRequest.setQuery("schema=openid" + 139 "&access_token=" + accessToken.getValue()); 140 break; 141 142 default: 143 throw new SerializeException("Unexpected HTTP method: " + httpMethod); 144 } 145 146 return httpRequest; 147 } 148 149 150 /** 151 * Parses the specified HTTP request for a UserInfo request. 152 * 153 * @param httpRequest The HTTP request. Must not be {@code null}. 154 * 155 * @return The UserInfo request. 156 * 157 * @throws ParseException If the HTTP request couldn't be parsed to a 158 * UserInfo request. 159 */ 160 public static UserInfoRequest parse(final HTTPRequest httpRequest) 161 throws ParseException { 162 163 HTTPRequest.Method httpMethod = httpRequest.getMethod(); 164 165 AccessToken accessToken = null; 166 167 switch (httpMethod) { 168 169 case GET: 170 171 String authzHeader = httpRequest.getAuthorization(); 172 173 if (authzHeader == null) 174 throw new ParseException("Missing HTTP Authorization header"); 175 176 accessToken = AccessToken.parse(authzHeader); 177 178 String query = httpRequest.getQuery(); 179 180 if (query == null) 181 throw new ParseException("Missing query string"); 182 183 if (query.indexOf("schema=openid") < 0) 184 throw new ParseException("Missing or unexpected schema parameter, must be \"openid\""); 185 186 break; 187 188 189 case POST: 190 191 httpRequest.ensureContentType(CommonContentTypes.APPLICATION_URLENCODED); 192 193 Map<String,String> params = httpRequest.getQueryParameters(); 194 195 if (! params.containsKey("schema")) 196 throw new ParseException("Missing schema parameter"); 197 198 if ("openid".equals(params.get("schema"))) 199 throw new ParseException("Unexpected schema parameter, must be \"openid\""); 200 201 if (! params.containsKey("access_token")) 202 throw new ParseException("Missing access_token parameter"); 203 204 accessToken = AccessToken.parse(params.get("access_token")); 205 206 break; 207 208 default: 209 throw new ParseException("Unexpected HTTP method: " + httpMethod); 210 } 211 212 return new UserInfoRequest(httpMethod, accessToken); 213 } 214 }