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.oauth2.sdk; 019 020 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.Map; 024import java.util.Set; 025 026import net.jcip.annotations.Immutable; 027 028import net.minidev.json.JSONObject; 029 030import com.nimbusds.oauth2.sdk.token.Tokens; 031import com.nimbusds.oauth2.sdk.http.CommonContentTypes; 032import com.nimbusds.oauth2.sdk.http.HTTPResponse; 033 034 035/** 036 * Access token response from the Token endpoint. 037 * 038 * <p>Example HTTP response: 039 * 040 * <pre> 041 * HTTP/1.1 200 OK 042 * Content-Type: application/json;charset=UTF-8 043 * Cache-Control: no-store 044 * Pragma: no-cache 045 * 046 * { 047 * "access_token" : "2YotnFZFEjr1zCsicMWpAA", 048 * "token_type" : "example", 049 * "expires_in" : 3600, 050 * "refresh_token" : "tGzv3JOkF0XG5Qx2TlKWIA", 051 * "example_parameter" : "example_value" 052 * } 053 * </pre> 054 * 055 * <p>Related specifications: 056 * 057 * <ul> 058 * <li>OAuth 2.0 (RFC 6749), sections 4.1.4, 4.3.3, 4.4.3 and 5.1. 059 * </ul> 060 */ 061@Immutable 062public class AccessTokenResponse extends TokenResponse implements SuccessResponse { 063 064 065 /** 066 * The tokens. 067 */ 068 private final Tokens tokens; 069 070 071 /** 072 * Optional custom parameters. 073 */ 074 private final Map<String,Object> customParams; 075 076 077 /** 078 * Creates a new access token response. 079 * 080 * @param tokens The tokens. Must not be {@code null}. 081 */ 082 public AccessTokenResponse(final Tokens tokens) { 083 084 this(tokens, null); 085 } 086 087 088 /** 089 * Creates a new access token response. 090 * 091 * @param tokens The tokens. Must not be {@code null}. 092 * @param customParams Optional custom parameters, {@code null} if 093 * none. 094 */ 095 public AccessTokenResponse(final Tokens tokens, 096 final Map<String,Object> customParams) { 097 098 if (tokens == null) 099 throw new IllegalArgumentException("The tokens must not be null"); 100 101 this.tokens = tokens; 102 103 this.customParams = customParams; 104 } 105 106 107 @Override 108 public boolean indicatesSuccess() { 109 110 return true; 111 } 112 113 114 /** 115 * Returns the tokens. 116 * 117 * @return The tokens. 118 */ 119 public Tokens getTokens() { 120 121 return tokens; 122 } 123 124 125 /** 126 * Returns the custom parameters. 127 * 128 * @return The custom parameters, as a unmodifiable map, empty map if 129 * none. 130 */ 131 public Map<String,Object> getCustomParameters() { 132 133 if (customParams == null) 134 return Collections.emptyMap(); 135 136 return Collections.unmodifiableMap(customParams); 137 } 138 139 140 @Deprecated 141 public Map<String,Object> getCustomParams() { 142 143 return getCustomParameters(); 144 } 145 146 147 /** 148 * Returns a JSON object representation of this access token response. 149 * 150 * <p>Example JSON object: 151 * 152 * <pre> 153 * { 154 * "access_token" : "SlAV32hkKG", 155 * "token_type" : "Bearer", 156 * "refresh_token" : "8xLOxBtZp8", 157 * "expires_in" : 3600 158 * } 159 * </pre> 160 * 161 * @return The JSON object. 162 */ 163 public JSONObject toJSONObject() { 164 165 JSONObject o = tokens.toJSONObject(); 166 167 if (customParams != null) 168 o.putAll(customParams); 169 170 return o; 171 } 172 173 174 @Override 175 public HTTPResponse toHTTPResponse() { 176 177 HTTPResponse httpResponse = new HTTPResponse(HTTPResponse.SC_OK); 178 179 httpResponse.setContentType(CommonContentTypes.APPLICATION_JSON); 180 httpResponse.setCacheControl("no-store"); 181 httpResponse.setPragma("no-cache"); 182 183 httpResponse.setContent(toJSONObject().toString()); 184 185 return httpResponse; 186 } 187 188 189 /** 190 * Parses an access token response from the specified JSON object. 191 * 192 * @param jsonObject The JSON object to parse. Must not be {@code null}. 193 * 194 * @return The access token response. 195 * 196 * @throws ParseException If the JSON object couldn't be parsed to an 197 * access token response. 198 */ 199 public static AccessTokenResponse parse(final JSONObject jsonObject) 200 throws ParseException { 201 202 Tokens tokens = Tokens.parse(jsonObject); 203 204 // Determine the custom param names 205 Set<String> paramNames = tokens.getParameterNames(); 206 Set<String> customParamNames = jsonObject.keySet(); 207 customParamNames.removeAll(paramNames); 208 209 Map<String,Object> customParams = null; 210 211 if (! customParamNames.isEmpty()) { 212 213 customParams = new HashMap<>(); 214 215 for (String name: customParamNames) { 216 customParams.put(name, jsonObject.get(name)); 217 } 218 } 219 220 return new AccessTokenResponse(tokens, customParams); 221 } 222 223 224 /** 225 * Parses an access token response from the specified HTTP response. 226 * 227 * @param httpResponse The HTTP response. Must not be {@code null}. 228 * 229 * @return The access token response. 230 * 231 * @throws ParseException If the HTTP response couldn't be parsed to an 232 * access token response. 233 */ 234 public static AccessTokenResponse parse(final HTTPResponse httpResponse) 235 throws ParseException { 236 237 httpResponse.ensureStatusCode(HTTPResponse.SC_OK); 238 JSONObject jsonObject = httpResponse.getContentAsJSONObject(); 239 return parse(jsonObject); 240 } 241}