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.HashSet;
022import java.util.Set;
023
024import net.minidev.json.JSONObject;
025
026import com.nimbusds.oauth2.sdk.ParseException;
027import com.nimbusds.oauth2.sdk.Scope;
028
029
030/**
031 * The base abstract class for access tokens. Concrete extending classes should
032 * be immutable.
033 *
034 * <p>Related specifications:
035 *
036 * <ul>
037 *     <li>OAuth 2.0 (RFC 6749), sections 1.4 and 5.1.
038 * </ul>
039 */
040public abstract class AccessToken extends Token {
041
042        
043        /**
044         * The access token type.
045         */
046        private final AccessTokenType type;
047        
048        
049        /**
050         * Optional lifetime, in seconds.
051         */
052        private final long lifetime;
053        
054        
055        /**
056         * Optional scope.
057         */
058        private final Scope scope;
059
060
061        /**
062         * Creates a new minimal access token with a randomly generated 256-bit 
063         * (32-byte) value, Base64URL-encoded. The optional lifetime and scope 
064         * are left undefined.
065         *
066         * @param type The access token type. Must not be {@code null}.
067         */
068        public AccessToken(final AccessTokenType type) {
069        
070                this(type, 32);
071        }
072
073
074        /**
075         * Creates a new minimal access token with a randomly generated value 
076         * of the specified byte length, Base64URL-encoded. The optional 
077         * lifetime and scope are left undefined.
078         *
079         * @param type       The access token type. Must not be {@code null}.
080         * @param byteLength The byte length of the value to generate. Must be
081         *                   greater than one.
082         */
083        public AccessToken(final AccessTokenType type, final int byteLength) {
084        
085                this(type, byteLength, 0L, null);
086        }
087
088
089        /**
090         * Creates a new access token with a randomly generated 256-bit 
091         * (32-byte) value, Base64URL-encoded.
092         *
093         * @param type     The access token type. Must not be {@code null}.
094         * @param lifetime The lifetime in seconds, 0 if not specified.
095         * @param scope    The scope, {@code null} if not specified.
096         */
097        public AccessToken(final AccessTokenType type,
098                           final long lifetime, 
099                           final Scope scope) {
100        
101                this(type, 32, lifetime, scope);
102        }
103
104
105        /**
106         * Creates a new access token with a randomly generated value 
107         * of the specified byte length, Base64URL-encoded, and optional 
108         * lifetime and scope.
109         *
110         * @param type       The access token type. Must not be {@code null}.
111         * @param byteLength The byte length of the value to generate. Must be
112         *                   greater than one.
113         * @param lifetime   The lifetime in seconds, 0 if not specified.
114         * @param scope      The scope, {@code null} if not specified.
115         */
116        public AccessToken(final AccessTokenType type, 
117                           final int byteLength, 
118                           final long lifetime, 
119                           final Scope scope) {
120        
121                super(byteLength);
122
123                if (type == null)
124                        throw new IllegalArgumentException("The access token type must not be null");
125
126                this.type = type;
127
128                this.lifetime = lifetime;
129                this.scope = scope;
130        }
131        
132        
133        /**
134         * Creates a new minimal access token with the specified value. The 
135         * optional lifetime and scope are left undefined.
136         *
137         * @param type  The access token type. Must not be {@code null}.
138         * @param value The access token value. Must not be {@code null} or
139         *              empty string.
140         */
141        public AccessToken(final AccessTokenType type, final String value) {
142        
143                this(type, value, 0L, null);
144        }
145        
146        
147        /**
148         * Creates a new access token with the specified value and optional 
149         * lifetime and scope.
150         *
151         * @param type     The access token type. Must not be {@code null}.
152         * @param value    The access token value. Must not be {@code null} or
153         *                 empty string.
154         * @param lifetime The lifetime in seconds, 0 if not specified.
155         * @param scope    The scope, {@code null} if not specified.
156         */
157        public AccessToken(final AccessTokenType type, 
158                           final String value, 
159                           final long lifetime, 
160                           final Scope scope) {
161        
162                super(value);
163
164                if (type == null)
165                        throw new IllegalArgumentException("The access token type must not be null");
166
167                this.type = type;
168
169                this.lifetime = lifetime;
170                this.scope = scope;
171        }
172
173
174        /**
175         * Returns the access token type.
176         *
177         * @return The access token type.
178         */
179        public AccessTokenType getType() {
180
181                return type;
182        }
183
184        
185        /**
186         * Returns the lifetime of this access token.
187         *
188         * @return The lifetime in seconds, 0 if not specified.
189         */
190        public long getLifetime() {
191        
192                return lifetime;
193        }
194        
195        
196        /**
197         * Returns the scope of this access token.
198         *
199         * @return The scope, {@code null} if not specified.
200         */
201        public Scope getScope() {
202        
203                return scope;
204        }
205
206
207        @Override
208        public Set<String> getParameterNames() {
209
210                Set<String> paramNames = new HashSet<>();
211                paramNames.add("access_token");
212                paramNames.add("token_type");
213
214                if (getLifetime() > 0)
215                        paramNames.add("expires_in");
216
217                if (getScope() != null)
218                        paramNames.add("scope");
219
220                return paramNames;
221        }
222
223
224        @Override
225        public JSONObject toJSONObject() {
226
227                JSONObject o = new JSONObject();
228
229                o.put("access_token", getValue());
230                o.put("token_type", type.toString());
231                
232                if (getLifetime() > 0)
233                        o.put("expires_in", lifetime);
234
235                if (getScope() != null)
236                        o.put("scope", scope.toString());
237                
238                return o;
239        }
240
241
242        @Override
243        public String toJSONString() {
244
245                return toJSONObject().toString();
246        }
247        
248        
249        /**
250         * Returns the {@code Authorization} HTTP request header value for this
251         * access token.
252         *
253         * @return The {@code Authorization} header value.
254         */
255        public abstract String toAuthorizationHeader();
256
257
258        /**
259         * Parses an access token from a JSON object access token response.
260         * Only bearer access tokens are supported.
261         *
262         * @param jsonObject The JSON object to parse. Must not be 
263         *                   {@code null}.
264         *
265         * @return The access token.
266         *
267         * @throws ParseException If the JSON object couldn't be parsed to an
268         *                        access token.
269         */
270        public static AccessToken parse(final JSONObject jsonObject)
271                throws ParseException {
272
273                return BearerAccessToken.parse(jsonObject);
274        }
275        
276        
277        /**
278         * Parses an {@code Authorization} HTTP request header value for an 
279         * access token. Only bearer access token are supported.
280         *
281         * @param header The {@code Authorization} header value to parse. Must 
282         *               not be {@code null}.
283         *
284         * @return The access token.
285         *
286         * @throws ParseException If the {@code Authorization} header value 
287         *                        couldn't be parsed to an access token.
288         */
289        public static AccessToken parse(final String header)
290                throws ParseException {
291        
292                return BearerAccessToken.parse(header);
293        }
294}