001package com.nimbusds.openid.connect.provider.spi.grants; 002 003 004import com.nimbusds.oauth2.sdk.ParseException; 005import com.nimbusds.oauth2.sdk.Scope; 006import com.nimbusds.oauth2.sdk.id.Audience; 007import com.nimbusds.oauth2.sdk.id.Subject; 008import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 009import com.nimbusds.openid.connect.sdk.claims.ACR; 010import com.nimbusds.openid.connect.sdk.claims.AMR; 011import net.jcip.annotations.Immutable; 012import net.minidev.json.JSONObject; 013import org.checkerframework.checker.nullness.qual.Nullable; 014 015import java.util.Date; 016import java.util.List; 017import java.util.Objects; 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 this.longLived = longLived; 233 this.refreshTokenSpec = Objects.requireNonNull(refreshTokenSpec); 234 } 235 236 237 /** 238 * Returns the authorisation lifetime. 239 * 240 * @return {@code true} for a long-lived authorisation (implies 241 * persistence), {@code false} for a short-lived (transient). 242 */ 243 public boolean isLongLived() { 244 245 return longLived; 246 } 247 248 249 /** 250 * Returns the refresh token specification. 251 * 252 * @return The refresh token specification. 253 */ 254 public RefreshTokenSpec getRefreshTokenSpec() { 255 256 return refreshTokenSpec; 257 } 258 259 260 @Override 261 public JSONObject toJSONObject() { 262 263 JSONObject o = super.toJSONObject(); 264 265 o.put("long_lived", longLived); 266 267 if (refreshTokenSpec.issue()) { 268 o.put("refresh_token", refreshTokenSpec.toJSONObject()); 269 } 270 271 return o; 272 } 273 274 275 /** 276 * Parses a password grant authorisation from the specified JSON 277 * object. 278 * 279 * @param jsonObject The JSON object to parse. Must not be 280 * {@code null}. 281 * 282 * @return The password grant authorisation. 283 * 284 * @throws ParseException If parsing failed. 285 */ 286 public static PasswordGrantAuthorization parse(final JSONObject jsonObject) 287 throws ParseException { 288 289 SubjectAuthorization authz = SubjectAuthorization.parse(jsonObject); 290 291 boolean longLived = JSONObjectUtils.getBoolean(jsonObject, "long_lived", false); 292 293 RefreshTokenSpec rtSpec; 294 if (jsonObject.containsKey("refresh_token")) { 295 rtSpec = RefreshTokenSpec.parse(JSONObjectUtils.getJSONObject(jsonObject, "refresh_token")); 296 } else { 297 rtSpec = RefreshTokenSpec.DEFAULT; 298 } 299 300 return new PasswordGrantAuthorization( 301 authz.getSubject(), 302 authz.getScope(), 303 longLived, 304 authz.getAccessTokenSpec(), 305 rtSpec, 306 authz.getIDTokenSpec(), 307 authz.getClaimsSpec(), 308 authz.getData()); 309 } 310 311 312 /** 313 * Parses a password grant authorisation from the specified JSON 314 * object string. 315 * 316 * @param json The JSON object string to parse. Must not be 317 * {@code null}. 318 * 319 * @return The password grant authorisation. 320 * 321 * @throws ParseException If parsing failed. 322 */ 323 public static PasswordGrantAuthorization parse(final String json) 324 throws ParseException { 325 326 return parse(JSONObjectUtils.parse(json)); 327 } 328}