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     */
043    @Immutable
044    public final class RefreshTokenRequest extends TokenRequest {
045    
046    
047            /**
048             * The refresh token.
049             */
050            private final RefreshToken refreshToken;
051            
052            
053            /**
054             * Creates a new unauthenticated refresh token request.
055             *
056             * @param refreshToken The refresh token. Must not be {@code null}.
057             */
058            public RefreshTokenRequest(final RefreshToken refreshToken) {
059            
060                    this(refreshToken, null);
061            }
062            
063             
064            /**
065             * Creates a new authenticated refresh token request.
066             *
067             * @param refreshToken The refresh token. Must not be {@code null}.
068             * @param clientAuth   The client authentication, {@code null} if none.
069             */
070            public RefreshTokenRequest(final RefreshToken refreshToken, 
071                                       final ClientAuthentication clientAuth) {
072            
073                    super(GrantType.REFRESH_TOKEN, clientAuth);
074                    
075                    if (refreshToken == null)
076                            throw new IllegalArgumentException("The refresh token must not be null");
077                    
078                    this.refreshToken = refreshToken;
079            }
080            
081            
082            /**
083             * Gets the refresh token.
084             *
085             * @return The refresh token.
086             */
087            public RefreshToken getRefreshToken() {
088            
089                    return refreshToken;
090            }
091            
092            
093            @Override
094            public HTTPRequest toHTTPRequest(final URL url)
095                    throws SerializeException {
096                    
097                    HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.POST, url);
098                    
099                    httpRequest.setContentType(CommonContentTypes.APPLICATION_URLENCODED);
100                    
101                    Map<String,String> params = new LinkedHashMap<String,String>();
102                    params.put("grant_type", getGrantType().toString());
103                    params.put("refresh_token", refreshToken.getValue());
104                    
105                    httpRequest.setQuery(URLUtils.serializeParameters(params));
106                    
107                    if (getClientAuthentication() != null)
108                            getClientAuthentication().applyTo(httpRequest);
109                    
110                    return httpRequest;
111            }
112            
113            
114            /**
115             * Parses the specified HTTP request for a refresh token request.
116             *
117             * @param httpRequest The HTTP request. Must not be {@code null}.
118             *
119             * @return The refresh token request.
120             *
121             * @throws ParseException If the HTTP request couldn't be parsed to a 
122             *                        refresh token request.
123             */
124            public static RefreshTokenRequest parse(final HTTPRequest httpRequest)
125                    throws ParseException {
126                    
127                    // Only HTTP POST accepted
128                    httpRequest.ensureMethod(HTTPRequest.Method.POST);
129                    httpRequest.ensureContentType(CommonContentTypes.APPLICATION_URLENCODED);
130                    
131                    // No fragment!
132                    // May use query component!
133                    
134                    Map<String,String> params = httpRequest.getQueryParameters();
135                    
136                    
137                    // Parse grant type
138                    String grantTypeString = params.get("grant_type");
139                    
140                    if (grantTypeString == null)
141                            throw new ParseException("Missing \"grant_type\" parameter");
142    
143                    GrantType grantType = new GrantType(grantTypeString);
144                            
145                    if (! grantType.equals(GrantType.REFRESH_TOKEN))
146                            throw new ParseException("Invalid \"grant_type\" parameter: " + grantTypeString);
147                    
148                    
149                    // Parse refresh token
150                    String tokenString = params.get("refresh_token");
151                    
152                    if (tokenString == null)
153                            throw new ParseException("Missing \"refresh_token\" parameter");
154                    
155                    // Parse client authentication
156                    ClientAuthentication clientAuth = ClientAuthentication.parse(httpRequest);
157                    
158                    return new RefreshTokenRequest(new RefreshToken(tokenString), clientAuth);
159            }
160    }