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