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.Collections;
023import java.util.HashMap;
024import java.util.List;
025import java.util.Map;
026
027import net.jcip.annotations.Immutable;
028
029import com.nimbusds.oauth2.sdk.ParseException;
030import com.nimbusds.oauth2.sdk.http.HTTPRequest;
031import com.nimbusds.oauth2.sdk.id.Audience;
032import com.nimbusds.oauth2.sdk.id.Issuer;
033import com.nimbusds.oauth2.sdk.id.Subject;
034import com.nimbusds.oauth2.sdk.util.MultivaluedMapUtils;
035import com.nimbusds.openid.connect.sdk.federation.entities.EntityID;
036
037
038/**
039 * Fetch entity statement request.
040 *
041 * <p>Related specifications:
042 *
043 * <ul>
044 *     <li>OpenID Connect Federation 1.0, section 6.1.1.
045 * </ul>
046 */
047@Immutable
048public class FetchEntityStatementRequest extends FederationAPIRequest {
049        
050        
051        /**
052         * The issuer.
053         */
054        private final Issuer issuer;
055        
056        
057        /**
058         * The optional subject.
059         */
060        private final Subject subject;
061        
062        
063        /**
064         * The optional audience.
065         */
066        private final Audience audience;
067        
068        
069        /**
070         * Creates a new entity fetch request.
071         *
072         * @param endpoint The federation API endpoint. Must not be
073         *                 {@code null}.
074         * @param issuer   The issuer entity identifier. Must not be
075         *                 {@code null}.
076         * @param subject  The subject entity identifier, {@code null} if not
077         *                 specified.
078         * @param audience The audience (requester) entity identifier,
079         *                 {@code null} if not specified.
080         */
081        public FetchEntityStatementRequest(final URI endpoint, final Issuer issuer, final Subject subject, final Audience audience) {
082                super(endpoint, OperationType.FETCH);
083                if (issuer == null) {
084                        throw new IllegalArgumentException("The issuer must not be null");
085                }
086                this.issuer = issuer;
087                this.subject = subject;
088                this.audience = audience;
089        }
090        
091        
092        /**
093         * Creates a new entity fetch request.
094         *
095         * @param endpoint The federation API endpoint. Must not be
096         *                 {@code null}.
097         * @param issuer   The issuer entity identifier. Must not be
098         *                 {@code null}.
099         * @param subject  The subject entity identifier, {@code null} if not
100         *                 specified.
101         * @param audience The audience (requester) entity identifier,
102         *                 {@code null} if not specified.
103         */
104        public FetchEntityStatementRequest(final URI endpoint, final EntityID issuer, final EntityID subject, final EntityID audience) {
105                this(endpoint,
106                        new Issuer(issuer.getValue()),
107                        subject != null ? new Subject(subject.getValue()) : null,
108                        audience != null ? new Audience(audience.getValue()) : null);
109        }
110        
111        
112        /**
113         * Returns the issuer.
114         *
115         * @return The issuer.
116         */
117        public Issuer getIssuer() {
118                return issuer;
119        }
120        
121        
122        /**
123         * Returns the issuer entity ID.
124         *
125         * @return The issuer entity ID.
126         */
127        public EntityID getIssuerEntityID() {
128                return new EntityID(getIssuer().getValue());
129        }
130        
131        
132        /**
133         * Returns the optional subject.
134         *
135         * @return The subject, {@code null} if not specified.
136         */
137        public Subject getSubject() {
138                return subject;
139        }
140        
141        
142        /**
143         * Returns the optional subject entity ID.
144         *
145         * @return The subject entity ID, {@code null} if not specified.
146         */
147        public EntityID getSubjectEntityID() {
148                return getSubject() != null ? new EntityID(getSubject().getValue()) : null;
149        }
150        
151        
152        /**
153         * Returns the optional audience (requester).
154         *
155         * @return The audience, {@code null} if not specified.
156         */
157        public Audience getAudience() {
158                return audience;
159        }
160        
161        
162        /**
163         * Returns the optional audience (requester) entity ID .
164         *
165         * @return The audience entity ID, {@code null} if not specified.
166         */
167        public EntityID getAudienceEntityID() {
168                return getAudience() != null ? new EntityID(getAudience().getValue()) : null;
169        }
170        
171        
172        @Override
173        public Map<String, List<String>> toParameters() {
174                
175                Map<String, List<String>> params = new HashMap<>();
176                params.put("iss", Collections.singletonList(getIssuer().getValue()));
177                if (getSubject() != null) {
178                        params.put("sub", Collections.singletonList(getSubject().getValue()));
179                }
180                if (getAudience() != null) {
181                        params.put("aud", Collections.singletonList(getAudience().getValue()));
182                }
183                return params;
184        }
185        
186        
187        /**
188         * Parses a fetch entity statement request from the specified query
189         * string parameters.
190         *
191         * @param params The query string parameters. Must not be {@code null}.
192         *
193         * @return The fetch entity statement request.
194         *
195         * @throws ParseException If parsing failed.
196         */
197        public static FetchEntityStatementRequest parse(final Map<String, List<String>> params)
198                throws ParseException {
199                
200                String value = MultivaluedMapUtils.getFirstValue(params, "operation");
201                
202                if (value != null && ! value.equalsIgnoreCase(OperationType.FETCH.getValue())) {
203                        throw new ParseException("The operation type must be fetch or unspecified");
204                }
205                
206                value = MultivaluedMapUtils.getFirstValue(params, "iss");
207                if (value == null) {
208                        throw new ParseException("Missing iss (issuer) parameter");
209                }
210                Issuer issuer = new Issuer(value);
211                
212                value = MultivaluedMapUtils.getFirstValue(params, "sub");
213                Subject subject = null;
214                if (value != null) {
215                        subject = new Subject(value);
216                }
217                
218                value = MultivaluedMapUtils.getFirstValue(params, "aud");
219                Audience audience = null;
220                if (value != null) {
221                        audience = new Audience(value);
222                }
223                
224                return new FetchEntityStatementRequest(null, issuer, subject, audience);
225        }
226        
227        
228        /**
229         * Parses a fetch entity statement request from the specified HTTP
230         * request.
231         *
232         * @param httpRequest The HTTP request. Must not be {@code null}.
233         *
234         * @return The fetch entity statement request.
235         *
236         * @throws ParseException If parsing failed.
237         */
238        public static FetchEntityStatementRequest parse(final HTTPRequest httpRequest)
239                throws ParseException {
240                
241                httpRequest.ensureMethod(HTTPRequest.Method.GET);
242                FetchEntityStatementRequest request = parse(httpRequest.getQueryParameters());
243                return new FetchEntityStatementRequest(
244                        httpRequest.getURI(),
245                        request.getIssuer(),
246                        request.getSubject(),
247                        request.getAudience());
248        }
249}