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;
019
020
021import com.nimbusds.common.contenttype.ContentType;
022import com.nimbusds.oauth2.sdk.ParseException;
023import com.nimbusds.oauth2.sdk.ProtectedResourceRequest;
024import com.nimbusds.oauth2.sdk.SerializeException;
025import com.nimbusds.oauth2.sdk.http.HTTPRequest;
026import com.nimbusds.oauth2.sdk.token.AccessToken;
027import com.nimbusds.oauth2.sdk.util.URLUtils;
028import net.jcip.annotations.Immutable;
029
030import java.net.URI;
031import java.util.Collections;
032import java.util.HashMap;
033import java.util.List;
034import java.util.Map;
035
036
037/**
038 * UserInfo request. Used to retrieve the consented claims about the end-user.
039 *
040 * <p>Example HTTP GET request with a Bearer token:
041 *
042 * <pre>
043 * GET /userinfo HTTP/1.1
044 * Host: server.example.com
045 * Authorization: Bearer Eabeeduphee3aiviehahreacaoNg2thu
046 * </pre>
047 *
048 * <p>Example HTTP GET request with a DPoP token and proof:
049 *
050 * <pre>
051 * GET /userinfo HTTP/1.1
052 * Host: server.example.com
053 * Authorization: DPoP jo4kahphoh1ath4INaochohLeeshaiyo
054 * DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik...
055 * </pre>
056 *
057 * <p>Related specifications:
058 *
059 * <ul>
060 *     <li>OpenID Connect Core 1.0, section 5.3.1.
061 *     <li>OAuth 2.0 Bearer Token Usage (RFC6750), section 2.
062 *     <li>OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer
063 *         (DPoP) (RFC 9449), section 7.
064 * </ul>
065 */
066@Immutable
067public class UserInfoRequest extends ProtectedResourceRequest {
068
069
070        /**
071         * The HTTP method.
072         */
073        private final HTTPRequest.Method httpMethod;
074        
075        
076        /**
077         * Creates a new UserInfo HTTP GET request.
078         *
079         * @param uri         The URI of the UserInfo endpoint. May be
080         *                    {@code null} if the {@link #toHTTPRequest} method
081         *                    will not be used.
082         * @param accessToken An access token for the request. Must not be
083         *                    {@code null}.
084         */
085        public UserInfoRequest(final URI uri, final AccessToken accessToken) {
086        
087                this(uri, HTTPRequest.Method.GET, accessToken);
088        }
089        
090        
091        /**
092         * Creates a new UserInfo request.
093         *
094         * @param uri         The URI of the UserInfo endpoint. May be
095         *                    {@code null} if the {@link #toHTTPRequest} method
096         *                    will not be used.
097         * @param httpMethod  The HTTP method. Must be HTTP GET or POST and not 
098         *                    {@code null}.
099         * @param accessToken An access token for the request. Must not be
100         *                    {@code null}.
101         */
102        public UserInfoRequest(final URI uri, final HTTPRequest.Method httpMethod, final AccessToken accessToken) {
103        
104                super(uri, accessToken);
105                
106                if (httpMethod == null)
107                        throw new IllegalArgumentException("The HTTP method must not be null");
108                
109                this.httpMethod = httpMethod;
110                
111                
112                if (accessToken == null)
113                        throw new IllegalArgumentException("The access token must not be null");
114        }
115        
116        
117        /**
118         * Gets the HTTP method for this UserInfo request.
119         *
120         * @return The HTTP method.
121         */
122        public HTTPRequest.Method getMethod() {
123        
124                return httpMethod;
125        }
126        
127        
128        @Override
129        public HTTPRequest toHTTPRequest() {
130                
131                if (getEndpointURI() == null)
132                        throw new SerializeException("The endpoint URI is not specified");
133
134                HTTPRequest httpRequest = new HTTPRequest(httpMethod, getEndpointURI());
135                
136                switch (httpMethod) {
137                
138                        case GET:
139                                httpRequest.setAuthorization(getAccessToken().toAuthorizationHeader());
140                                break;
141                                
142                        case POST:
143                                httpRequest.setEntityContentType(ContentType.APPLICATION_URLENCODED);
144                                Map<String, List<String>> params = new HashMap<>();
145                                params.put("access_token", Collections.singletonList(getAccessToken().getValue()));
146                                httpRequest.setBody(URLUtils.serializeParameters(params));
147                                break;
148                        
149                        default:
150                                throw new SerializeException("Unexpected HTTP method: " + httpMethod);
151                }
152                
153                return httpRequest;
154        }
155        
156        
157        /**
158         * Parses the specified HTTP request for a UserInfo request.
159         *
160         * @param httpRequest The HTTP request. Must not be {@code null}.
161         *
162         * @return The UserInfo request.
163         *
164         * @throws ParseException If the HTTP request couldn't be parsed to a 
165         *                        UserInfo request.
166         */
167        public static UserInfoRequest parse(final HTTPRequest httpRequest)
168                throws ParseException {
169                
170                return new UserInfoRequest(
171                        httpRequest.getURI(),
172                        httpRequest.getMethod(),
173                        AccessToken.parse(httpRequest)
174                );
175        }
176}