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