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