001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2016, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.openid.connect.sdk; 019 020 021import com.nimbusds.common.contenttype.ContentType; 022import com.nimbusds.jwt.JWT; 023import com.nimbusds.oauth2.sdk.ParseException; 024import com.nimbusds.oauth2.sdk.SerializeException; 025import com.nimbusds.oauth2.sdk.SuccessResponse; 026import com.nimbusds.oauth2.sdk.http.HTTPResponse; 027import com.nimbusds.openid.connect.sdk.claims.UserInfo; 028import net.jcip.annotations.Immutable; 029 030import java.util.Objects; 031 032 033/** 034 * UserInfo success response. 035 * 036 * <p>The UserInfo claims may be passed as an unprotected JSON object or as a 037 * plain, signed or encrypted JSON Web Token (JWT). Use the appropriate 038 * constructor for that. 039 * 040 * <p>Example UserInfo HTTP response: 041 * 042 * <pre> 043 * HTTP/1.1 200 OK 044 * Content-Type: application/json 045 * 046 * { 047 * "sub" : "248289761001", 048 * "name" : "Jane Doe" 049 * "given_name" : "Jane", 050 * "family_name" : "Doe", 051 * "email" : "[email protected]", 052 * "picture" : "http://example.com/janedoe/me.jpg" 053 * } 054 * </pre> 055 * 056 * <p>Related specifications: 057 * 058 * <ul> 059 * <li>OpenID Connect Core 1.0 060 * </ul> 061 */ 062@Immutable 063public class UserInfoSuccessResponse 064 extends UserInfoResponse 065 implements SuccessResponse { 066 067 068 /** 069 * The UserInfo claims set, serialisable to a JSON object. 070 */ 071 private final UserInfo claimsSet; 072 073 074 /** 075 * The UserInfo claims set, as plain, signed or encrypted JWT. 076 */ 077 private final JWT jwt; 078 079 080 /** 081 * Creates a new UserInfo success response where the claims are 082 * specified as an unprotected UserInfo claims set. 083 * 084 * @param claimsSet The UserInfo claims set. Must not be {@code null}. 085 */ 086 public UserInfoSuccessResponse(final UserInfo claimsSet) { 087 this.claimsSet = Objects.requireNonNull(claimsSet); 088 this.jwt = null; 089 } 090 091 092 /** 093 * Creates a new UserInfo success response where the claims are 094 * specified as a plain, signed or encrypted JSON Web Token (JWT). 095 * 096 * @param jwt The UserInfo claims set. Must not be {@code null}. 097 */ 098 public UserInfoSuccessResponse(final JWT jwt) { 099 this.jwt = Objects.requireNonNull(jwt); 100 this.claimsSet = null; 101 } 102 103 104 @Override 105 public boolean indicatesSuccess() { 106 return true; 107 } 108 109 110 /** 111 * Gets the content type of this UserInfo response. 112 * 113 * @return The content type, according to the claims format. 114 */ 115 public ContentType getEntityContentType() { 116 117 if (claimsSet != null) 118 return ContentType.APPLICATION_JSON; 119 else 120 return ContentType.APPLICATION_JWT; 121 } 122 123 124 /** 125 * Gets the UserInfo claims set as an unprotected UserInfo claims set. 126 * 127 * @return The UserInfo claims set, {@code null} if it was specified as 128 * JSON Web Token (JWT) instead. 129 */ 130 public UserInfo getUserInfo() { 131 132 return claimsSet; 133 } 134 135 136 /** 137 * Gets the UserInfo claims set as a plain, signed or encrypted JSON 138 * Web Token (JWT). 139 * 140 * @return The UserInfo claims set as a JSON Web Token (JWT), 141 * {@code null} if it was specified as an unprotected UserInfo 142 * claims set instead. 143 */ 144 public JWT getUserInfoJWT() { 145 146 return jwt; 147 } 148 149 150 @Override 151 public HTTPResponse toHTTPResponse() { 152 153 HTTPResponse httpResponse = new HTTPResponse(HTTPResponse.SC_OK); 154 155 httpResponse.setEntityContentType(getEntityContentType()); 156 157 String content; 158 159 if (claimsSet != null) { 160 161 content = claimsSet.toJSONObject().toString(); 162 163 } else { 164 165 try { 166 content = jwt.serialize(); 167 168 } catch (IllegalStateException e) { 169 170 throw new SerializeException("Couldn't serialize UserInfo claims JWT: " + 171 e.getMessage(), e); 172 } 173 } 174 175 httpResponse.setBody(content); 176 177 return httpResponse; 178 } 179 180 181 /** 182 * Parses a UserInfo response from the specified HTTP response. 183 * 184 * <p>Example HTTP response: 185 * 186 * <pre> 187 * HTTP/1.1 200 OK 188 * Content-Type: application/json 189 * 190 * { 191 * "sub" : "248289761001", 192 * "name" : "Jane Doe" 193 * "given_name" : "Jane", 194 * "family_name" : "Doe", 195 * "email" : "[email protected]", 196 * "picture" : "http://example.com/janedoe/me.jpg" 197 * } 198 * </pre> 199 * 200 * @param httpResponse The HTTP response. Must not be {@code null}. 201 * 202 * @return The UserInfo response. 203 * 204 * @throws ParseException If the HTTP response couldn't be parsed to a 205 * UserInfo response. 206 */ 207 public static UserInfoSuccessResponse parse(final HTTPResponse httpResponse) 208 throws ParseException { 209 210 httpResponse.ensureStatusCode(HTTPResponse.SC_OK); 211 212 httpResponse.ensureEntityContentType(); 213 214 ContentType ct = httpResponse.getEntityContentType(); 215 216 UserInfoSuccessResponse response; 217 218 if (ct.matches(ContentType.APPLICATION_JSON)) { 219 220 UserInfo claimsSet; 221 222 try { 223 claimsSet = new UserInfo(httpResponse.getBodyAsJSONObject()); 224 225 } catch (Exception e) { 226 227 throw new ParseException("Couldn't parse UserInfo claims: " + 228 e.getMessage(), e); 229 } 230 231 response = new UserInfoSuccessResponse(claimsSet); 232 233 } else if (ct.matches(ContentType.APPLICATION_JWT)) { 234 235 JWT jwt; 236 237 try { 238 jwt = httpResponse.getBodyAsJWT(); 239 240 } catch (ParseException e) { 241 242 throw new ParseException("Couldn't parse UserInfo claims JWT: " + 243 e.getMessage(), e); 244 } 245 246 response = new UserInfoSuccessResponse(jwt); 247 248 } else { 249 throw new ParseException("Unexpected Content-Type, must be " + 250 ContentType.APPLICATION_JSON + 251 " or " + 252 ContentType.APPLICATION_JWT); 253 } 254 255 return response; 256 } 257}