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.registration;
019
020
021import java.net.URI;
022import java.net.URISyntaxException;
023
024import net.jcip.annotations.Immutable;
025
026import com.nimbusds.common.contenttype.ContentType;
027import com.nimbusds.jwt.SignedJWT;
028import com.nimbusds.oauth2.sdk.AbstractRequest;
029import com.nimbusds.oauth2.sdk.ParseException;
030import com.nimbusds.oauth2.sdk.SerializeException;
031import com.nimbusds.oauth2.sdk.http.HTTPRequest;
032import com.nimbusds.oauth2.sdk.util.StringUtils;
033import com.nimbusds.openid.connect.sdk.federation.entities.EntityStatement;
034
035
036/**
037 * Explicit client registration request for a federation entity.
038 *
039 * <p>Related specifications:
040 *
041 * <ul>
042 *     <li>OpenID Connect Federation 1.0, section 9.2.
043 * </ul>
044 */
045@Immutable
046public class ExplicitClientRegistrationRequest extends AbstractRequest {
047        
048        
049        /**
050         * The entity statement.
051         */
052        private final EntityStatement entityStatement;
053        
054        
055        /**
056         * Creates a new explicit client registration request for a federation
057         * entity.
058         *
059         * @param uri             The URI of the federation registration
060         *                        endpoint. May be {@code null} if the
061         *                        {@link #toHTTPRequest} method will not be
062         *                        used.
063         * @param entityStatement The entity statement of the client. Must not
064         *                        be {@code null}.
065         */
066        public ExplicitClientRegistrationRequest(final URI uri, final EntityStatement entityStatement) {
067                super(uri);
068                this.entityStatement = entityStatement;
069        }
070        
071        
072        /**
073         * Returns the entity statement.
074         *
075         * @return The entity statement.
076         */
077        public EntityStatement getEntityStatement() {
078                return entityStatement;
079        }
080        
081        
082        @Override
083        public HTTPRequest toHTTPRequest() {
084                
085                if (getEndpointURI() == null) {
086                        throw new SerializeException("The endpoint URI is not specified");
087                }
088                
089                HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.POST, getEndpointURI());
090                httpRequest.setEntityContentType(ContentType.APPLICATION_JOSE);
091                httpRequest.setQuery(getEntityStatement().getSignedStatement().serialize());
092                return httpRequest;
093        }
094        
095        
096        /**
097         * Parses an explicit client registration request from the specified
098         * HTTP request.
099         *
100         * @param httpRequest The HTTP request. Must not be {@code null}.
101         *
102         * @return The explicit client registration request.
103         *
104         * @throws ParseException If the HTTP request couldn't be parsed to an
105         *                        explicit client registration request.
106         */
107        public static ExplicitClientRegistrationRequest parse(final HTTPRequest httpRequest)
108                throws ParseException {
109                
110                // Only HTTP POST accepted
111                URI uri;
112                try {
113                        uri = httpRequest.getURL().toURI();
114                } catch (URISyntaxException e) {
115                        throw new ParseException(e.getMessage(), e);
116                }
117                
118                httpRequest.ensureMethod(HTTPRequest.Method.POST);
119                httpRequest.ensureEntityContentType(ContentType.APPLICATION_JOSE);
120                
121                String jwtString = httpRequest.getQuery();
122                if (StringUtils.isBlank(jwtString)) {
123                        throw new ParseException("Missing entity body");
124                }
125                
126                SignedJWT signedJWT;
127                try {
128                        signedJWT = SignedJWT.parse(jwtString);
129                } catch (java.text.ParseException e) {
130                        throw new ParseException("Invalid entity statement: " + e.getMessage(), e);
131                }
132                
133                return new ExplicitClientRegistrationRequest(uri, EntityStatement.parse(signedJWT));
134        }
135}