SpringbootでLINEのOAuth2ログインを試した

Kazuki Koide

September 24, 2018

タイトルの通り、いわゆる「LINEでログイン」を試してみた時のメモ。

ソースコード

koirand/springboot-line-login: LINE login with Springboot Sample

OAuth2での認証方法

第1回:Spring Security 5でサポートされるOAuth 2.0 LoginをSpring Bootで使ってみる

主にこの記事にOAuth2クライアントの実装を行った。OAuth2でログインするためには、spring-security-oauth2-clientモジュールを使う。OpenID Connectでの認証を行う場合は加えてspring-security-oauth2-joseが必要になるが、今回はOAuth2のみなので入れなかった。

<!-- OAuth2 authentication-->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>

application.properties に以下の通りLINE用の設定を記載する。clientIDclientSeretはLINE Developersで取得したものに書き換える。

# Settings for LINE login
spring.security.oauth2.client.registration.line.clientId={Set your client id}
spring.security.oauth2.client.registration.line.clientSecret={Set your client secret}
spring.security.oauth2.client.registration.line.authorizationGrantType=authorization_code
spring.security.oauth2.client.registration.line.redirectUriTemplate={baseUrl}/login/oauth2/code/{registrationId}
spring.security.oauth2.client.registration.line.scope=profile
spring.security.oauth2.client.registration.line.clientName=LINE
spring.security.oauth2.client.provider.line.authorizationUri=https://access.line.me/oauth2/v2.1/authorize
spring.security.oauth2.client.provider.line.tokenUri=https://api.line.me/oauth2/v2.1/token
spring.security.oauth2.client.provider.line.jwkSetUri=https://api.line.me/oauth2/v2.1/verify
spring.security.oauth2.client.provider.line.userInfoUri=https://api.line.me/v2/profile
spring.security.oauth2.client.provider.line.userNameAttribute=userId

Spring Securtyでは、GitHub、Google、Facebook、Oktaの4つのプロバイダに関しては、各設定値の初期値が既に設定されている。なのでapploication.propatiesにはclientIdclientSecretだけを設定すれば動作する。例えばGitHubを追加するなら、以下の設定を追加するだけで良い。

# Settings for GitHub login
spring.security.oauth2.client.registration.github.clientId={Set your client id}
spring.security.oauth2.client.registration.github.clientSecret={Set your client secret}

LINEは初期値が設定されていないので全ての設定が必要になる。scopeの種類や、各エンドポイントのURI、APIの仕様などは以下を参照。

LINEの場合、ユーザープロファイルを取得するためのAPI(userInfoUriで指定しているエンドポイント)のレスポンスが以下のようなJSONになる。従ってuserNameAttributeには、ユーザー名に該当するuserIdを指定している。

{
  "userId":"U4af4980629...",
  "displayName":"Brown",
  "pictureUrl":"https://example.com/abcdefghijklmn",
  "statusMessage":"Hello, LINE!"
}

ちなみにSpringboot v2.1.0.M2より古いバージョンは、userNameAttributeが反映されないので注意されたし。

UserNameAttribute for custom OAuth2 provider by thiagohirata · Pull Request #10672 · spring-projects/spring-boot

コントローラーのメソッドの引数に@AuthenticationPrincipalを指定することで、認証済みのユーザーの情報を受け取ることができるようになる。ここではシンプルにユーザー情報をレスポンスボディにそのままセットしている。

package com.example;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;

@RestController
public class SampleController {

  @GetMapping("/")
  public Object index(@AuthenticationPrincipal OAuth2User oauth2User) {
      return oauth2User;
  }
}

http://localhost:8080にアクセスすると、未認証の場合は、/loginにリダイレクトされる。/loginエンドポイントを実装していなければ、Spring SecurityのDefaultLoginPageGeneratingFilterが以下のログイン画面を自動生成する仕組みになっている。

この例ではLINEのみだが、複数のプロバイダを設定した場合はそれぞれのリンクが表示される。LINEリンクをクリックすると、http://localhost:8080/oauth2/authorization/lineに遷移する。自前のログインページを作成する場合は同じようにこのURIへ遷移するリンクなりボタンを作成すれば良い。http://localhost:8080/oauth2/authorization/lineにアクセスすると、そこから更にauthorizationUriで設定したhttps://access.line.me/oauth2/v2.1/authorizeへリダイレクトしてLINEの認証画面が表示される。認証に成功すると、http://localhost:8080/login/oauth2/code/lineへリダイレクトし、そして最初にアクセスしたhttp://localhost:8080へリダイレクトする。まとめると以下のようなページ遷移になる。

http://localhost:8080
↓ リダイレクト
http://localhost:8080/login
↓ リンクをクリック
http://localhost:8080/oauth2/authorization/line
↓ リダイレクト
https://access.line.me/oauth2/v2.1/authorize
↓ 認証成功
http://localhost:8080/login/oauth2/code/line
↓ リダイレクト
http://localhost:8080

なお、認証成功時のリダイレクト先のURLについては、LINE Developer画面上でホワイトリストに設定しておく必要がある。LINE以外の他のプロバイダでも同様。

別の実装方法

LINE Engieeringブログで、spring-boot-starter-securityspring-security-oauthを使った実現方法が紹介されていたが、この方法だとOAuth2プロバイダが1つしか指定できなかったので採用しなかった。実際はLINEだけでなくGoogleやFacebookと併用したいケースが多いのではないだろうか。

Spring Security + 設定ファイルで始める LINE との ID Federation : LINE Engineering Blog