001package com.nimbusds.oauth2.sdk;
002
003
004import net.jcip.annotations.Immutable;
005
006import net.minidev.json.JSONObject;
007
008import com.nimbusds.oauth2.sdk.token.AccessToken;
009import com.nimbusds.oauth2.sdk.token.RefreshToken;
010import com.nimbusds.oauth2.sdk.token.TokenPair;
011import com.nimbusds.oauth2.sdk.http.CommonContentTypes;
012import com.nimbusds.oauth2.sdk.http.HTTPResponse;
013
014
015/**
016 * Access token response from the Token endpoint. This class is immutable.
017 *
018 * <p>Example HTTP response:
019 *
020 * <pre>
021 * HTTP/1.1 200 OK
022 * Content-Type: application/json;charset=UTF-8
023 * Cache-Control: no-store
024 * Pragma: no-cache
025 *
026 * {
027 *   "access_token"      : "2YotnFZFEjr1zCsicMWpAA",
028 *   "token_type"        : "example",
029 *   "expires_in"        : 3600,
030 *   "refresh_token"     : "tGzv3JOkF0XG5Qx2TlKWIA",
031 *   "example_parameter" : "example_value"
032 * }
033 * </pre>
034 *
035 * <p>Related specifications:
036 *
037 * <ul>
038 *     <li>OAuth 2.0 (RFC 6749), sections 4.1.4, 4.3.3,  4.4.3 and 5.1.
039 * </ul>
040 *
041 * @author Vladimir Dzhuvinov
042 */
043@Immutable
044public class AccessTokenResponse 
045        extends TokenResponse
046        implements SuccessResponse {
047
048
049        /**
050         * The access token.
051         */
052        private final AccessToken accessToken;
053        
054        
055        /**
056         * Optional refresh token.
057         */
058        private final RefreshToken refreshToken;
059        
060        
061        /**
062         * Creates a new access token response.
063         *
064         * @param accessToken  The access token. Must not be {@code null}.
065         * @param refreshToken Optional refresh token, {@code null} if none.
066         */
067        public AccessTokenResponse(final AccessToken accessToken,
068                                   final RefreshToken refreshToken) {
069                                   
070                if (accessToken == null)
071                        throw new IllegalArgumentException("The access token must not be null");
072                
073                this.accessToken = accessToken;
074                
075                this.refreshToken = refreshToken;
076        }
077
078
079        /**
080         * Creates a new access token response.
081         *
082         * @param tokenPair The access and refresh token pair. Must not be 
083         *                  {@code null}.
084         */
085        public AccessTokenResponse(final TokenPair tokenPair) {
086                                   
087                this(tokenPair.getAccessToken(), tokenPair.getRefreshToken());
088        }
089        
090        
091        /**
092         * Gets the access token.
093         *
094         * @return The access token.
095         */
096        public AccessToken getAccessToken() {
097        
098                return accessToken;
099        }
100        
101        
102        /**
103         * Gets the optional refresh token.
104         *
105         * @return The refresh token, {@code null} if none.
106         */
107        public RefreshToken getRefreshToken() {
108        
109                return refreshToken;
110        }
111
112
113        /**
114         * Gets the access and refresh token pair.
115         *
116         * @return The access and refresh token pair. Must not be {@code null}.
117         */
118        public TokenPair getTokenPair() {
119
120                return new TokenPair(accessToken, refreshToken);
121        }
122        
123        
124        /**
125         * Returns the JSON object representing this access token response.
126         *
127         * <p>Example JSON object:
128         *
129         * <pre>
130         * {
131         *   "access_token" : "SlAV32hkKG",
132         *   "token_type"   : "Bearer",
133         *   "refresh_token": "8xLOxBtZp8",
134         *   "expires_in"   : 3600
135         * }
136         * </pre>
137         *
138         * @return The JSON object.
139         *
140         * @throws SerializeException If this access token response couldn't be
141         *                            serialised to a JSON object.
142         */
143        public JSONObject toJSONObject()
144                throws SerializeException {
145        
146                JSONObject o = accessToken.toJSONObject();
147
148                if (refreshToken != null)
149                        o.putAll(refreshToken.toJSONObject());
150                
151                return o;
152        }
153        
154        
155        @Override
156        public HTTPResponse toHTTPResponse()
157                throws SerializeException {
158        
159                HTTPResponse httpResponse = new HTTPResponse(HTTPResponse.SC_OK);
160                
161                httpResponse.setContentType(CommonContentTypes.APPLICATION_JSON);
162                httpResponse.setCacheControl("no-store");
163                httpResponse.setPragma("no-cache");
164                
165                httpResponse.setContent(toJSONObject().toString());
166                
167                return httpResponse;
168        }
169        
170        
171        /**
172         * Parses an access token response from the specified JSON object.
173         *
174         * @param jsonObject The JSON object to parse. Must not be {@code null}.
175         *
176         * @return The access token response.
177         *
178         * @throws ParseException If the JSON object couldn't be parsed to an
179         *                        access token response.
180         */
181        public static AccessTokenResponse parse(final JSONObject jsonObject)
182                throws ParseException {
183                
184                AccessToken accessToken = AccessToken.parse(jsonObject);
185                
186                RefreshToken refreshToken = RefreshToken.parse(jsonObject);
187                
188                return new AccessTokenResponse(accessToken, refreshToken);
189        }
190        
191        
192        /**
193         * Parses an access token response from the specified HTTP response.
194         *
195         * @param httpResponse The HTTP response. Must not be {@code null}.
196         *
197         * @return The access token response.
198         *
199         * @throws ParseException If the HTTP response couldn't be parsed to an 
200         *                        access token response.
201         */
202        public static AccessTokenResponse parse(final HTTPResponse httpResponse)
203                throws ParseException {
204                
205                httpResponse.ensureStatusCode(HTTPResponse.SC_OK);
206                
207                JSONObject jsonObject = httpResponse.getContentAsJSONObject();
208                
209                return parse(jsonObject);
210        }
211}