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