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 java.util.HashMap;
022import java.util.Map;
023
024import com.nimbusds.oauth2.sdk.AccessTokenResponse;
025import com.nimbusds.oauth2.sdk.ParseException;
026import com.nimbusds.oauth2.sdk.http.HTTPResponse;
027import com.nimbusds.openid.connect.sdk.token.OIDCTokens;
028import net.jcip.annotations.Immutable;
029import net.minidev.json.JSONObject;
030
031
032/**
033 * OpenID Connect token response from the Token endpoint.
034 *
035 * <p>Example HTTP response:
036 *
037 * <pre>
038 * HTTP/1.1 200 OK
039 * Content-Type: application/json
040 * Cache-Control: no-store
041 * Pragma: no-cache
042 * 
043 * {
044 *   "access_token"  : "SlAV32hkKG",
045 *   "token_type"    : "Bearer",
046 *   "refresh_token" : "8xLOxBtZp8",
047 *   "expires_in"    : 3600,
048 *   "id_token"      : "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9zZXJ2Z
049 *    XIuZXhhbXBsZS5jb20iLCJ1c2VyX2lkIjoiMjQ4Mjg5NzYxMDAxIiwiYXVkIjoic
050 *    zZCaGRSa3F0MyIsIm5vbmNlIjoibi0wUzZfV3pBMk1qIiwiZXhwIjoxMzExMjgxO
051 *    TcwLCJpYXQiOjEzMTEyODA5NzB9.RgXxzppVvn1EjUiV3LIZ19SyhdyREe_2jJjW
052 *    5EC8XjNuJfe7Dte8YxRXxssJ67N8MT9mvOI3HOHm4whNx5FCyemyCGyTLHODCeAr
053 *    _id029-4JP0KWySoan1jmT7vbGHhu89-l9MTdaEvu7pNZO7DHGwqnMWRe8hdG7jU
054 *    ES4w4ReQTygKwXVVOaiGoeUrv6cZdbyOnpGlRlHaiOsv_xMunNVJtn5dLz-0zZwV
055 *    ftKVpFuc1pGaVsyZsOtkT32E4c6MDHeCvIDlR5ESC0ct8BLvGJDB5954MjCR4_X2
056 *    GAEHonKw4NF8wTmUFvhslYXmjRNFs21Byjn3jNb7lSa3MBfVsw"
057 * }
058 * </pre>
059 *
060 * <p>Related specifications:
061 *
062 * <ul>
063 *     <li>OpenID Connect Core 1.0, section 3.1.3.3.
064 *     <li>OAuth 2.0 (RFC 6749), sections 4.1.4 and 5.1.
065 * </ul>
066 */
067@Immutable
068public class OIDCTokenResponse extends AccessTokenResponse {
069
070
071        /**
072         * The OpenID Connect tokens.
073         */
074        private final OIDCTokens tokens;
075
076
077        /**
078         * Creates a new OpenID Connect access token response.
079         *
080         * @param tokens The OpenID Connect tokens. Must not be {@code null}.
081         */
082        public OIDCTokenResponse(final OIDCTokens tokens) {
083                                   
084                this(tokens, null);
085        }
086
087
088        /**
089         * Creates a new OpenID Connect access token response.
090         *
091         * @param tokens       The OpenID Connect tokens. Must not be
092         *                     {@code null}.
093         * @param customParams Optional custom parameters, {@code null} if
094         *                     none.
095         */
096        public OIDCTokenResponse(final OIDCTokens tokens,
097                                 final Map<String, Object> customParams) {
098
099                super(tokens, customParams);
100
101                this.tokens = tokens;
102        }
103
104
105        /**
106         * Gets the OpenID Connect tokens.
107         *
108         * @return The OpenID Connect tokens.
109         */
110        public OIDCTokens getOIDCTokens() {
111
112                return tokens;
113        }
114        
115        
116        /**
117         * Returns a JSON object representation of this OpenID Connect token
118         * response.
119         *
120         * <p>Example JSON object:
121         *
122         * <pre>
123         * {
124         *   "access_token" : "SlAV32hkKG",
125         *   "token_type"   : "Bearer",
126         *   "refresh_token": "8xLOxBtZp8",
127         *   "expires_in"   : 3600,
128         *   "id_token"     : "eyJ0 ... NiJ9.eyJ1c ... I6IjIifX0.DeWt4Qu ... ZXso"
129         * }
130         * </pre>
131         *
132         * @return The JSON object.
133         */
134        @Override
135        public JSONObject toJSONObject() {
136        
137                JSONObject o = super.toJSONObject();
138                o.putAll(getOIDCTokens().toJSONObject());
139                return o;
140        }
141        
142        
143        @Override
144        public OIDCTokenResponse toSuccessResponse() {
145                return this;
146        }
147        
148        
149        /**
150         * Parses an OpenID Connect token response from the specified JSON
151         * object.
152         *
153         * @param jsonObject The JSON object to parse. Must not be 
154         *                   {@code null}.
155         *
156         * @return The OpenID Connect token response.
157         *
158         * @throws ParseException If the JSON object couldn't be parsed to an
159         *                        OpenID Connect token response.
160         */
161        public static OIDCTokenResponse parse(final JSONObject jsonObject)
162                throws ParseException {
163
164                OIDCTokens tokens = OIDCTokens.parse(jsonObject);
165
166                // Parse the custom parameters
167                Map<String,Object> customParams = new HashMap<>();
168                customParams.putAll(jsonObject);
169                for (String tokenParam: tokens.getParameterNames()) {
170                        customParams.remove(tokenParam);
171                }
172
173                if (customParams.isEmpty()) {
174                        return new OIDCTokenResponse(tokens);
175                }
176                
177                return new OIDCTokenResponse(tokens, customParams);
178        }
179        
180        
181        /**
182         * Parses an OpenID Connect access token response from the specified 
183         * HTTP response.
184         *
185         * @param httpResponse The HTTP response. Must not be {@code null}.
186         *
187         * @return The OpenID Connect access token response.
188         *
189         * @throws ParseException If the HTTP response couldn't be parsed to an 
190         *                        OpenID Connect access token response.
191         */
192        public static OIDCTokenResponse parse(final HTTPResponse httpResponse)
193                throws ParseException {
194                
195                httpResponse.ensureStatusCode(HTTPResponse.SC_OK);
196                JSONObject jsonObject = httpResponse.getContentAsJSONObject();
197                return parse(jsonObject);
198        }
199}