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 com.nimbusds.oauth2.sdk.ParseException;
022import com.nimbusds.oauth2.sdk.http.HTTPRequest;
023import com.nimbusds.oauth2.sdk.id.Subject;
024import com.nimbusds.oauth2.sdk.util.MultivaluedMapUtils;
025import com.nimbusds.oauth2.sdk.util.StringUtils;
026import com.nimbusds.oauth2.sdk.util.URIUtils;
027import com.nimbusds.openid.connect.sdk.federation.entities.EntityID;
028import com.nimbusds.openid.connect.sdk.federation.entities.EntityType;
029import net.jcip.annotations.Immutable;
030
031import java.net.URI;
032import java.util.Collections;
033import java.util.LinkedHashMap;
034import java.util.List;
035import java.util.Map;
036
037
038/**
039 * Resolve entity statement request.
040 *
041 * <p>Related specifications:
042 *
043 * <ul>
044 *     <li>OpenID Connect Federation 1.0, section 7.2.1.
045 * </ul>
046 */
047@Immutable
048public class ResolveRequest extends FederationAPIRequest {
049        
050        
051        /**
052         * The subject.
053         */
054        private final Subject subject;
055        
056        
057        /**
058         * The trust anchor.
059         */
060        private final EntityID anchor;
061        
062        
063        /**
064         * The entity type to resolve.
065         */
066        private final EntityType entityType;
067        
068        
069        /**
070         * Creates a new resolve entity statement request.
071         *
072         * @param endpoint   The federation resolve endpoint. Must not be
073         *                   {@code null}.
074         * @param subject    The subject. Must not be {@code null}.
075         * @param anchor     The trust anchor. Must not be {@code null}.
076         * @param entityType The entity type to resolve, {@code null} if not
077         *                   specified.
078         */
079        public ResolveRequest(final URI endpoint,
080                              final Subject subject,
081                              final EntityID anchor,
082                              final EntityType entityType) {
083                
084                super(endpoint);
085                
086                if (subject == null) {
087                        throw new IllegalArgumentException("The subject must not be null");
088                }
089                this.subject = subject;
090                
091                if (anchor == null) {
092                        throw new IllegalArgumentException("The anchor must not be null");
093                }
094                this.anchor = anchor;
095                
096                this.entityType = entityType;
097        }
098        
099        
100        /**
101         * Returns the subject.
102         *
103         * @return The subject.
104         */
105        public Subject getSubject() {
106                return subject;
107        }
108        
109        
110        /**
111         * Returns the subject entity ID.
112         *
113         * @return The subject entity ID.
114         */
115        public EntityID getSubjectEntityID() {
116                return new EntityID(subject);
117        }
118        
119        
120        /**
121         * Returns the trust anchor.
122         *
123         * @return The trust anchor.
124         */
125        public EntityID getTrustAnchor() {
126                return anchor;
127        }
128        
129        
130        /**
131         * Returns the entity type to resolve.
132         *
133         * @return The entity type to resolve.
134         */
135        public EntityType getEntityType() {
136                return entityType;
137        }
138        
139        
140        @Override
141        public Map<String, List<String>> toParameters() {
142                Map<String, List<String>> params = new LinkedHashMap<>();
143                params.put("sub", Collections.singletonList(getSubject().getValue()));
144                params.put("anchor", Collections.singletonList(getTrustAnchor().getValue()));
145                if (getEntityType() != null) {
146                        params.put("type", Collections.singletonList(getEntityType().getValue()));
147                }
148                return params;
149        }
150        
151        
152        /**
153         * Parses a resolve entity statement request from the specified query
154         * string parameters.
155         *
156         * @param params The query string parameters. Must not be {@code null}.
157         *
158         * @return The resolve entity statement request.
159         *
160         * @throws ParseException If parsing failed.
161         */
162        public static ResolveRequest parse(final Map<String, List<String>> params)
163                throws ParseException {
164                
165                String value = MultivaluedMapUtils.getFirstValue(params, "sub");
166                if (StringUtils.isBlank(value)) {
167                        throw new ParseException("Missing sub");
168                }
169                Subject subject = new Subject(value);
170                
171                value = MultivaluedMapUtils.getFirstValue(params, "anchor");
172                if (StringUtils.isBlank(value)) {
173                        throw new ParseException("Missing anchor");
174                }
175                EntityID anchor = new EntityID(value);
176                
177                EntityType entityType = null;
178                value = MultivaluedMapUtils.getFirstValue(params, "type");
179                if (StringUtils.isNotBlank(value)) {
180                        entityType = new EntityType(value);
181                }
182                
183                return new ResolveRequest(null, subject, anchor, entityType);
184        }
185        
186        
187        /**
188         * Parses a resolve entity statement request from the specified HTTP
189         * request.
190         *
191         * @param httpRequest The HTTP request. Must not be {@code null}.
192         *
193         * @return The resolve entity statement request.
194         *
195         * @throws ParseException If parsing failed.
196         */
197        public static ResolveRequest parse(final HTTPRequest httpRequest)
198                throws ParseException {
199                
200                httpRequest.ensureMethod(HTTPRequest.Method.GET);
201                
202                ResolveRequest request = ResolveRequest.parse(httpRequest.getQueryStringParameters());
203                
204                return new ResolveRequest(
205                        URIUtils.getBaseURI(httpRequest.getURI()),
206                        request.getSubject(),
207                        request.getTrustAnchor(),
208                        request.getEntityType());
209        }
210}