OTOBANK Engineering Blog

オトバンクはコンテンツが大好きなエンジニアを募集しています!

Google Cloud Identity-Aware Proxy (Cloud IAP) のJWTをPHPで検証しつつ、中身について少し勉強する

お久しぶりです。 @kalibora です。

いきなりですが、 Google Cloud Identity-Aware Proxy (以下Cloud IAP) 便利ですね。

詳細は Cloud Identity-Aware Proxy  |  Identity-Aware Proxy  |  Google Cloud この辺りを読んでもらえばいいとして、

知らない人にざっくり説明すると、

既存のWebアプリにこの機能を設定すれば、必ずGoogleログインが必須になり、 ログインしたユーザーがあらかじめ許可されたユーザーであれば、既存のWebアプリに通して(プロキシして)くれる。

というような機能です。

G Suite を使っている会社であれば、社員がみんな Google アカウントを持っているので、 社内の管理系ツールなどに認証機能がなくとも、この機能を使えばあっという間に認証機能のできあがり。なので楽ですね。

はい。で、そういった機能で必ず必要になるのが、

  • どうやって認証したユーザーのIDをアプリ側で取得するか?
  • その改ざんの防止

です。

認証したユーザーが誰なのか?が分からなければアプリ側でそれに応じた細かな制御も出来ないですし、 誰なのか?が改ざんされたら元も子もありません。

その辺りの説明は

署名済みヘッダーによるアプリの保護  |  Identity-Aware Proxy のドキュメント  |  Google Cloud

にあるのですが、ここで使用しているのが最近よく聞く JWT (Json Web Token) です。

具体的にはプロキシされたHTTPリクエストのヘッダーには必ず x-goog-iap-jwt-assertion を含んでおり、

この値が JWT (もっと具体的に言うと JWS の Compact 形式)となっています。

JWS は 署名付きメッセージのことで Compact は よく見るドット2つで連携した形式のことみたいですが、

私が適当な事言うよりも 複雑に関係しあうJWTまわりの仕様を見る: JWS (JSON Web Signature) - 理系学生日記 ここを見たほうがよいです。

ともかくメッセージがあって、その改ざん防止のために署名してるんだな。くらいの理解でひとまずここはいきましょう。

はい、それでその大事なメッセージ本体の部分はペイロードといいます。

このペイロード部分にユーザーIDである sub と、メールアドレス email が含まれているので、

アプリ側では JWT を適当なライブラリでパースし、その中身を取って使えばいいのです。

ちなみに改ざん防止の検証が不要なら、ライブラリさえいりません。

下記のワンライナーは JWT のヘッダ部分をパースする例です。

$ php -r 'var_dump(base64_decode(strtr("eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJUbGstZyJ9", "-_", "+"), true));'
Command line code:1:
string(42) "{"alg":"ES256","typ":"JWT","kid":"rTlk-g"}"

ドットで区切られたパーツ部分は、単なる Base64Url形式なので、こんなシンプルな実装で取得できるんですね。

とはいえ、改ざん防止を検証しないなんてことはありえないので、ちゃんと検証しましょう。

また、 署名済みヘッダーによるアプリの保護  |  Identity-Aware Proxy のドキュメント  |  Google Cloud にあるように、署名の検証だけでなく、ヘッダやペイロードの中身が制約に従っているかも確認する必要があります。

ちなみに私は Introduction - JWT Framework というライブラリを使って実装し、下記のパッケージとして公開しました。

kalibora/google-cloud-iap-jwt-validator - Packagist

記事中の間違いやバグなどあれば報告していただけると幸いです。 それではまた。

builderscon 2018 に参加しました #builderscon

こんにちは、7月にオトバンクに入社してエンジニアをやっている@s4kr4です。
9月7日〜9月8日に開催されたbuilderscon 2018に参加しました。

builderscon.io

buildersconのテーマ「知らなかった、を聞く」の通り、Webからコンテナ技術、IoT関連などさまざまなジャンルのセッションがありました。

自分はWeb系のセッションを中心に参加したのですが、その裏でも面白そうなセッションが多かったです。
YouTubeに順次動画が上がっているようなので、時間がある時に見てみたいと思います。(プレイリスト)

以下、印象に残ったセッションを共有します。

Algorithms in React

発表者: @koba04 さん
スライド: https://speakerdeck.com/koba04/algorithms-in-react

speakerdeck.com

Stackと呼ばれていたReactの内部構造が、Fiberなるものに書き換えられたお話でした。 内部処理が非同期になり、差分計算 → レンダリングの速度がかなり向上したそうです。

「Web とは何か?」 - あるいは「Web を Web たらしめるものは何か?」

発表者: @Jxck さん
スライド: 公開なし?

Webの始まりから現在、そしてこれからのWebについて。
今までどういう要求があってどういう変遷を辿ってきたのか、これからどうなっていくべきかという話でした。
@Jxckさんが運営されている mozaic.fm というPodcastをたまに聞いているのですが、まさにこれを生で聞いているような感じでした。

すべてが gem になる - サービス密結合からの段階的脱却

発表者: @izumin5210 さん
スライド: https://speakerdeck.com/izumin5210/builderscon-tokyo-2018

speakerdeck.com

複数のサービスから同じデータを使いたい場合にどう対応するか?という話です。
密結合のメリット・デメリットを検討し、最終的にはモデルをshared gemにするという方法で解決したそうです。

ブログサービスのHTTPS化を支えたAWSで作るピタゴラスイッチ

発表者: @aereal さん
スライド: https://speakerdeck.com/aereal/the-construction-of-large-scale-tls-certificates-management-system-with-aws

speakerdeck.com

はてなブログで運用するドメインを全てHTTPS化できるようになったのは記憶に新しいですが、それを実現するためにどういう設計・運用を行ったのか、という話でした。
全てをAWS上のトリガーやバッチで実現する設計の中で見えてきたTipsや、大規模な処理をどのように分割・管理したか等、とても勉強になりました。


どのセッションも実践的・具体的で勉強になり、また行きたいと思えるイベントでした。
社内で使っているReactや、業務でも個人的にももっと日常的に使えると良いなあと思っていたコンテナ技術周辺についても学ぶことがあったので、ぜひ今後に活かせていければと思います。
今回は興味のある分野のセッションにばかり参加していましたが、次回があればぜひその他のセッションにも参加してみたいです。

Hyper と fish の環境構築をしてみたよ

あああああああああけましておめでとうございます (まじか) @riaf です!
すっかりブログの更新をサボっていましたが、今後も気張らずにゆるくやっていこうと思いますので今年もよろしくお願いします。

というわけで (どういうわけだ)、最近 macOS をクリーンインストールして、新たに環境構築する機会があったので、気持ちだけでもナウでヤングになろうと思い、ターミナルに Hyper、シェルを fish にしてみた記録です。

(インストールのあたりの話とかはめちゃ簡単なので省略)

Hyper をインストールすると、 /usr/local/bin/hyper/Applications/Hyper.app/Contents/Resources/bin/hyper のシンボリックリンクが作られます。プラグイン・テーマのインストールはこのコマンドを使うということですね。

# こんな感じ
hyper i verminal

Homebrew をインストールすると、/usr/local/bin/hyper が消えてしまったのですが、Hyper を再起動すると自動的にまた作られるようでした。

プラグインはひとまずそれなりに使われていそうだった

  • hyper-search
  • hypercwd
  • hyper-statusline

あたりを入れてみました。各プラグインの詳細はまあどこかで紹介されていることでしょう。

初期状態だと Hyper (に限らずだけど) ではキーリピートが効かなくなっていたので、

defaults write -g ApplePressAndHoldEnabled -bool false

こうしてキーリピートできるようにしておきました。

いつもだとここでなにも考えずに brew install zsh してしまうところだったのですが、ナウでヤングな僕は fish を使おうと思ったので brew install fish としました。インストール後は /etc/shells に追記して、chsh するだけですね。そういえばここで再ログインが必要かもしれません。

日本語をうまく扱えない、という話を割と見たんですが、バージョン 2 系からは環境変数 LANGja_JP.UTF-8 を設定してあげれば特に問題なく使えています。

fish も最近のプロダクトっぽい感じでプラグインマネージャーがいくつかありまして、僕は fisherman を入れてみました。

curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisherman

こちらも同様に簡単にプラグインをインストールできます。

# こんな感じ
fisher i fzf

zsh のゴリゴリカスタマイズできる感じも好きだったのですが、最近はちょっとそれも億劫になってきていたので、デフォルトで色々してくれちゃうのは楽チンでいいですね。

どちらもまだ若いプロジェクトなこともあって、この記事の情報もいつまで使えるかわからないですが、久々にそういう環境を楽しんでみることにします ;p