001    package com.nimbusds.oauth2.sdk;
002    
003    
004    import java.util.Map;
005    
006    import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
007    
008    import com.nimbusds.oauth2.sdk.http.CommonContentTypes;
009    import 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     * @version $version$ (2013-01-30)
038     */
039    public abstract class TokenRequest implements Request {
040    
041    
042            /**
043             * The grant type.
044             */
045            private final GrantType grantType;
046            
047            
048            /**
049             * The client authentication, {@code null} if none.
050             */
051            private final ClientAuthentication clientAuth;
052            
053            
054            /**
055             * Creates a new token request.
056             *
057             * @param grantType  The grant type. Must not be {@code null}.
058             * @param clientAuth The client authentication, {@code null} if none.
059             */
060            protected TokenRequest(final GrantType grantType, final ClientAuthentication clientAuth) {
061            
062                    if (grantType == null)
063                            throw new IllegalArgumentException("The grant type must not be null");
064                    
065                    this.grantType = grantType;
066                    
067                    this.clientAuth = clientAuth;
068            }
069            
070            
071            /**
072             * Gets the grant type.
073             *
074             * @return The grant type.
075             */
076            public GrantType getGrantType() {
077            
078                    return grantType;
079            }
080            
081            
082            /**
083             * Gets the client authentication.
084             *
085             * @return The client authentication, {@code null} if none.
086             */
087            public ClientAuthentication getClientAuthentication() {
088            
089                    return clientAuth;
090            }
091            
092            
093            /**
094             * Parses the specified HTTP request for a token request.
095             *
096             * @param httpRequest The HTTP request. Must not be {@code null}.
097             *
098             * @return The token request.
099             *
100             * @throws ParseException If the HTTP request couldn't be parsed to a 
101             *                        token request.
102             */
103            public static TokenRequest parse(final HTTPRequest httpRequest)
104                    throws ParseException {
105                    
106                    // Only HTTP POST accepted
107                    httpRequest.ensureMethod(HTTPRequest.Method.POST);
108                    httpRequest.ensureContentType(CommonContentTypes.APPLICATION_URLENCODED);
109                    
110                    // No fragment!
111                    // May use query component!
112                    Map<String,String> params = httpRequest.getQueryParameters();
113                    
114                    
115                    // Parse grant type
116                    final String grantTypeString = params.get("grant_type");
117                    
118                    if (grantTypeString == null)
119                            throw new ParseException("Missing \"grant_type\" parameter");
120                    
121                    GrantType grantType = new GrantType(grantTypeString);
122                    
123                    if (grantType.equals(GrantType.AUTHORIZATION_CODE))
124                            return AccessTokenRequest.parse(httpRequest);
125    
126                    else if (grantType.equals(GrantType.REFRESH_TOKEN))
127                            return RefreshTokenRequest.parse(httpRequest);
128                    
129                    else
130                            throw new ParseException("Unsupported \"grant_type\": " + grantType);
131            }
132    }