mradul
mradul

Reputation: 560

Get access token from Oauth2 rest api using java

I need to call Oauth2 ResT API service to fetch the access token and expire_in values from the JSON file by it.

Below is a sample CURL which i need to call using JAVA i am beginner in JAVA so not able to figure out how to do it however i can do it using shell script.

curl -u 'ClientId:Clientaccesskey' https://oauth2.url/oauth/token -X POST -d 'response_type=token&client_id=ClientId&username=user&password=userpassword&scope=process&grant_type=password'

Sample JSON retured by above curl command --

{"access_token":"accessTokentobefetched","token_type":"bearer","refresh_token":"refreshToken","expires_in":7199,"scope":"process","jti":"somehexadecimalvaliu"}

In shell script we can fetch the value of access token and other fields using AWK command and other commands.

So i need to call this CURL command in JAVA and fetch the value of access token and other keys from the JSON file.

Any help which can help me start with this is welcome as i am new to JAVA and learning.

Upvotes: 2

Views: 26726

Answers (3)

Andreas Lorenzen
Andreas Lorenzen

Reputation: 4230

There are quite a few libraries that you can use to help you make a regular HTTP POST request from Java, but since you seem to require to send plain text/plain body content - I suggest that you use okhttp3. This is a fairly lightweight and easy to work with HTTP client.

You will need to add the following dependency to your pom.xml, grabbed from https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp/4.7.2:

        <!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.7.2</version>
        </dependency>

If you are using gradle, just visit the before mentioned URL, and get the gradle equivalent dependency declaration.

And here's a complete class that illustrates how the okhttp3 client can be used to perform the POST request, and extract the return value. This example expects that you are using the spring-boot-starter-web dependency (this will include the jackson and tomcat libraries that are used in the example).

package com.example.demo;

import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Component
public class TokenRequester {

    public String getAccessToken() throws IOException {
        // Create a new HTTP client
        OkHttpClient client = new OkHttpClient().newBuilder().build();
        // Create the request body
        MediaType mediaType = MediaType.parse("text/plain");
        RequestBody body = RequestBody.create(mediaType, "response_type=token&client_id=ClientId&username=user&password=userpassword&scope=process&grant_type=password");
        // Build the request object, with method, headers
        Request request = new Request.Builder()
                .url("https://oauth2.url/oauth/token")
                .method("POST", body)
                .addHeader("Authorization", createAuthHeaderString("ClientId", "Clientaccesskey"))
                .addHeader("Content-Type", "text/plain")
                .build();
        // Perform the request, this potentially throws an IOException
        Response response = client.newCall(request).execute();
        // Read the body of the response into a hashmap
        Map<String,Object> responseMap = new ObjectMapper().
                readValue(response.body().byteStream(), HashMap.class);
        // Read the value of the "access_token" key from the hashmap 
        String accessToken = (String)responseMap.get("access_token");
        // Return the access_token value
        return accessToken;
    }

    // Just a helper metod to create the basic auth header
    private String createAuthHeaderString(String username, String password) {
        String auth = username + ":" + password;
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.US_ASCII));
        String authHeader = "Basic " + new String(encodedAuth);
        return authHeader;
    }
}

You may need to tweak a few things here. I could ask you to supply me the verbose output from the curl command, in order to be sure about the encoding - but give this one a try and see what you get?

Upvotes: 4

Ali Dahaghin
Ali Dahaghin

Reputation: 87

curl is a HTTP client. better solution is using HTTP client APIs for java to call endpoints. RestTemplate is common HTTP client comes with spring and it is your best choice.

Upvotes: 0

Andreas Lorenzen
Andreas Lorenzen

Reputation: 4230

Here's a solution that involves only Spring, using a RestTemplate for the POST request.

I found that when you use curl -X POST -d 'key=data', curl will add the header content-type: application/x-www-form-urlencoded, so the solution here will do the same.

This solution sets up the RestTemplate with the headers and body you have specified, and captures the response in an object equivalent to the one you have described.

The following solution consists of two files that you can try to introduce into your solution:

RestTemplateTokenRequester.java

package com.example.demo;

import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;

@Component
public class RestTemplateTokenRequester {

    public TokenResponse requestAccessToken() {
        // Create a RestTemplate to describe the request
        RestTemplate restTemplate = new RestTemplate();

        // Specify the http headers that we want to attach to the request
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Authorization", createAuthHeaderString("ClientId", "Clientaccesskey"));

        // Create a map of the key/value pairs that we want to supply in the body of the request
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("response_type","token");
        map.add("client_id","ClientId");
        map.add("username","user");
        map.add("password","userpassword");
        map.add("scope","process");
        map.add("grant_type","password");

        // Create an HttpEntity object, wrapping the body and headers of the request
        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);

        // Execute the request, as a POSt, and expecting a TokenResponse object in return
        ResponseEntity<TokenResponse> response =
                restTemplate.exchange("https://oauth2.url/oauth/token",
                        HttpMethod.POST,
                        entity,
                        TokenResponse.class);

        return response.getBody();
    }

    // Just a helper metod to create the basic auth header
    private String createAuthHeaderString(String username, String password) {
        String auth = username + ":" + password;
        byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.US_ASCII));
        String authHeader = "Basic " + new String(encodedAuth);
        return authHeader;
    }
}

TokenResponse.java

This is simply a POJO that is used by the jackson mapper, to capture the response in an object that you can easily read your result from.

package com.example.demo;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties(ignoreUnknown = true)
public class TokenResponse {
    @JsonProperty("access_token")
    private String accessToken;
    @JsonProperty("token_type")
    private String tokenType;
    @JsonProperty("refresh_token")
    private String refreshToken;
    @JsonProperty("expires_in")
    private Integer expiresIn;
    @JsonProperty("scope")
    private String scope;
    @JsonProperty("jti")
    private String jti;
}

I hope this solution will help you - I would prefer it over the other solution I have suggested with okhttp3.

Upvotes: 4

Related Questions