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}