001package com.nimbusds.openid.connect.provider.spi.grants; 002 003 004import java.util.List; 005 006import com.nimbusds.oauth2.sdk.ParseException; 007import com.nimbusds.oauth2.sdk.id.Audience; 008import com.nimbusds.oauth2.sdk.id.Subject; 009import com.nimbusds.oauth2.sdk.token.TokenEncoding; 010import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 011import net.jcip.annotations.Immutable; 012import net.minidev.json.JSONObject; 013 014 015/** 016 * Access token specification.. 017 */ 018@Immutable 019public class AccessTokenSpec extends TokenSpec { 020 021 022 /** 023 * Default access token specification. No explicit token lifetime is 024 * specified (to let the Connect2id server apply the default configured 025 * lifetime for access tokens). No explicit token audience is 026 * specified. No subject in impersonation and delegation cases is 027 * specified. The token is self-contained (JWT-encoded) and not 028 * encrypted. 029 */ 030 public static final AccessTokenSpec DEFAULT = new AccessTokenSpec(); 031 032 033 /** 034 * The access token encoding. 035 */ 036 private final TokenEncoding encoding; 037 038 039 /** 040 * If {@code true} flags the access token for encryption. Applies to 041 * self-contained access tokens only. 042 */ 043 private final boolean encrypt; 044 045 046 /** 047 * Creates a new default access token specification. No explicit 048 * token lifetime is specified (to let the Connect2id server apply the 049 * default configured lifetime for access tokens). No explicit token 050 * audience is specified. No subject in impersonation and delegation 051 * cases is specified. The token is self-contained (JWT-encoded) and 052 * not encrypted. 053 */ 054 public AccessTokenSpec() { 055 056 this(0L, null, TokenEncoding.SELF_CONTAINED, null, false); 057 } 058 059 060 /** 061 * Creates a new access token specification. 062 * 063 * @param lifetime The access token lifetime, in seconds, 064 * zero if not specified (to let the 065 * Connect2id server apply the default 066 * configured lifetime for access tokens). 067 * @param audList Explicit list of audiences for the access 068 * token, {@code null} if not specified. 069 * @param encoding The access token encoding. Must not be 070 * {@code null}. 071 * @param impersonatedSubject The subject in impersonation and 072 * delegation cases, {@code null} if not 073 * applicable. 074 * @param encrypt If {@code true} flags the access token 075 * for encryption. Applies to self-contained 076 * (JWT) access tokens only. 077 */ 078 public AccessTokenSpec(final long lifetime, 079 final List<Audience> audList, 080 final TokenEncoding encoding, 081 final Subject impersonatedSubject, 082 final boolean encrypt) { 083 084 super(lifetime, audList, impersonatedSubject); 085 086 if (encoding == null) { 087 throw new IllegalArgumentException("The access token encoding must not be null"); 088 } 089 090 this.encoding = encoding; 091 092 // Only JWT tokens may be encrypted 093 this.encrypt = encoding.equals(TokenEncoding.SELF_CONTAINED) && encrypt; 094 } 095 096 097 /** 098 * Creates a new access token specification. No subject in 099 * impersonation and delegation cases is specified. 100 * 101 * @param lifetime The access token lifetime, in seconds, zero if not 102 * specified (to let the Connect2id server apply the 103 * default configured lifetime for access tokens). 104 * @param audList Explicit list of audiences for the access token, 105 * {@code null} if not specified. 106 * @param encoding The access token encoding. Must not be {@code null}. 107 * @param encrypt If {@code true} flags the access token for 108 * encryption. Applies to self-contained (JWT) access 109 * tokens only. 110 */ 111 public AccessTokenSpec(final long lifetime, 112 final List<Audience> audList, 113 final TokenEncoding encoding, 114 final boolean encrypt) { 115 116 this(lifetime, audList, encoding, null, encrypt); 117 } 118 119 120 /** 121 * Creates a new access token specification. No explicit token audience 122 * is specified. No subject in impersonation and delegation cases is 123 * specified. 124 * 125 * @param lifetime The access token lifetime, in seconds, zero if not 126 * specified (to let the Connect2id server apply the 127 * default configured lifetime for access tokens). 128 * @param encoding The access token encoding. Must not be {@code null}. 129 * @param encrypt If {@code true} flags the access token for 130 * encryption. Applies to self-contained (JWT) access 131 * tokens only. 132 */ 133 public AccessTokenSpec(final long lifetime, 134 final TokenEncoding encoding, 135 final boolean encrypt) { 136 137 this(lifetime, null, encoding, null, encrypt); 138 } 139 140 141 /** 142 * Returns the access token encoding. 143 * 144 * @return The access token encoding. 145 */ 146 public TokenEncoding getEncoding() { 147 148 return encoding; 149 } 150 151 152 /** 153 * Returns the access token encryption flag. 154 * 155 * @return If {@code true} the access token is flagged for encryption. 156 * Applies to self-contained access tokens only. 157 */ 158 public boolean encrypt() { 159 160 return encrypt; 161 } 162 163 164 @Override 165 public JSONObject toJSONObject() { 166 167 JSONObject o = super.toJSONObject(); 168 169 if (getLifetime() <= 0) { 170 // Implies not specified - remove 171 o.remove("lifetime"); 172 } 173 174 o.put("encoding", encoding.toString()); 175 176 if (encoding.equals(TokenEncoding.SELF_CONTAINED)) { 177 o.put("encrypt", encrypt); 178 } 179 180 return o; 181 } 182 183 184 /** 185 * Parses an access token specification from the specified JSON object. 186 * 187 * @param jsonObject The JSON object. Must not be {@code null}. 188 * 189 * @return The access token specification. 190 * 191 * @throws ParseException If parsing failed. 192 */ 193 public static AccessTokenSpec parse(final JSONObject jsonObject) 194 throws ParseException { 195 196 TokenSpec tokenSpec = TokenSpec.parse(jsonObject); 197 198 // Adjust lifetime value for not specified (0) 199 long lifetime = tokenSpec.getLifetime() > 0 ? tokenSpec.getLifetime() : 0; 200 201 TokenEncoding encoding = TokenEncoding.SELF_CONTAINED; 202 boolean encrypt = false; 203 204 if (jsonObject.containsKey("encoding")) { 205 206 String c = JSONObjectUtils.getString(jsonObject, "encoding"); 207 208 try { 209 encoding = TokenEncoding.valueOf(c.toUpperCase()); 210 211 } catch (IllegalArgumentException e) { 212 213 throw new ParseException("Invalid access token encoding"); 214 } 215 } 216 217 if (encoding.equals(TokenEncoding.SELF_CONTAINED)) { 218 if (jsonObject.containsKey("encrypt")) { 219 220 encrypt = JSONObjectUtils.getBoolean(jsonObject, "encrypt"); 221 } 222 } 223 224 return new AccessTokenSpec(lifetime, tokenSpec.getAudience(), encoding, tokenSpec.getImpersonatedSubject(), encrypt); 225 } 226}