001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2016, 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.id;
019
020
021import java.io.IOException;
022import java.net.URI;
023import java.util.List;
024import java.util.Set;
025
026import com.nimbusds.jose.util.Resource;
027import com.nimbusds.jose.util.ResourceRetriever;
028import com.nimbusds.oauth2.sdk.GeneralException;
029import com.nimbusds.oauth2.sdk.util.JSONArrayUtils;
030
031
032/**
033 * Sector identifier URI validator.
034 *
035 * <p>Related specifications:
036 *
037 * <ul>
038 *     <li>OpenID Connect Core 1.0, section 8.1.
039 *     <li>OpenID Connect Dynamic Client Registration 1.0, section 5.
040 * </ul>
041 */
042public class SectorIDURIValidator {
043        
044
045        /**
046         * The URL resource retriever.
047         */
048        private final ResourceRetriever resourceRetriever;
049
050
051        /**
052         * Creates a new sector identifier URI validator.
053         *
054         * @param resourceRetriever The URL resource retriever to use. Must not
055         *                          be {@code null}.
056         */
057        public SectorIDURIValidator(final ResourceRetriever resourceRetriever) {
058                if (resourceRetriever == null) {
059                        throw new IllegalArgumentException("The resource retriever must not be null");
060                }
061                this.resourceRetriever = resourceRetriever;
062        }
063
064
065        /**
066         * Returns the URL resource retriever.
067         *
068         * @return The resource retriever.
069         */
070        public ResourceRetriever getResourceRetriever() {
071                return resourceRetriever;
072        }
073
074
075        /**
076         * Validates the specified sector identifier URI by ensuring it lists
077         * all specified redirection URIs.
078         *
079         *
080         * @param sectorURI    The sector identifier URI. Must not be
081         *                     {@code null}.
082         * @param redirectURIs The redirection URIs of the client. Must not be
083         *                     {@code null}.
084         *
085         * @throws GeneralException If validation failed.
086         */
087        public void validate(final URI sectorURI, final Set<URI> redirectURIs)
088                throws GeneralException {
089
090                Resource resource;
091
092                try {
093                        resource = resourceRetriever.retrieveResource(sectorURI.toURL());
094                } catch (IOException e) {
095                        throw new GeneralException("Couldn't retrieve the sector ID JSON document: " + e.getMessage(), e);
096                }
097
098                if (resource.getContentType() == null) {
099                        throw new GeneralException("Couldn't validate sector ID URI: Missing Content-Type");
100                }
101
102                if (! resource.getContentType().toLowerCase().startsWith("application/json")) {
103                        throw new GeneralException("Couldn't validate sector ID URI: Content-Type must be application/json, found " + resource.getContentType());
104                }
105
106                List<URI> uriList = JSONArrayUtils.toURIList(JSONArrayUtils.parse(resource.getContent()));
107
108                for (URI uri: redirectURIs) {
109
110                        if (! uriList.contains(uri)) {
111                                throw new GeneralException("Sector ID URI validation failed: Redirect URI " + uri + " is missing from published JSON array at sector ID URI " + sectorURI);
112                        }
113                }
114        }
115}