001package com.nimbusds.oauth2.sdk;
002
003
004import java.net.URL;
005import java.util.Map;
006
007import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
008import com.nimbusds.oauth2.sdk.http.CommonContentTypes;
009import com.nimbusds.oauth2.sdk.http.HTTPRequest;
010
011
012/**
013 * The base abstract class for access token and refresh token requests to the
014 * Token endpoint. The request type can be inferred by calling 
015 * {@link #getGrantType}.
016 *
017 * <p>Example access token request:
018 *
019 * <pre>
020 * POST /token HTTP/1.1
021 * Host: server.example.com
022 * Content-Type: application/x-www-form-urlencoded
023 * Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
024 * 
025 * grant_type=authorization_code
026 * &amp;code=SplxlOBeZQQYbYS6WxSbIA
027 * &amp;redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
028 * </pre>
029 *
030 * <p>Related specifications:
031 *
032 * <ul>
033 *     <li>OAuth 2.0 (RFC 6749), sections 4.1.3, .
034 * </ul>
035 *
036 * @author Vladimir Dzhuvinov
037 */
038public abstract class TokenRequest extends AbstractRequest {
039
040
041        /**
042         * The grant type.
043         */
044        private final GrantType grantType;
045        
046        
047        /**
048         * The client authentication, {@code null} if none.
049         */
050        private final ClientAuthentication clientAuth;
051        
052        
053        /**
054         * Creates a new token request.
055         *
056         * @param uri        The URI of the token endpoint. May be 
057         *                   {@code null} if the {@link #toHTTPRequest()}
058         *                   method will not be used.
059         * @param grantType  The grant type. Must not be {@code null}.
060         * @param clientAuth The client authentication, {@code null} if none.
061         */
062        protected TokenRequest(final URL uri, 
063                               final GrantType grantType, 
064                               final ClientAuthentication clientAuth) {
065        
066                super(uri);
067                
068                if (grantType == null)
069                        throw new IllegalArgumentException("The grant type must not be null");
070                
071                this.grantType = grantType;
072                
073                this.clientAuth = clientAuth;
074        }
075        
076        
077        /**
078         * Gets the grant type.
079         *
080         * @return The grant type.
081         */
082        public GrantType getGrantType() {
083        
084                return grantType;
085        }
086        
087        
088        /**
089         * Gets the client authentication.
090         *
091         * @return The client authentication, {@code null} if none.
092         */
093        public ClientAuthentication getClientAuthentication() {
094        
095                return clientAuth;
096        }
097        
098        
099        /**
100         * Parses the specified HTTP request for a token request.
101         *
102         * @param httpRequest The HTTP request. Must not be {@code null}.
103         *
104         * @return The token request.
105         *
106         * @throws ParseException If the HTTP request couldn't be parsed to a 
107         *                        token request.
108         */
109        public static TokenRequest parse(final HTTPRequest httpRequest)
110                throws ParseException {
111                
112                // Only HTTP POST accepted
113                httpRequest.ensureMethod(HTTPRequest.Method.POST);
114                httpRequest.ensureContentType(CommonContentTypes.APPLICATION_URLENCODED);
115                
116                // No fragment!
117                // May use query component!
118                Map<String,String> params = httpRequest.getQueryParameters();
119                
120                
121                // Parse grant type
122                final String grantTypeString = params.get("grant_type");
123                
124                if (grantTypeString == null)
125                        throw new ParseException("Missing \"grant_type\" parameter");
126                
127                GrantType grantType = new GrantType(grantTypeString);
128                
129                if (grantType.equals(GrantType.AUTHORIZATION_CODE))
130                        return AccessTokenRequest.parse(httpRequest);
131
132                else if (grantType.equals(GrantType.REFRESH_TOKEN))
133                        return RefreshTokenRequest.parse(httpRequest);
134                
135                else
136                        throw new ParseException("Unsupported \"grant_type\": " + grantType);
137        }
138}