はじめに
-
LINEログイン機能を試してみる – 発火後忘失
で、 Spring Boot 2.1.7 (Spring Security 5.1.6) を利用してLINEログインを行ってみました。
本ドキュメントは、このコードをそのまま Spring Boot 2.4.5 へアップグレードしたところ上手く動かなかったので修正を行った記録です。
コード
なお、今回の対応前の、 Spring Boot 2.1.7 バージョンは 55b9ea4b2
です。
本文中の「昔のコード」とはこれを指します。
対応内容
本質と関係ないものは省略します。
Support space-delimited oauth2 scope (spring-projects/spring-boot #15398)
(表題に反して) scope の指定でスペースが許可されなくなり、カンマ ,
で区切らなければならなくなった模様です。
Support unsigned ID tokens for OIDC (spring-projects/spring-security #9494)
デフォルトでは RS256
固定 なので HS256
に挿げ替えます。
昔のコードが不都合なく動作していたのは、(ちゃんとは見ていませんが)おそらく署名の検証を行っていないからなのではないかと思います。 OAuath2.0 と共通フローだったのではないかと。
LINEログイン v2.1 API における userinfo_endpoint の誤解
昔のコードでは userinfo エンドポイントは https://api.line.me/v2/profile
だと誤解して設定していました。
昔のコードはこれで動作したのですが、Spring Securityのバージョンが上がったことで 検証が厳密になり、通らなくなっているようです。
LINEログイン v2.1 API で UserInfo レスポンス を満たすものを返してくるのは https://api.line.me/oauth2/v2.1/verify
だけのようだったので、今回これを指定しました。
ただ、LINEログインのリファレンスにもある通り、これは "IDトークンのペイロード部分" であり、LINE社はひとことも userinfoエンドポイント である、とは言っていないんですよね (しかし v2.1 は "OpenID Connect プロトコルをサポートし"ていると言っている…じゃあuserinfoエンドポイントはどこなんだっていう)。
また、 iat
やら exp
が含まれているのも、UserInfo として妥当であるとは言い難いように思われます(ユーザの属性ではないことは明らか)。
実装においては、APIリファレンスを見れば分かる通り、 /verify
へのリクエストには id_token
と client_id
パラメータが必須なので、少し工夫が必要でした。
まとめ
LINE社の主張に反し、 LINEログイン v2.1 API は OpenID Connect プロトコルには準拠していないと考えます。 なぜならば、 userinfo エンドポイントに相当するエンドポイントを備えていないからです。 (LINE社が言うところのOIDCサポートは、発行者を検証できるid tokenを返している、という部分でしょうか。それだけでは片手落ちでしょう。)
Spring Security のデフォルト実装を用いる場合、 openid
スコープを指定するとうまく動作しません。
本文では openid
を指定した実装を無理やり行いましたが、指定しない場合の実装(つまりOIDCでなくOAuth2.0として処理する)を tags/line-login-without-openid
タグで行っており、こちらの方が自然だと考えます。