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