LoginSignup
12
25

More than 5 years have passed since last update.

OAuth2.0の認証とアクセストークン取得までのサンプル(Java)

Posted at

OAuth2.0で認証してアクセストークンを取得するまでのサンプルコード。
認証サーバ側の設定等は今回は記載していない。

仕組(超概要)

① 事前に認証サーバ側で発行したクライアントIDとシークレットKeyを取得
② 認証エンドポイントへリクエスト(URLアクセス)
③ 認証を行う(ユーザIDとパスワードの入力)
④ リダイレクトでコールバックページにリクエストが来る
⑤ 認証が成功していれば許可コードがクエリパラメタ等で貰える
⑥ 許可コードとクライアントID、シークレットKeyをトークンエンドポイントに送信(POST等)
⑦ アクセストークン(とリフレッシュトークン)を取得
⑧ あとはAPIを投げるなり、IDトークンも貰ってSSOするとかご自由に

環境

認証サーバにはOpenAMを使って検証した(このあたりの設定は今回は触れない)。
クライアント側はgoogleのoauth-clientを利用した。
あと、簡単に試すためspark-frameworkを利用している。

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>

実装サンプル

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.0で認証を行いアクセストークンを取得
 * @author owl
 */
public class MyOAuthServiceProviderSample {

    public static void main(String[] args) {

        /**
         * ① 認証要求
         */
        get("/auth", new Route() {
            @Override
            public Object handle(Request req, Response resp) throws Exception {

                /**
                 * 認証エンドポイントと、クライアントIDを指定
                 * 今回はOpenAMで構築した認証サーバを利用
                 */
                AuthorizationCodeRequestUrl codeUrl = new AuthorizationCodeRequestUrl("http://www1.openamexam.co.jp:18080/openam/oauth2/authorize?", "oauth_client_key");

                codeUrl.setScopes(Arrays.asList("openid profile email"));       // 取得したい情報を指定
                codeUrl.setResponseTypes(Arrays.asList("code"));                // 許可コードをもらう
                codeUrl.setRedirectUri("http://localhost:4567/callback");       // CallBackUrlを指定
                codeUrl.setState("this_is_test_state_code");                    // ステートコードを指定、CSRF対策用
                codeUrl.set("nonce", "this_is_one_time_phrase");                // nonceを指定、リプレイアタック対策用
                codeUrl.set("access_type", "offline");                          // リフレッシュトークンを要求する
                codeUrl.set("realm", "/api");                                   // realmを指定

                resp.redirect(codeUrl.build());                                 // 認証エンドポイントに飛ばす

                return null;
            }
        });

        /**
         * ② アクセストークンの取得
         * -- 認証エンドポイントで認証が行われると、リダイレクトでこちらにCallBackしてくる
         */
        get("/callback", new Route() {
            @Override
            public Object handle(Request req, Response resp) throws Exception {

                /**
                 * 許可コードからアクセストークンを要求
                 * この辺は認証サーバの設定にも依存する。今回はQueryStringで取得できるように設定している。
                 */
                String allowCode = req.queryParams("code");                     // 許可コードを取得
                // ステートコードを取得
                // ここで要求時と値が変わらないかチェックすべき(今回は割愛)
                String stateCode = req.queryParams("state");                    

                /**
                 * 許可コードで、アクセストークンの取得要求を行う
                 * この辺は認証サーバの設定にも依存する。今回はPOST方式でシークレットキーを送る
                 */
                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");      // 再度自身のURLを指定しないとエラーになる
                tokenUrl.set("client_id", "oauth_client_key");                  // クライアントIDを設定
                tokenUrl.set("client_secret", "oauth_secret_key");              // シークレットIDを設定

                TokenResponse tr = null;
                String accessToken = null;
                String refreshToken = null;
                try {
                    tr = tokenUrl.execute();
                    accessToken = tr.getAccessToken();
                    refreshToken = tr.getRefreshToken() == null ? "null" : tr.getRefreshToken();
                    // idTokenもらって解析してその情報信用して自社サービスとかにログインさせればSSOとすることも可
                    String idToken = (String)tr.get("id_token");
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    tr = null;
                }                

                return "AccessToken = " + accessToken
                        + "<br>RefreshToken = " + refreshToken;
            }
        });        

    }

}
12
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
25