001    package com.nimbusds.oauth2.sdk.token;
002    
003    
004    import net.minidev.json.JSONObject;
005    
006    import com.nimbusds.oauth2.sdk.ParseException;
007    import 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     */
021    public 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 value. 
046             * The value will be made up of 32 mixed-case alphanumeric ASCII 
047             * characters. The optional lifetime and scope 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 length. The value will be made up of mixed-case 
060             * alphanumeric ASCII characters. The optional lifetime and scope are 
061             * left undefined.
062             *
063             * @param type   The access token type. Must not be {@code null}.
064             * @param length The number of characters. Must be a positive integer.
065             */
066            public AccessToken(final AccessTokenType type, final int length) {
067            
068                    this(type, length, 0l, null);
069            }
070    
071    
072            /**
073             * Creates a new access token with a randomly generated value and the 
074             * specified optional lifetime and scope. The value will be made up of
075             * 32 mixed-case alphanumeric ASCII characters.
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 of the 
091             * specified length and optional lifetime and scope. The value will be 
092             * made up of mixed-case alphanumeric ASCII characters.
093             *
094             * @param type     The access token type. Must not be {@code null}.
095             * @param length   The number of characters. Must be a positive 
096             *                 integer.
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 length, 
102                               final long lifetime, 
103                               final Scope scope) {
104            
105                    super(length);
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             * Gets 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             * Gets 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             * Gets 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    }