001package com.nimbusds.oauth2.sdk; 002 003 004import java.net.MalformedURLException; 005import java.net.URI; 006import java.net.URISyntaxException; 007import java.net.URL; 008import java.util.Map; 009 010import net.jcip.annotations.Immutable; 011 012import com.nimbusds.oauth2.sdk.auth.ClientAuthentication; 013import com.nimbusds.oauth2.sdk.http.CommonContentTypes; 014import com.nimbusds.oauth2.sdk.http.HTTPRequest; 015import com.nimbusds.oauth2.sdk.util.URLUtils; 016 017 018/** 019 * Token request. Used to obtain an 020 * {@link com.nimbusds.oauth2.sdk.token.AccessToken access token} and an 021 * optional {@link com.nimbusds.oauth2.sdk.token.RefreshToken refresh token} 022 * at the Token endpoint of the authorisation server. 023 * 024 * <p>Example token request with an authorisation code grant: 025 * 026 * <pre> 027 * POST /token HTTP/1.1 028 * Host: server.example.com 029 * Content-Type: application/x-www-form-URIencoded 030 * Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW 031 * 032 * grant_type=authorization_code 033 * &code=SplxlOBeZQQYbYS6WxSbIA 034 * &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb 035 * </pre> 036 * 037 * <p>Related specifications: 038 * 039 * <ul> 040 * <li>OAuth 2.0 (RFC 6749), sections 4.1.3, 4.3.2, 4.4.2 and 6. 041 * </ul> 042 */ 043@Immutable 044public class TokenRequest extends AbstractRequest { 045 046 047 /** 048 * The client authentication, {@code null} if none. 049 */ 050 private final ClientAuthentication clientAuth; 051 052 053 /** 054 * The authorisation grant. 055 */ 056 private final AuthorizationGrant authzGrant; 057 058 059 /** 060 * Creates a new token request. 061 * 062 * @param uri The URI of the token endpoint. May be 063 * {@code null} if the {@link #toHTTPRequest} method 064 * will not be used. 065 * @param clientAuth The client authentication, {@code null} if none. 066 * @param authzGrant The authorisation grant. Must not be {@code null}. 067 */ 068 public TokenRequest(final URI uri, 069 final ClientAuthentication clientAuth, 070 final AuthorizationGrant authzGrant) { 071 072 super(uri); 073 074 this.clientAuth = clientAuth; 075 076 if (authzGrant == null) 077 throw new IllegalArgumentException("The authorization grant must not be null"); 078 079 this.authzGrant = authzGrant; 080 } 081 082 083 /** 084 * Gets the client authentication. 085 * 086 * @return The client authentication, {@code null} if none. 087 */ 088 public ClientAuthentication getClientAuthentication() { 089 090 return clientAuth; 091 } 092 093 094 /** 095 * Gets the authorisation grant. 096 * 097 * @return The authorisation grant. 098 */ 099 public AuthorizationGrant getAuthorizationGrant() { 100 101 return authzGrant; 102 } 103 104 105 @Override 106 public HTTPRequest toHTTPRequest() 107 throws SerializeException { 108 109 if (getEndpointURI() == null) 110 throw new SerializeException("The endpoint URI is not specified"); 111 112 URL url; 113 114 try { 115 url = getEndpointURI().toURL(); 116 117 } catch (MalformedURLException e) { 118 119 throw new SerializeException(e.getMessage(), e); 120 } 121 122 HTTPRequest httpRequest = new HTTPRequest(HTTPRequest.Method.POST, url); 123 httpRequest.setContentType(CommonContentTypes.APPLICATION_URLENCODED); 124 125 Map<String,String> params = authzGrant.toParameters(); 126 127 httpRequest.setQuery(URLUtils.serializeParameters(params)); 128 129 if (getClientAuthentication() != null) 130 getClientAuthentication().applyTo(httpRequest); 131 132 return httpRequest; 133 } 134 135 136 /** 137 * Parses the specified HTTP request for a token request. 138 * 139 * @param httpRequest The HTTP request. Must not be {@code null}. 140 * 141 * @return The token request. 142 * 143 * @throws ParseException If the HTTP request couldn't be parsed to a 144 * token request. 145 */ 146 public static TokenRequest parse(final HTTPRequest httpRequest) 147 throws ParseException { 148 149 // Only HTTP POST accepted 150 httpRequest.ensureMethod(HTTPRequest.Method.POST); 151 httpRequest.ensureContentType(CommonContentTypes.APPLICATION_URLENCODED); 152 153 // No fragment! 154 // May use query component! 155 Map<String,String> params = httpRequest.getQueryParameters(); 156 157 // Parse grant 158 AuthorizationGrant authzGrant = AuthorizationGrant.parse(params); 159 160 // Parse client auth 161 ClientAuthentication clientAuth = ClientAuthentication.parse(httpRequest); 162 163 URI uri; 164 165 try { 166 uri = httpRequest.getURL().toURI(); 167 168 } catch (URISyntaxException e) { 169 170 throw new ParseException(e.getMessage(), e); 171 } 172 173 return new TokenRequest(uri, clientAuth, authzGrant); 174 } 175}