001    package com.nimbusds.oauth2.sdk;
002    
003    
004    import java.net.URL;
005    import java.util.LinkedHashMap;
006    import java.util.Map;
007    
008    import net.jcip.annotations.Immutable;
009    
010    import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
011    import com.nimbusds.oauth2.sdk.token.RefreshToken;
012    import com.nimbusds.oauth2.sdk.http.CommonContentTypes;
013    import com.nimbusds.oauth2.sdk.http.HTTPRequest;
014    import com.nimbusds.oauth2.sdk.util.URLUtils;
015    
016    
017    /**
018     * Refresh token request to the Token endpoint. Used to refresh an 
019     * {@link com.nimbusds.oauth2.sdk.token.AccessToken access token}. This class 
020     * is immutable.
021     *
022     * <p>Note that the optional scope parameter is not supported.
023     *
024     * <p>Example refresh token request:
025     *
026     * <pre>
027     * POST /token HTTP/1.1
028     * Host: server.example.com
029     * Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
030     * Content-Type: application/x-www-form-urlencoded;charset=UTF-8
031     *
032     * grant_type=refresh_token&amp;refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
033     * </pre>
034     *
035     * <p>Related specifications:
036     *
037     * <ul>
038     *     <li>OAuth 2.0 (RFC 6749), section 6.
039     * </ul>
040     *
041     * @author Vladimir Dzhuvinov
042     * @version $version$ (2013-05-10)
043     */
044    @Immutable
045    public final class RefreshTokenRequest extends TokenRequest {
046    
047    
048            /**
049             * The refresh token.
050             */
051            private final RefreshToken refreshToken;
052            
053            
054            /**
055             * Creates a new unauthenticated refresh token request.
056             *
057             * @param refreshToken The refresh token. Must not be {@code null}.
058             */
059            public RefreshTokenRequest(final RefreshToken refreshToken) {
060            
061                    this(refreshToken, null);
062            }
063            
064             
065            /**
066             * Creates a new authenticated refresh token request.
067             *
068             * @param refreshToken The refresh token. Must not be {@code null}.
069             * @param clientAuth   The client authentication, {@code null} if none.
070             */
071            public RefreshTokenRequest(final RefreshToken refreshToken, 
072                                       final ClientAuthentication clientAuth) {
073            
074                    super(GrantType.REFRESH_TOKEN, clientAuth);
075                    
076                    if (refreshToken == null)
077                            throw new IllegalArgumentException("The refresh token must not be null");
078                    
079                    this.refreshToken = refreshToken;
080            }
081            
082            
083            /**
084             * Gets the refresh token.
085             *
086             * @return The refresh token.
087             */
088            public RefreshToken getRefreshToken() {
089            
090                    return refreshToken;
091            }
092            
093            
094            @Override
095            public HTTPRequest toHTTPRequest(final URL url)
096                    throws SerializeException {
097                    
098                    HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.POST, url);
099                    
100                    httpRequest.setContentType(CommonContentTypes.APPLICATION_URLENCODED);
101                    
102                    Map<String,String> params = new LinkedHashMap<String,String>();
103                    params.put("grant_type", getGrantType().toString());
104                    params.put("refresh_token", refreshToken.getValue());
105                    
106                    httpRequest.setQuery(URLUtils.serializeParameters(params));
107                    
108                    if (getClientAuthentication() != null)
109                            getClientAuthentication().applyTo(httpRequest);
110                    
111                    return httpRequest;
112            }
113            
114            
115            /**
116             * Parses the specified HTTP request for a refresh token request.
117             *
118             * @param httpRequest The HTTP request. Must not be {@code null}.
119             *
120             * @return The refresh token request.
121             *
122             * @throws ParseException If the HTTP request couldn't be parsed to a 
123             *                        refresh token request.
124             */
125            public static RefreshTokenRequest parse(final HTTPRequest httpRequest)
126                    throws ParseException {
127                    
128                    // Only HTTP POST accepted
129                    httpRequest.ensureMethod(HTTPRequest.Method.POST);
130                    httpRequest.ensureContentType(CommonContentTypes.APPLICATION_URLENCODED);
131                    
132                    // No fragment!
133                    // May use query component!
134                    
135                    Map<String,String> params = httpRequest.getQueryParameters();
136                    
137                    
138                    // Parse grant type
139                    String grantTypeString = params.get("grant_type");
140                    
141                    if (grantTypeString == null)
142                            throw new ParseException("Missing \"grant_type\" parameter");
143    
144                    GrantType grantType = new GrantType(grantTypeString);
145                            
146                    if (! grantType.equals(GrantType.REFRESH_TOKEN))
147                            throw new ParseException("Invalid \"grant_type\" parameter: " + grantTypeString);
148                    
149                    
150                    // Parse refresh token
151                    String tokenString = params.get("refresh_token");
152                    
153                    if (tokenString == null)
154                            throw new ParseException("Missing \"refresh_token\" parameter");
155                    
156                    // Parse client authentication
157                    ClientAuthentication clientAuth = ClientAuthentication.parse(httpRequest);
158                    
159                    return new RefreshTokenRequest(new RefreshToken(tokenString), clientAuth);
160            }
161    }