001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2020, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.openid.connect.sdk.federation.api;
019
020
021import java.net.URI;
022import java.util.*;
023
024import net.jcip.annotations.Immutable;
025
026import com.nimbusds.common.contenttype.ContentType;
027import com.nimbusds.jwt.SignedJWT;
028import com.nimbusds.jwt.util.DateUtils;
029import com.nimbusds.oauth2.sdk.ParseException;
030import com.nimbusds.oauth2.sdk.http.HTTPRequest;
031import com.nimbusds.oauth2.sdk.id.Identifier;
032import com.nimbusds.oauth2.sdk.id.Subject;
033import com.nimbusds.oauth2.sdk.util.MultivaluedMapUtils;
034import com.nimbusds.oauth2.sdk.util.StringUtils;
035import com.nimbusds.oauth2.sdk.util.URLUtils;
036import com.nimbusds.openid.connect.sdk.federation.entities.EntityID;
037
038
039/**
040 * Trust mark status request.
041 *
042 * <p>Related specifications:
043 *
044 * <ul>
045 *     <li>OpenID Connect Federation 1.0, section 7.4.1.
046 * </ul>
047 */
048@Immutable
049public class TrustMarkStatusRequest extends FederationAPIRequest {
050        
051        
052        /**
053         * The trust mark subject.
054         */
055        private final Subject subject;
056        
057        
058        /**
059         * The trust mark identifier.
060         */
061        private final Identifier id;
062        
063        
064        /**
065         * The trust mark issue time.
066         */
067        private final Date iat;
068        
069        
070        /**
071         * The trust mark.
072         */
073        private final SignedJWT trustMark;
074        
075        
076        /**
077         * Creates a new trust mark status request.
078         *
079         * @param endpoint The trust mark status endpoint. Must not be
080         *                 {@code null}.
081         * @param subject  The subject. Must not be {@code null}.
082         * @param id       The trust mark identifier. Must not be {@code null}.
083         * @param iat      The trust mark issue time, {@code null} if not
084         *                 specified.
085         */
086        public TrustMarkStatusRequest(final URI endpoint,
087                                      final Subject subject,
088                                      final Identifier id,
089                                      final Date iat) {
090                
091                super(endpoint);
092                
093                if (subject == null) {
094                        throw new IllegalArgumentException("The subject must not be null");
095                }
096                this.subject = subject;
097                
098                if (id == null) {
099                        throw new IllegalArgumentException("The ID must not be null");
100                }
101                this.id = id;
102                
103                this.iat = iat;
104                
105                trustMark = null;
106        }
107        
108        
109        /**
110         * Creates a new trust mark status request.
111         *
112         * @param endpoint  The trust mark status endpoint. Must not be
113         *                  {@code null}.
114         * @param trustMark The trust mark. Must not be {@code null}.
115         */
116        public TrustMarkStatusRequest(final URI endpoint,
117                                      final SignedJWT trustMark) {
118                super(endpoint);
119                
120                if (trustMark == null) {
121                        throw new IllegalArgumentException("The trust mark must not be null");
122                }
123                this.trustMark = trustMark;
124                
125                subject = null;
126                id = null;
127                iat = null;
128        }
129        
130        
131        /**
132         * Returns the trust mark subject.
133         *
134         * @return The trust mark subject, {@code null} if not specified.
135         */
136        public Subject getSubject() {
137                return subject;
138        }
139        
140        
141        /**
142         * Returns the trust mark subject entity ID.
143         *
144         * @return The trust mark subject entity ID, {@code null} if not
145         *         specified.
146         */
147        public EntityID getSubjectEntityID() {
148                return subject != null ? new EntityID(subject) : null;
149        }
150        
151        
152        /**
153         * Returns the trust mark ID.
154         *
155         * @return The trust mark ID, {@code null} if not specified.
156         */
157        public Identifier getID() {
158                return id;
159        }
160        
161        
162        /**
163         * Returns the trust mark issue time.
164         *
165         * @return The trust mark issue time, {@code null} if not specified.
166         */
167        public Date getIssueTime() {
168                return iat;
169        }
170        
171        
172        /**
173         * Returns the trust mark.
174         *
175         * @return The trust mark, {@code null} if not specified.
176         */
177        public SignedJWT getTrustMark() {
178                return trustMark;
179        }
180        
181        
182        @Override
183        public Map<String, List<String>> toParameters() {
184                Map<String, List<String>> params = new LinkedHashMap<>();
185                if (getSubject() != null) {
186                        params.put("sub", Collections.singletonList(getSubject().getValue()));
187                }
188                if (getID() != null) {
189                        params.put("id", Collections.singletonList(getID().getValue()));
190                }
191                if (getIssueTime() != null) {
192                        params.put("iat", Collections.singletonList(DateUtils.toSecondsSinceEpoch(getIssueTime()) + ""));
193                }
194                if (getTrustMark() != null) {
195                        params.put("trust_mark", Collections.singletonList(getTrustMark().serialize()));
196                }
197                return params;
198        }
199        
200        
201        @Override
202        public HTTPRequest toHTTPRequest() {
203                HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.POST, getEndpointURI());
204                httpRequest.setEntityContentType(ContentType.APPLICATION_URLENCODED);
205                httpRequest.setQuery(URLUtils.serializeParameters(toParameters()));
206                return httpRequest;
207        }
208        
209        
210        /**
211         * Parses a trust mark status request from the specified request
212         * parameters.
213         *
214         * @param params The request parameters. Must not be {@code null}.
215         *
216         * @return The trust mark status request.
217         *
218         * @throws ParseException If parsing failed.
219         */
220        public static TrustMarkStatusRequest parse(final Map<String, List<String>> params)
221                throws ParseException {
222                
223                Subject subject = null;
224                String value = MultivaluedMapUtils.getFirstValue(params, "sub");
225                if (StringUtils.isNotBlank(value)) {
226                        subject = new Subject(value);
227                }
228                
229                Identifier id = null;
230                value = MultivaluedMapUtils.getFirstValue(params, "id");
231                if (StringUtils.isNotBlank(value)) {
232                        id = new Identifier(value);
233                }
234                
235                Date iat = null;
236                value = MultivaluedMapUtils.getFirstValue(params, "iat");
237                if (StringUtils.isNotBlank(value)) {
238                        try {
239                                iat = DateUtils.fromSecondsSinceEpoch(Long.parseLong(value));
240                        } catch (NumberFormatException e) {
241                                throw new ParseException("Illegal iat");
242                        }
243                }
244                
245                SignedJWT trustMark = null;
246                value = MultivaluedMapUtils.getFirstValue(params, "trust_mark");
247                if (StringUtils.isNotBlank(value)) {
248                        try {
249                                trustMark = SignedJWT.parse(value);
250                        } catch (java.text.ParseException e) {
251                                throw new ParseException("Invalid trust mark: " + e.getMessage(), e);
252                        }
253                }
254                
255                if (trustMark != null) {
256                        return new TrustMarkStatusRequest(null, trustMark);
257                }
258                
259                try {
260                        return new TrustMarkStatusRequest(null, subject, id, iat);
261                } catch (IllegalArgumentException e) {
262                        throw new ParseException("Invalid request: " + e.getMessage());
263                }
264        }
265        
266        
267        /**
268         * Parses a trust mark status request from the specified HTTP request.
269         *
270         * @param httpRequest The HTTP request. Must not be {@code null}.
271         *
272         * @return The trust negotiation request.
273         *
274         * @throws ParseException If parsing failed.
275         */
276        public static TrustMarkStatusRequest parse(final HTTPRequest httpRequest)
277                throws ParseException {
278                
279                httpRequest.ensureMethod(HTTPRequest.Method.POST);
280                httpRequest.ensureEntityContentType(ContentType.APPLICATION_URLENCODED);
281                
282                TrustMarkStatusRequest request = TrustMarkStatusRequest.parse(httpRequest.getQueryParameters());
283                
284                if (request.getTrustMark() != null) {
285                        return new TrustMarkStatusRequest(
286                                httpRequest.getURI(),
287                                request.trustMark
288                        );
289                } else {
290                        return new TrustMarkStatusRequest(
291                                httpRequest.getURI(),
292                                request.getSubject(),
293                                request.getID(),
294                                request.getIssueTime()
295                        );
296                }
297        }
298}