001package com.nimbusds.openid.connect.provider.spi.grants; 002 003 004import java.util.Date; 005import java.util.List; 006 007import net.jcip.annotations.Immutable; 008import net.minidev.json.JSONObject; 009import org.checkerframework.checker.nullness.qual.Nullable; 010 011import com.nimbusds.oauth2.sdk.ParseException; 012import com.nimbusds.oauth2.sdk.Scope; 013import com.nimbusds.oauth2.sdk.id.Audience; 014import com.nimbusds.oauth2.sdk.id.Subject; 015import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 016import com.nimbusds.openid.connect.sdk.claims.ACR; 017import com.nimbusds.openid.connect.sdk.claims.AMR; 018 019 020/** 021 * Authorisation produced by a {@link PasswordGrantHandler}. Specifies a 022 * subject (end-user) and permits ID and refresh token issue. 023 * 024 * <p>Required authorisation details: 025 * 026 * <ul> 027 * <li>The authenticated subject (end-user). 028 * <li>The authorised scope. 029 * </ul> 030 * 031 * <p>All other parameters are optional or have suitable defaults. 032 */ 033@Immutable 034public class PasswordGrantAuthorization extends SubjectAuthorization { 035 036 037 /** 038 * Controls the authorisation lifetime, {@code true} for a long-lived 039 * (implies persistence), {@code false} for a short-lived (transient). 040 */ 041 private final boolean longLived; 042 043 044 /** 045 * The refresh token specification. 046 */ 047 private final RefreshTokenSpec refreshTokenSpec; 048 049 050 /** 051 * Creates a new OAuth 2.0 - only authorisation for a password grant. 052 * 053 * @param subject The subject (end-user) identifier. Must not 054 * be {@code null}. 055 * @param scope The authorised scope values. Must not be 056 * {@code null}. 057 */ 058 public PasswordGrantAuthorization(final Subject subject, 059 final Scope scope) { 060 061 this (subject, null, null, null, scope, null, false, AccessTokenSpec.DEFAULT, RefreshTokenSpec.DEFAULT, 062 IDTokenSpec.NONE, ClaimsSpec.NONE, null); 063 } 064 065 066 /** 067 * Creates a new OAuth 2.0 - only authorisation for a password grant. 068 * 069 * @param subject The subject (end-user) identifier. Must not 070 * be {@code null}. 071 * @param scope The authorised scope values. Must not be 072 * {@code null}. 073 * @param audList Explicit list of audiences for the access 074 * token, {@code null} if not specified. 075 * @param longLived Controls the authorisation lifetime, 076 * {@code true} for a long-lived (implies 077 * persistence), {@code false} for a 078 * short-lived (transient). 079 * @param accessTokenSpec The access token specification. Must not 080 * be {@code null}. 081 * @param refreshTokenSpec The refresh token specification. Must not 082 * be {@code null}. 083 * @param data Additional data as a JSON object, 084 * {@code null} if not specified. 085 */ 086 @Deprecated 087 public PasswordGrantAuthorization(final Subject subject, 088 final Scope scope, 089 final @Nullable List<Audience> audList, 090 final boolean longLived, 091 final AccessTokenSpec accessTokenSpec, 092 final RefreshTokenSpec refreshTokenSpec, 093 final @Nullable JSONObject data) { 094 095 this (subject, null, null, null, scope, audList, longLived, accessTokenSpec, refreshTokenSpec, 096 IDTokenSpec.NONE, ClaimsSpec.NONE, data); 097 } 098 099 100 /** 101 * Creates a new OAuth 2.0 - only authorisation for a password grant. 102 * 103 * @param subject The subject (end-user) identifier. Must not 104 * be {@code null}. 105 * @param scope The authorised scope values. Must not be 106 * {@code null}. 107 * @param longLived Controls the authorisation lifetime, 108 * {@code true} for a long-lived (implies 109 * persistence), {@code false} for a 110 * short-lived (transient). 111 * @param accessTokenSpec The access token specification. Must not 112 * be {@code null}. 113 * @param refreshTokenSpec The refresh token specification. Must not 114 * be {@code null}. 115 * @param data Additional data as a JSON object, 116 * {@code null} if not specified. 117 */ 118 public PasswordGrantAuthorization(final Subject subject, 119 final Scope scope, 120 final boolean longLived, 121 final AccessTokenSpec accessTokenSpec, 122 final RefreshTokenSpec refreshTokenSpec, 123 final @Nullable JSONObject data) { 124 125 this(subject, scope, longLived, accessTokenSpec, refreshTokenSpec, IDTokenSpec.NONE, ClaimsSpec.NONE, data); 126 } 127 128 129 /** 130 * Creates a new OpenID Connect / OAuth 2.0 authorisation for a 131 * password grant. 132 * 133 * @param subject The subject (end-user) identifier. Must not 134 * be {@code null}. 135 * @param authTime The time of the subject authentication. If 136 * {@code null} it will be set to now. 137 * Applies only if an ID token is issued. 138 * @param acr The Authentication Context Class Reference 139 * (ACR), {@code null} if not specified. 140 * Applies only if an ID token is issued. 141 * @param amrList The Authentication Methods Reference (AMR) 142 * list, {@code null} if not specified. Applies 143 * only if an ID token is issued. 144 * @param scope The authorised scope values. Must not be 145 * {@code null}. 146 * @param audList Explicit list of audiences for the access 147 * token, {@code null} if not specified. 148 * @param longLived Controls the authorisation lifetime. 149 * {@code true} for a long-lived (implies 150 * persistence), {@code false} for a 151 * short-lived (transient). 152 * @param accessTokenSpec The access token specification. Must not be 153 * {@code null}. 154 * @param refreshTokenSpec The refresh token specification. Must not be 155 * {@code null}. 156 * @param idTokenSpec The ID token specification. Must not be 157 * {@code null}. 158 * @param claimsSpec The OpenID claims specification. 159 * @param data Additional data as a JSON object, 160 * {@code null} if not specified. 161 */ 162 @Deprecated 163 public PasswordGrantAuthorization(final Subject subject, 164 final @Nullable Date authTime, 165 final @Nullable ACR acr, 166 final @Nullable List<AMR> amrList, 167 final Scope scope, 168 final @Nullable List<Audience> audList, 169 final boolean longLived, 170 final AccessTokenSpec accessTokenSpec, 171 final RefreshTokenSpec refreshTokenSpec, 172 final IDTokenSpec idTokenSpec, 173 final ClaimsSpec claimsSpec, 174 final @Nullable JSONObject data) { 175 176 this( 177 subject, 178 scope, 179 longLived, 180 new AccessTokenSpec( 181 accessTokenSpec.getLifetime(), 182 audList, 183 accessTokenSpec.getEncoding(), 184 accessTokenSpec.getImpersonatedSubject(), 185 accessTokenSpec.getEncryptSelfContained(), 186 accessTokenSpec.getSubjectType()), 187 refreshTokenSpec, 188 new IDTokenSpec( 189 idTokenSpec.issue(), 190 idTokenSpec.getLifetime(), 191 authTime, 192 acr, 193 amrList, 194 idTokenSpec.getImpersonatedSubject()), 195 claimsSpec, 196 data); 197 } 198 199 200 /** 201 * Creates a new OpenID Connect / OAuth 2.0 authorisation for a 202 * password grant. 203 * 204 * @param subject The subject (end-user) identifier. Must not 205 * be {@code null}. 206 * @param scope The authorised scope values. Must not be 207 * {@code null}. 208 * @param longLived Controls the authorisation lifetime. 209 * {@code true} for a long-lived (implies 210 * persistence), {@code false} for a 211 * short-lived (transient). 212 * @param accessTokenSpec The access token specification. Must not be 213 * {@code null}. 214 * @param refreshTokenSpec The refresh token specification. Must not be 215 * {@code null}. 216 * @param idTokenSpec The ID token specification. Must not be 217 * {@code null}. 218 * @param claimsSpec The OpenID claims specification. 219 * @param data Additional data as a JSON object, 220 * {@code null} if not specified. 221 */ 222 public PasswordGrantAuthorization(final Subject subject, 223 final Scope scope, 224 final boolean longLived, 225 final AccessTokenSpec accessTokenSpec, 226 final RefreshTokenSpec refreshTokenSpec, 227 final IDTokenSpec idTokenSpec, 228 final ClaimsSpec claimsSpec, 229 final @Nullable JSONObject data) { 230 231 super(subject, scope, accessTokenSpec, idTokenSpec, claimsSpec, data); 232 233 this.longLived = longLived; 234 235 if (refreshTokenSpec == null) { 236 throw new IllegalArgumentException("The refresh token specification must not be null"); 237 } 238 this.refreshTokenSpec = refreshTokenSpec; 239 } 240 241 242 /** 243 * Returns the authorisation lifetime. 244 * 245 * @return {@code true} for a long-lived authorisation (implies 246 * persistence), {@code false} for a short-lived (transient). 247 */ 248 public boolean isLongLived() { 249 250 return longLived; 251 } 252 253 254 /** 255 * Returns the refresh token specification. 256 * 257 * @return The refresh token specification. 258 */ 259 public RefreshTokenSpec getRefreshTokenSpec() { 260 261 return refreshTokenSpec; 262 } 263 264 265 @Override 266 public JSONObject toJSONObject() { 267 268 JSONObject o = super.toJSONObject(); 269 270 o.put("long_lived", longLived); 271 272 if (refreshTokenSpec.issue()) { 273 o.put("refresh_token", refreshTokenSpec.toJSONObject()); 274 } 275 276 return o; 277 } 278 279 280 /** 281 * Parses a password grant authorisation from the specified JSON 282 * object. 283 * 284 * @param jsonObject The JSON object to parse. Must not be 285 * {@code null}. 286 * 287 * @return The password grant authorisation. 288 * 289 * @throws ParseException If parsing failed. 290 */ 291 public static PasswordGrantAuthorization parse(final JSONObject jsonObject) 292 throws ParseException { 293 294 SubjectAuthorization authz = SubjectAuthorization.parse(jsonObject); 295 296 boolean longLived = JSONObjectUtils.getBoolean(jsonObject, "long_lived", false); 297 298 RefreshTokenSpec rtSpec; 299 if (jsonObject.containsKey("refresh_token")) { 300 rtSpec = RefreshTokenSpec.parse(JSONObjectUtils.getJSONObject(jsonObject, "refresh_token")); 301 } else { 302 rtSpec = RefreshTokenSpec.DEFAULT; 303 } 304 305 return new PasswordGrantAuthorization( 306 authz.getSubject(), 307 authz.getScope(), 308 longLived, 309 authz.getAccessTokenSpec(), 310 rtSpec, 311 authz.getIDTokenSpec(), 312 authz.getClaimsSpec(), 313 authz.getData()); 314 } 315 316 317 /** 318 * Parses a password grant authorisation from the specified JSON 319 * object string. 320 * 321 * @param json The JSON object string to parse. Must not be 322 * {@code null}. 323 * 324 * @return The password grant authorisation. 325 * 326 * @throws ParseException If parsing failed. 327 */ 328 public static PasswordGrantAuthorization parse(final String json) 329 throws ParseException { 330 331 return parse(JSONObjectUtils.parse(json)); 332 } 333}