001package com.nimbusds.oauth2.sdk.token; 002 003 004import java.util.HashSet; 005import java.util.Set; 006 007import net.minidev.json.JSONObject; 008 009import com.nimbusds.oauth2.sdk.ParseException; 010import com.nimbusds.oauth2.sdk.Scope; 011 012 013/** 014 * The base abstract class for access tokens. Concrete extending classes should 015 * be immutable. 016 * 017 * <p>Related specifications: 018 * 019 * <ul> 020 * <li>OAuth 2.0 (RFC 6749), sections 1.4 and 5.1. 021 * </ul> 022 */ 023public abstract class AccessToken extends Token { 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 * Returns 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 * Returns 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 * Returns 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 Set<String> getParameterNames() { 192 193 Set<String> paramNames = new HashSet<>(); 194 paramNames.add("access_token"); 195 paramNames.add("token_type"); 196 197 if (getLifetime() > 0) 198 paramNames.add("expires_in"); 199 200 if (getScope() != null) 201 paramNames.add("scope"); 202 203 return paramNames; 204 } 205 206 207 @Override 208 public JSONObject toJSONObject() { 209 210 JSONObject o = new JSONObject(); 211 212 o.put("access_token", getValue()); 213 o.put("token_type", type.toString()); 214 215 if (getLifetime() > 0) 216 o.put("expires_in", lifetime); 217 218 if (getScope() != null) 219 o.put("scope", scope.toString()); 220 221 return o; 222 } 223 224 225 @Override 226 public String toJSONString() { 227 228 return toJSONObject().toString(); 229 } 230 231 232 /** 233 * Returns the {@code Authorization} HTTP request header value for this 234 * access token. 235 * 236 * @return The {@code Authorization} header value. 237 */ 238 public abstract String toAuthorizationHeader(); 239 240 241 /** 242 * Parses an access token from a JSON object access token response. 243 * Only bearer access tokens are supported. 244 * 245 * @param jsonObject The JSON object to parse. Must not be 246 * {@code null}. 247 * 248 * @return The access token. 249 * 250 * @throws ParseException If the JSON object couldn't be parsed to an 251 * access token. 252 */ 253 public static AccessToken parse(final JSONObject jsonObject) 254 throws ParseException { 255 256 return BearerAccessToken.parse(jsonObject); 257 } 258 259 260 /** 261 * Parses an {@code Authorization} HTTP request header value for an 262 * access token. Only bearer access token are supported. 263 * 264 * @param header The {@code Authorization} header value to parse. Must 265 * not be {@code null}. 266 * 267 * @return The access token. 268 * 269 * @throws ParseException If the {@code Authorization} header value 270 * couldn't be parsed to an access token. 271 */ 272 public static AccessToken parse(final String header) 273 throws ParseException { 274 275 return BearerAccessToken.parse(header); 276 } 277}