I have created an app in the Google Developer's Console, then created OAuth2 credentials. I have a client_id and client_secret. Now, I want to use these to obtain an access token for two-legged calls into the Google Drive API. I am using Google's oauth2 client in java:
import com.google.api.client.auth.oauth2.ClientCredentialsTokenRequest;
import com.google.api.client.auth.oauth2.ClientParametersAuthentication;
import com.google.api.client.auth.oauth2.TokenResponse;
...
public void oauth2Test() {
String clientId = "...";
String clientSecret = "...";
ClientCredentialsTokenRequest request = new ClientCredentialsTokenRequest(
new NetHttpTransport(),
new JacksonFactory(),
new GenericUrl("https://accounts.google.com/o/oauth2/auth"));
request.setClientAuthentication(new ClientParametersAuthentication(clientId, clientSecret));
TokenResponse response;
try {
response = request.execute();
} catch (Exception ex) {
ex.printStackTrace();
}
}
However, I get a "400 Bad Request" with message
"Required parameter is missing: response_type".
What is the correct way to obtain an access token in the two-legged request model? Note: I only have the client_id and client_secret, I do not have the full API token.
EDIT: My original question was imprecise. While I prefer to start only with client_id and client_secret, that is not necessary. It is OK to use google-specific APIs to obtain access tokens and it is OK to use GoogleCredential. What is necessary is that I am able to use whatever access token(s) are obtained from the authorization process in a generic REST call. In other words, given google app credentials, which can be {client_id,client_secret}, or a google service account key in either JSON or P12 format, how do I obtain access token(s) and how are they used in the REST API call -- do I set the Authorization header or something else?
The first answer points out that client_credential isn't supported, which I've verified. But I still need a path to get the bearer token, so that I can use it in REST calls without specific Google client API libraries. So I started with code that works, but uses the Google libraries. It requires a JSON credential file.
InputStream is = getClass().getResourceAsStream("JSONCredFile");
GoogleCredential credential = GoogleCredential.fromStream(is).createScoped(scopes);
Drive service = new Drive.Builder(new NetHttpTransport(), new JacksonFactory(), credential)
.setApplicationName("My app")
.build();
FileList result = service.files().list().setPageSize(10)
.setFields("nextPageToken, files(id, name)")
.execute();
By hooking up an SSLSocket proxy to the credential (details omitted), I was able to trace the outbound communication:
POST /token HTTP/1.1
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.23.0 (gzip)
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Host: oauth2.googleapis.com
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 771
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=<lots of encoded stuff>
The reply is a gzip-encoded bearer token, which is used in the API call:
GET /drive/v3/files?fields=nextPageToken,%20files(id,%20name)&pageSize=10 HTTP/1.1
Accept-Encoding: gzip
Authorization: Bearer ya29.c.Eln_BSgrx0afa85mdMstW5jzEvM5dotWpctSXl-DE1jeO2mmu1h0FErr_EZO05YnC-B1yz30IBwOyFXoWr_wwKxlZk08R6eZldNU-EAfrQ1yNftymn_Qqc_pfg
Clearly this is the JWT profile of oauth2. But now what? Somehow I need to get the bearer token without actually making the API call through the specific library. The Google OAuth2 libraries don't seem to support this request type, at least I don't see a "JWT" flavor of TokenRequest. I can cook up the OAuth2 call directly, or create a subclass of TokenRequest that supports JWT?
Any better ideas?