Sample (Java) for OAuth 2.0 authentication and access token acquisition

Sample code to authenticate with OAuth 2.0 and get an access token. The settings on the authentication server side are not described this time.

Mechanism (super overview)

(1) Obtain the client ID and secret key issued in advance on the authentication server side ② Request to authentication endpoint (URL access) ③ Authenticate (enter user ID and password) ④ A request comes to the callback page by redirect ⑤ If the authentication is successful, you can get the authorization code from the query parameters etc. ⑥ Send the authorization code, client ID, and secret key to the token endpoint (POST, etc.) ⑦ Get access token (and refresh token) ⑧ After that, as soon as you throw the API, you can get an ID token and SSO freely.

environment

I verified using OpenAM for the authentication server (I will not touch on the settings around here). The client side used google's oauth-client. Also, I use spark-framework to try it easily.

pom.xml


        <dependency>
          <groupId>com.sparkjava</groupId>
          <artifactId>spark-core</artifactId>
          <version>2.7.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.oauth-client</groupId>
            <artifactId>google-oauth-client</artifactId>
            <version>1.23.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.http-client</groupId>
            <artifactId>google-http-client-jackson2</artifactId>
            <version>1.23.0</version>
        </dependency>

Implementation sample

MyOAuthServiceProviderSample.java


import java.util.Arrays;
import spark.Request;
import spark.Response;
import spark.Route;
import static spark.Spark.*;
import com.google.api.client.auth.oauth2.AuthorizationCodeRequestUrl;
import com.google.api.client.auth.oauth2.AuthorizationCodeTokenRequest;
import com.google.api.client.auth.oauth2.TokenResponse;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import java.io.IOException;

/**
 * OAuth2.Authenticate with 0 and get an access token
 * @author owl
 */
public class MyOAuthServiceProviderSample {
 
    public static void main(String[] args) {

        /**
         *① Authentication request
         */
        get("/auth", new Route() {
            @Override
            public Object handle(Request req, Response resp) throws Exception {
               
                /**
                 *Specify the authentication endpoint and client ID
                 *This time, we will use the authentication server built with OpenAM.
                 */
                AuthorizationCodeRequestUrl codeUrl = new AuthorizationCodeRequestUrl("http://www1.openamexam.co.jp:18080/openam/oauth2/authorize?", "oauth_client_key");

                codeUrl.setScopes(Arrays.asList("openid profile email"));       //Specify the information you want to get
                codeUrl.setResponseTypes(Arrays.asList("code"));                //Get a permit code
                codeUrl.setRedirectUri("http://localhost:4567/callback");       //Specify CallBackUrl
                codeUrl.setState("this_is_test_state_code");                    //Specify the state code, for CSRF measures
                codeUrl.set("nonce", "this_is_one_time_phrase");                //Specify nonce, for replay attack countermeasures
                codeUrl.set("access_type", "offline");                          //Request a refresh token
                codeUrl.set("realm", "/api");                                   //Specify realm
                
                resp.redirect(codeUrl.build());                                 //Skip to the authentication endpoint
                
                return null;
            }
        });

        /**
         *② Acquisition of access token
         * --When the authentication endpoint is authenticated, a redirect will call you back.
         */
        get("/callback", new Route() {
            @Override
            public Object handle(Request req, Response resp) throws Exception {
                
                /**
                 *Request an access token from the authorization code
                 *This area also depends on the settings of the authentication server. This time, it is set so that it can be obtained with QueryString.
                 */
                String allowCode = req.queryParams("code");                     //Get permission code
                //Get state code
                //Here you should check if the value is the same as when requested (this time omitted)
                String stateCode = req.queryParams("state");                    
                
                /**
                 *Make an access token acquisition request with the authorization code
                 *This area also depends on the settings of the authentication server. This time send the secret key by POST method
                 */
                AuthorizationCodeTokenRequest tokenUrl = new AuthorizationCodeTokenRequest(
                    new NetHttpTransport(),
                    new JacksonFactory(),
                    new GenericUrl("http://www1.openamexam.co.jp:18080/openam/oauth2/access_token?realm=/api"),
                    allowCode                        
                );

                tokenUrl.setGrantType("authorization_code");
                tokenUrl.setRedirectUri("http://localhost:4567/callback");      //If you do not specify your own URL again, an error will occur
                tokenUrl.set("client_id", "oauth_client_key");                  //Set client ID
                tokenUrl.set("client_secret", "oauth_secret_key");              //Set secret ID
                
                TokenResponse tr = null;
                String accessToken = null;
                String refreshToken = null;
                try {
                    tr = tokenUrl.execute();
                    accessToken = tr.getAccessToken();
                    refreshToken = tr.getRefreshToken() == null ? "null" : tr.getRefreshToken();
                    //It is also possible to make it SSO if you get idToken, analyze it, trust the information and log in to your own service
                    String idToken = (String)tr.get("id_token");
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    tr = null;
                }                
                
                return "AccessToken = " + accessToken
                        + "<br>RefreshToken = " + refreshToken;
            }
        });        
        
    }
    
}

Recommended Posts

Sample (Java) for OAuth 2.0 authentication and access token acquisition
Java: Timed token management class for Web API authentication
Java while and for statements
AWS SDK for Java 1.11.x and 2.x
Java for beginners, expressions and operators 1
Java for beginners, expressions and operators 2
Java 9 new features and sample code
BloomFilter description and implementation sample (JAVA)
Classes and instances Java for beginners
Relationship between kotlin and java access modifiers
[Java] for Each and sorted in Lambda
[For beginners] Difference between Java and Kotlin
Sample code collection for Azure Java development
[Java] Proxy for logging SQL and SQL results
Review notes for Java 1.7 and later file copies
Points for coexistence of devise and devise token auth
I studied for 3 weeks and passed Java Bronze
Kantai Collection Java # 1 Classes and Objects [For Beginners]
How to access Java Private methods and fields