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.token;
019
020
021import java.util.List;
022import java.util.Map;
023
024import net.jcip.annotations.Immutable;
025import net.minidev.json.JSONObject;
026
027import com.nimbusds.oauth2.sdk.ParseException;
028import com.nimbusds.oauth2.sdk.Scope;
029import com.nimbusds.oauth2.sdk.http.HTTPRequest;
030import com.nimbusds.oauth2.sdk.util.MultivaluedMapUtils;
031import com.nimbusds.oauth2.sdk.util.StringUtils;
032
033
034/**
035 * Bearer access token.
036 *
037 * <p>Example bearer access token serialised to JSON:
038 *
039 * <pre>
040 * {
041 *   "access_token" : "2YotnFZFEjr1zCsicMWpAA",
042 *   "token_type"   : "bearer",
043 *   "expires_in"   : 3600,
044 *   "scope"        : "read write"
045 * }
046 * </pre>
047 *
048 * <p>The above example token serialised to a HTTP Authorization header:
049 *
050 * <pre>
051 * Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
052 * </pre>
053 *
054 * <p>Related specifications:
055 *
056 * <ul>
057 *     <li>OAuth 2.0 (RFC 6749), sections 1.4 and 5.1.
058 *     <li>OAuth 2.0 Bearer Token Usage (RFC 6750).
059 * </ul>
060 */
061@Immutable
062public class BearerAccessToken extends AccessToken {
063        
064        
065        private static final long serialVersionUID = 2387121016151061194L;
066        
067        
068        /**
069         * Creates a new minimal bearer access token with a randomly generated 
070         * 256-bit (32-byte) value, Base64URL-encoded. The optional lifetime 
071         * and scope are left undefined.
072         */
073        public BearerAccessToken() {
074        
075                this(32);
076        }       
077
078
079        /**
080         * Creates a new minimal bearer access token with a randomly generated 
081         * value of the specified byte length, Base64URL-encoded. The optional 
082         * lifetime and scope are left undefined.
083         *
084         * @param byteLength The byte length of the value to generate. Must be
085         *                   greater than one.
086         */
087        public BearerAccessToken(final int byteLength) {
088        
089                this(byteLength, 0L, null);
090        }
091
092
093        /**
094         * Creates a new bearer access token with a randomly generated 256-bit 
095         * (32-byte) value, Base64URL-encoded.
096         *
097         * @param lifetime The lifetime in seconds, 0 if not specified.
098         * @param scope    The scope, {@code null} if not specified.
099         */
100        public BearerAccessToken(final long lifetime, final Scope scope) {
101        
102                this(32, lifetime, scope);
103        }
104
105
106        /**
107         * Creates a new bearer access token with a randomly generated value of 
108         * the specified byte length, Base64URL-encoded.
109         *
110         * @param byteLength The byte length of the value to generate. Must be
111         *                   greater than one.
112         * @param lifetime   The lifetime in seconds, 0 if not specified.
113         * @param scope      The scope, {@code null} if not specified.
114         */
115        public BearerAccessToken(final int byteLength, final long lifetime, final Scope scope) {
116        
117                super(AccessTokenType.BEARER, byteLength, lifetime, scope);
118        }
119        
120        
121        /**
122         * Creates a new minimal bearer access token with the specified value.
123         * The optional lifetime and scope are left undefined.
124         *
125         * @param value The access token value. Must not be {@code null} or
126         *              empty string.
127         */
128        public BearerAccessToken(final String value) {
129        
130                this(value, 0L, null);
131        }
132        
133        
134        /**
135         * Creates a new bearer access token with the specified value and 
136         * optional lifetime and scope.
137         *
138         * @param value    The access token value. Must not be {@code null} or
139         *                 empty string.
140         * @param lifetime The lifetime in seconds, 0 if not specified.
141         * @param scope    The scope, {@code null} if not specified.
142         */
143        public BearerAccessToken(final String value, final long lifetime, final Scope scope) {
144        
145                super(AccessTokenType.BEARER, value, lifetime, scope);
146        }
147        
148        
149        /**
150         * Returns the HTTP Authorization header value for this bearer access 
151         * token.
152         *
153         * <p>Example:
154         *
155         * <pre>
156         * Authorization: Bearer eyJhbGciOiJIUzI1NiJ9
157         * </pre>
158         *
159         * @return The HTTP Authorization header.
160         */
161        @Override
162        public String toAuthorizationHeader(){
163        
164                return "Bearer " + getValue();
165        }
166        
167        
168        @Override
169        public boolean equals(final Object object) {
170        
171                return object instanceof BearerAccessToken &&
172                       this.toString().equals(object.toString());
173        }
174
175
176        /**
177         * Parses a bearer access token from a JSON object access token 
178         * response.
179         *
180         * @param jsonObject The JSON object to parse. Must not be 
181         *                   {@code null}.
182         *
183         * @return The bearer access token.
184         *
185         * @throws ParseException If the JSON object couldn't be parsed to a
186         *                        bearer access token.
187         */
188        public static BearerAccessToken parse(final JSONObject jsonObject)
189                throws ParseException {
190                
191                AccessTokenUtils.parseAndEnsureType(jsonObject, AccessTokenType.BEARER);
192                String accessTokenValue = AccessTokenUtils.parseValue(jsonObject);
193                long lifetime = AccessTokenUtils.parseLifetime(jsonObject);
194                Scope scope = AccessTokenUtils.parseScope(jsonObject);
195                return new BearerAccessToken(accessTokenValue, lifetime, scope);
196        }
197        
198        
199        /**
200         * Parses an HTTP Authorization header for a bearer access token.
201         *
202         * @param header The HTTP Authorization header value to parse. May be
203         *               {@code null} if the header is missing, in which case
204         *               an exception will be thrown.
205         *
206         * @return The bearer access token.
207         *
208         * @throws ParseException If the HTTP Authorization header value 
209         *                        couldn't be parsed to a bearer access token.
210         */
211        public static BearerAccessToken parse(final String header)
212                throws ParseException {
213                
214                return new BearerAccessToken(AccessTokenUtils.parseValueFromHeader(header, AccessTokenType.BEARER));
215        }
216        
217        
218        /**
219         * Parses a query or form parameters map for a bearer access token.
220         *
221         * @param parameters The query parameters. Must not be {@code null}.
222         *
223         * @return The bearer access token.
224         *
225         * @throws ParseException If a bearer access token wasn't found in the
226         *                        parameters.
227         */
228        public static BearerAccessToken parse(final Map<String,List<String>> parameters)
229                throws ParseException {
230                
231                if (! parameters.containsKey("access_token")) {
232                        throw new ParseException("Missing access token parameter", BearerTokenError.MISSING_TOKEN);
233                }
234                
235                String accessTokenValue = MultivaluedMapUtils.getFirstValue(parameters, "access_token");
236                
237                if (StringUtils.isBlank(accessTokenValue)) {
238                        throw new ParseException("Blank / empty access token", BearerTokenError.INVALID_REQUEST);
239                }
240                
241                return new BearerAccessToken(accessTokenValue);
242        }
243        
244        
245        
246        /**
247         * Parses an HTTP request for a bearer access token.
248         * 
249         * @param request The HTTP request to parse. Must not be {@code null}.
250         * 
251         * @return The bearer access token.
252         * 
253         * @throws ParseException If a bearer access token wasn't found in the
254         *                        HTTP request.
255         */
256        public static BearerAccessToken parse(final HTTPRequest request)
257                throws ParseException {
258
259                // See http://tools.ietf.org/html/rfc6750#section-2
260
261                String authzHeader = request.getAuthorization();
262
263                if (authzHeader != null) {
264
265                        return parse(authzHeader);
266                }
267
268                // Try alternative token locations, form and query string are
269                // parameters are not differentiated here
270
271                Map<String,List<String>> params = request.getQueryParameters();
272                        
273                return parse(params);
274        }
275}