001package com.nimbusds.openid.connect.provider.spi.grants; 002 003 004import java.util.*; 005 006import net.jcip.annotations.Immutable; 007 008import net.minidev.json.JSONObject; 009 010import com.nimbusds.oauth2.sdk.ParseException; 011import com.nimbusds.oauth2.sdk.Scope; 012import com.nimbusds.oauth2.sdk.id.Audience; 013import com.nimbusds.oauth2.sdk.id.Subject; 014import com.nimbusds.oauth2.sdk.util.JSONObjectUtils; 015 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 public PasswordGrantAuthorization(final Subject subject, 087 final Scope scope, 088 final List<Audience> audList, 089 final boolean longLived, 090 final AccessTokenSpec accessTokenSpec, 091 final RefreshTokenSpec refreshTokenSpec, 092 final JSONObject data) { 093 094 this (subject, null, null, null, scope, audList, longLived, accessTokenSpec, refreshTokenSpec, 095 IDTokenSpec.NONE, ClaimsSpec.NONE, data); 096 } 097 098 099 /** 100 * Creates a new OpenID Connect / OAuth 2.0 authorisation for a 101 * password grant. 102 * 103 * @param subject The subject (end-user) identifier. Must not 104 * be {@code null}. 105 * @param authTime The time of the subject authentication. If 106 * {@code null} it will be set to now. 107 * Applies only if an ID token is issued. 108 * @param acr The Authentication Context Class Reference 109 * (ACR), {@code null} if not specified. 110 * Applies only if an ID token is issued. 111 * @param amrList The Authentication Methods Reference (AMR) 112 * list, {@code null} if not specified. Applies 113 * only if an ID token is issued. 114 * @param scope The authorised scope values. Must not be 115 * {@code null}. 116 * @param audList Explicit list of audiences for the access 117 * token, {@code null} if not specified. 118 * @param longLived Controls the authorisation lifetime. 119 * {@code true} for a long-lived (implies 120 * persistence), {@code false} for a 121 * short-lived (transient). 122 * @param accessTokenSpec The access token specification. Must not be 123 * {@code null}. 124 * @param refreshTokenSpec The refresh token specification. Must not be 125 * {@code null}. 126 * @param idTokenSpec The ID token specification. Must not be 127 * {@code null}. 128 * @param claimsSpec The claims specification. 129 * @param data Additional data as a JSON object, 130 * {@code null} if not specified. 131 */ 132 public PasswordGrantAuthorization(final Subject subject, 133 final Date authTime, 134 final ACR acr, 135 final List<AMR> amrList, 136 final Scope scope, 137 final List<Audience> audList, 138 final boolean longLived, 139 final AccessTokenSpec accessTokenSpec, 140 final RefreshTokenSpec refreshTokenSpec, 141 final IDTokenSpec idTokenSpec, 142 final ClaimsSpec claimsSpec, 143 final JSONObject data) { 144 145 this( 146 subject, 147 scope, 148 longLived, 149 new AccessTokenSpec(accessTokenSpec.getLifetime(), audList, accessTokenSpec.getEncoding(), accessTokenSpec.encrypt()), 150 refreshTokenSpec, 151 new IDTokenSpec(idTokenSpec.issue(), idTokenSpec.getLifetime(), authTime, acr, amrList, idTokenSpec.getImpersonatedSubject()), 152 claimsSpec, 153 data); 154 } 155 156 157 /** 158 * Creates a new OpenID Connect / OAuth 2.0 authorisation for a 159 * password grant. 160 * 161 * @param subject The subject (end-user) identifier. Must not 162 * be {@code null}. 163 * @param scope The authorised scope values. Must not be 164 * {@code null}. 165 * @param longLived Controls the authorisation lifetime. 166 * {@code true} for a long-lived (implies 167 * persistence), {@code false} for a 168 * short-lived (transient). 169 * @param accessTokenSpec The access token specification. Must not be 170 * {@code null}. 171 * @param refreshTokenSpec The refresh token specification. Must not be 172 * {@code null}. 173 * @param idTokenSpec The ID token specification. Must not be 174 * {@code null}. 175 * @param claimsSpec The claims specification. 176 * @param data Additional data as a JSON object, 177 * {@code null} if not specified. 178 */ 179 public PasswordGrantAuthorization(final Subject subject, 180 final Scope scope, 181 final boolean longLived, 182 final AccessTokenSpec accessTokenSpec, 183 final RefreshTokenSpec refreshTokenSpec, 184 final IDTokenSpec idTokenSpec, 185 final ClaimsSpec claimsSpec, 186 final JSONObject data) { 187 188 super(subject, scope, accessTokenSpec, idTokenSpec, claimsSpec, data); 189 190 this.longLived = longLived; 191 192 if (refreshTokenSpec == null) { 193 throw new IllegalArgumentException("The refresh token specification must not be null"); 194 } 195 this.refreshTokenSpec = refreshTokenSpec; 196 } 197 198 199 /** 200 * Returns the authorisation lifetime. 201 * 202 * @return {@code true} for a long-lived authorisation (implies 203 * persistence), {@code false} for a short-lived (transient). 204 */ 205 public boolean isLongLived() { 206 207 return longLived; 208 } 209 210 211 /** 212 * Returns the refresh token specification. 213 * 214 * @return The refresh token specification. 215 */ 216 public RefreshTokenSpec getRefreshTokenSpec() { 217 218 return refreshTokenSpec; 219 } 220 221 222 @Override 223 public JSONObject toJSONObject() { 224 225 JSONObject o = super.toJSONObject(); 226 227 o.put("long_lived", longLived); 228 229 if (longLived && refreshTokenSpec.issue()) { 230 o.put("refresh_token", refreshTokenSpec.toJSONObject()); 231 } 232 233 return o; 234 } 235 236 237 /** 238 * Parses a password grant authorisation from the specified JSON 239 * object. 240 * 241 * @param jsonObject The JSON object to parse. Must not be 242 * {@code null}. 243 * 244 * @return The password grant authorisation. 245 * 246 * @throws ParseException If parsing failed. 247 */ 248 public static PasswordGrantAuthorization parse(final JSONObject jsonObject) 249 throws ParseException { 250 251 SubjectAuthorization authz = SubjectAuthorization.parse(jsonObject); 252 253 boolean longLived = false; 254 255 if (jsonObject.containsKey("long_lived")) { 256 longLived = JSONObjectUtils.getBoolean(jsonObject, "long_lived"); 257 } 258 259 RefreshTokenSpec rtSpec = new RefreshTokenSpec(); 260 261 if (longLived && jsonObject.containsKey("refresh_token")) { 262 rtSpec = RefreshTokenSpec.parse(JSONObjectUtils.getJSONObject(jsonObject, "refresh_token")); 263 } 264 265 return new PasswordGrantAuthorization( 266 authz.getSubject(), 267 authz.getScope(), 268 longLived, 269 authz.getAccessTokenSpec(), 270 rtSpec, 271 authz.getIDTokenSpec(), 272 authz.getClaimsSpec(), 273 authz.getData()); 274 } 275 276 277 /** 278 * Parses a password grant authorisation from the specified JSON 279 * object string. 280 * 281 * @param json The JSON object string to parse. Must not be 282 * {@code null}. 283 * 284 * @return The password grant authorisation. 285 * 286 * @throws ParseException If parsing failed. 287 */ 288 public static PasswordGrantAuthorization parse(final String json) 289 throws ParseException { 290 291 return parse(JSONObjectUtils.parse(json)); 292 } 293}