質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.33%

Spring BootでOAuth2を使うときのセッション保持方法

受付中

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 4,178

Youichi256

score 179

実現したいこと

Spring BootでOAuth2を使って認証しようとしています。
Googleでの認証は出来たのですが、そのあとのユーザ識別やログイン状態の保持方法が分かりません。

困っていること、分からないこと

  • ログイン状態の保持期間を1時間とかにしたい
    (GoogleのOAuth2の情報は30分でクリアされるようなので)
  • ユーザを一意に特定するのはOAuth2Authentication.getUserAuthentication().getDetails().get("sub")でよいか
    (RootController.java 参照)
  • ログイン直後にユーザに関する情報をセッションに入れるタイミングがほしい
    (onLogin()をオーバーライドするイメージ)
  • Google以外でもOAuthで認証するときに困らないような書き方

関連ソース

  • RootController.java
@Controller
@Slf4j
public class RootController {
    @RequestMapping("/")
    public String index(Model model, HttpServletRequest request, OAuth2Authentication auth) {
        if (request.isUserInRole("ROLE_USER")) {
            model.addAttribute("user", request.getRemoteUser());
            Object authDetails = auth.getUserAuthentication().getDetails();
            Map<?, ?> mm = null;
            if (authDetails instanceof LinkedHashMap) {
                mm = (LinkedHashMap<?, ?>) authDetails;
            }
            model.addAttribute("sub", mm.get("sub"));
            model.addAttribute("email", mm.get("email"));

            log.info("logined:{}", mm.get("email"));
            for (Entry<?, ?> m : mm.entrySet()) {
                log.info("AUTH:{}={}", m.getKey(), m.getValue());
            }
        } else {
            log.info("no login");
        }

        if (auth == null) {
            log.info("auth:null");
        } else {
            log.info("name:{}", auth);
        }

        return "index";
    }
}
  • SecurityConfig.java
@Component
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests().antMatchers("/").permitAll().anyRequest().authenticated()
            .and().logout().logoutSuccessUrl("/").permitAll();
    }
}
  • application.yml
security:
  oauth2:
    client:
      clientId: xxx.apps.googleusercontent.com
      clientSecret: yyy
      accessTokenUri: https://www.googleapis.com/oauth2/v4/token
      userAuthorizationUri: https://accounts.google.com/o/oauth2/v2/auth
      clientAuthenticationScheme: form
      scope:
        openid
        email
    resource:
      userInfoUri: https://www.googleapis.com/oauth2/v3/userinfo
      preferTokenInfo: true
  • build.gradle
buildscript {
    ext {
        springBootVersion = '1.5.3.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'

war {
    baseName = 'xxx'
    version = '0.0.1'
}

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

configurations {
    providedRuntime
}

dependencies {
    compile('org.springframework.boot:spring-boot-configuration-processor')
    compile('org.springframework.boot:spring-boot-starter-aop')
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.security.oauth:spring-security-oauth2')
    compileOnly('org.projectlombok:lombok')
    runtime('org.springframework.boot:spring-boot-devtools') //コード更新時にアプリケーションをリロード
    runtime('org.postgresql:postgresql')
    providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

bootRun {
    jvmArgs = ['-Dspring.output.ansi.enabled=always'] //コンソールに色を付ける
}

補足情報

開発環境:Eclipse 4.6 (Pleiades)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

複数の質問がありますので回答のみのものもあります。ご容赦ください。

  1. ログイン状態の保持期間を1時間とかにしたい
    トークンの有効期限は変えられませんが、自動リフレッシュする機能と強制破棄する仕組みも提供されています。これで代替できるか検討してください。
    https://developers.google.com/identity/protocols/OAuth2WebServer#offline

  2. ユーザを一意に特定するのはOAuth2Authentication.getUserAuthentication().getDetails().get("sub")でよいか
    ユーザの定義が曖昧なので正解になるかはわかりませんが、Googleアカウント利用者を一意に定義できる値は sub で間違いはありません。Googleアカウント利用者ひとりにつき複数のメールアドレスが使えますが、この場合のsubの値は一意に紐づけられます。https://developers.google.com/identity/protocols/OpenIDConnect#server-flow

  3. ログイン直後にユーザに関する情報をセッションに入れるタイミングがほしい
    ドンピシャのサンプルコードが以下にありますので参考にしてください。AuthenticationSuccessHandlerを実装するだけです。
    https://javapointers.com/tutorial/spring-custom-authenticationsuccesshandler-example-2/

  4. Google以外でもOAuthで認証するときに困らないような書き方
    具体的に書かれているControllerのコードは、Googleアカウントに依存する書き方になりますが、3.で示したSuccessHandlerにて実装を切り替えることがSpringの設定でも可能ですので、Controllerは認証環境に依存しない値をSuccessHandlerにてバインドした値から取得するようにすればControllerの依存度は低くなるでしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/29 12:04

    1.ログイン状態の保持期間を1時間とかにしたい
    OAuthサービスプロバイダごとに専用のやり方が必要そうですが、他の問題が片付いたら検討してみます。
    2.ユーザを一意に特定するのは
    ありがとうございます。公式情報を探したかったのです。
    3.ログイン直後にユーザに関する情報をセッションに入れるタイミングがほしい
    試してみましたが、ハンドラが呼ばれませんでした。ログインフォームにも仕掛けがいるようですので、OAuth2には対応していないのではないでしょうか。
    4.Google以外でもOAuthで認証するときに困らないような書き方
    OAuth2プロバイダごとの違いを吸収してくれるSpring Socialというのもあるみたいで、こちらも平行で調べています。

    キャンセル

  • 2017/06/29 20:37

    そうですね、SpringSocial経由でTwitter認証やFacebook認証の機能を簡単に使えますので、独自に実装しなくて済むのであれば、提供ライブラリを使うのが良いと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る