2020年5月、6月にやったこと

握力が70超えた

Go言語でつくるインタプリタ

全部終わった おもしろかった おもしろかった以上の感想はあんまりない

JSONのパーサー書いた

github.com

Go言語でつくるインタプリタ読んでてJSONのパーサーくらいならノリでかけそうだなと思って書いた なんとなくkotlinで書いたけどいろいろ楽だった Kotlin書いてるとJavaのコードを読めなくなるという問題がある

lexerのこの辺がだいぶあれだけど動いたので満足してしまった

なんかよくわからないWebアプリ書いた

github.com

デプロイ何もわからんのでECSになんかデプロイして遊んだりしようと思ったけどとりあえずデプロイ対象を書くか、になってしまったので書いてた いくつかWebアプリ実行してHTTPリクエストにHTTPリクエストの連携の経路を指定するとそれにあわせてWebアプリを呼び分けてくれるみたいなやつ

これを複数デプロイしてマイクロサービス間の通信したりxrayで連携してる様を眺めて遊んだりしようとしてた いまいちやる気がでず単体でデプロイして止まっている これははやくやらないとまずい 監視とかもこれにいろいろ入れて遊ぼうとしているので

ブログ書いた

dev.classmethod.jp

Javadocの例外のやつ 割と極論感あるけど個人的にはこの方向で割とうまくいっている認識がある

ハローキティのかんたん簿記 超入門

会社で勧められたので読んだ 結構わかりやすかった気がする ただ簿記の初心者本あるあるだと思うんだけど仕訳の話ばっかり

トコトンやさしい小売・流通の本

あんまり記憶がない

マンガでわかる! はじめての簿記

kindle unlimitedで読めたのであんまり期待しないで読んだらわかりやすかった  言うほど漫画では学べないけど これ系の本、全体的に損益計算書とか貸借対照表のがあんまりないのはなぜなのか 簿記の資格の初歩的なやつが仕訳に偏ってるからだと思うんだけども

いちばんやさしいブロックチェーンの教本 人気講師が教えるビットコインを支える仕組み (「いちばんやさしい教本」シリーズ)

雑に読むには割と重たい本だった ローカルで改ざん出来ない署名ができるデータの集合がブロックチェーンなんだなーくらいには理解したけどそれ以上は仕組みについての解説を軸にもうちょっと真面目に学ぶ必要がありそう ビジネス的に何に使えるの?的な話と仕組みの話がまとめて書いてあるのでそういうのを求めてる人にはよさそう

その他

ELBとかECSのガイド読んだりしてた気がする あとDockerのガイドも読んだ気がする あとはマイクロサービスパターンとか簿記の本他のやつとか英文解釈教室とか あとエリックエヴァンスのDDDもちょくちょく読んでる いろいろちょっとずつ読みすぎ感がある レアジョブは28回やってた

あとはこの辺の勉強会ひたすら見てた このへんは大変におもしろい https://authlete.connpass.com/

これからやること

  • AWS入門する
    • ECS
  • Webエンジニアが知っておきたいインフラの基
  • 入門監視
  • クリーンアーキテクチャ
  • Javaパフォーマンス
  • 実践ハイパフォーマンスMySQL 第3版
  • プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
    • 停滞気味
  • Linuxの仕組み
  • Goならわかるシステムプログラミング
  • 英語
  • 中国語
    • Toeic900超えるまで止める予定
  • ここ最近ほとんど業務でプログラミングをしなくなって、調整とかレビューとかばっかしてるがかなり雰囲気でやってるので、マネジメント系の本を読もうとしている
    • なにがいいのかよくわからん
  • Effective Go - The Go Programming Language
  • パタヘネ
  • OAuth2.0のクライアント書く
  • OAuth 2.0/OIDC関連仕様全部読む
  • WebAuthnのドキュメント読む
  • マイクロサービスパターン

2020年3月、4月にやったこと

だらだらしていた

[改訂新版] 3分間ネットワーク基礎講座

インフラなんもわからんのをいい加減なんとかしようと思って読んでた わかりやすかった

DNSをはじめよう ~基礎からトラブルシューティングまで~ 改訂第2版 はじめようシリーズ

DNSなんもわからんのでよんだ このあとDNSがよくわかる教科書を読んだ 個人的にはDNSがよくわかる教科書だけでよかったなという感じ ドメイン一回もとったことなくてとるときにハマってダメとかそういう場合にはよさそう

DNSがよくわかる教科書

DNSなんもわからんのでよんだ わかりやすかった DNSはとりあえずこれでいいやという気持ちになった

Amazon Route 53のガイド

読みながら多少さわった まあ

ELBのblackbeltのオンラインセミナー

わかりやすい

Go言語でつくるインタプリタ

マクロの直前までやった マクロもやる予定 これはおもしろい

エリック・エヴァンスのドメイン駆動設計

再度読み始めた 1/5くらいよんだ 1/5くらいまではなかなか苦行感があった なぜならやり取りの結果でてくるモデルがなんでそういうモデルになるのかよくわからないゆえ 設計の話が出てきたのでちょっとおもしろくなってきたかもしれない

いちばんやさしいブロックチェーンの教本 人気講師が教えるビットコインを支える仕組み 「いちばんやさしい教本」シリーズ

なんとなく半分くらいよんだ ずっとわかるようなわからないような気持ちにさせられる

英語

英文解釈教室

やっている 32ページまで 進みが遅いのはそもそも文法知識がなさすぎて登場する文法をあらためて学び直しているため そもそも適当な文法書を1冊やったほうがよいのでは

レアジョブ

なんとなく再開 4月から16回受講した 文法がぐちゃぐちゃなのと使う単語のバリエーションがかなり無なのをなんとかしたいのでその辺をなんとかしようとしている recentlyってめっちゃいってしまう

その他

他もなんかした気がするけどわすれた

アクセストークンの勉強会

https://authlete.connpass.com/event/172393/ これはよかった アクセストークンに構造を持たせるかどうかの話とか PARとかDPoPとか おさらいしたい

これからやること

  • AWS入門する
    • ELB
    • ECS
  • コンテナ入門する
  • Webエンジニアが知っておきたいインフラの基本
  • 実践ハイパフォーマンスMySQL 第3版
  • プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
    • 停滞気味
  • Linuxの仕組み
  • Goならわかるシステムプログラミング
  • 英語
  • 中国語
    • Toeic900超えるまで止める予定
  • ここ最近ほとんど業務でプログラミングをしなくなって、調整とかレビューとかばっかしてるがかなり雰囲気でやってるので、マネジメント系の本を読もうとしている
    • なにがいいのかよくわからん
  • Effective Go - The Go Programming Language
  • パタヘネ
  • OAuth2.0のクライアント書く
  • OAuth 2.0/OIDC関連仕様全部読む
  • WebAuthnのドキュメント読む
  • マイクロサービスパターン

2020年2月にやったこと

PKCEの実装したりAWSに入門したりしてた

ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本

DDDの本というよりはクラス設計の本だなこれはといった感じ 具体的な感想文は会社のブログに書いた

dev.classmethod.jp

WebAuthn仕様

5章まで読み終わった 5章読む必要あったかはかなり謎である そしてここからだというタイミングでいったんストップした

www.w3.org

WebAuthnのAPIを眺める

眺めるためのアプリをつくった なぜならCBORとかをいちいちパースするのがめんどうだったから これは会社のブログにかいた

dev.classmethod.jp

webpack初めて使った buefyは便利

Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂版

割と知ってるような話だったような気がする VPCのガイドをある程度読み進めてから読んだが完全に逆だった感がある

あとこれは完全に個人的なミスなんだけど改訂3版がもうでていた

VPCのユーザーガイド

一通り読んだりよくわからんところは触ったりなんだりした これはおもしろかった 次はRoute53とかELBあたりをやっていく予定

ちまちまブログ書いてた

dev.classmethod.jp これは便利 かなり使っています

dev.classmethod.jp これは個人で書いてた適当なコードに適用してあそんでいた

dev.classmethod.jp これは寝室にセキュリティーキーがあってとりにいくのめんどいけどwebauthnのAPI叩きたい、みたいなときに便利

これからやること

  • AWS入門する
    • ELB
    • Route53
  • Webエンジニアが知っておきたいインフラの基本
  • 実践ハイパフォーマンスMySQL 第3版
  • プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
    • 停滞気味
  • Linuxの仕組み
  • Goならわかるシステムプログラミング
  • 英語
  • 中国語
    • Toeic900超えるまで止める予定
  • ここ最近ほとんど業務でプログラミングをしなくなって、調整とかレビューとかばっかしてるがかなり雰囲気でやってるので、マネジメント系の本を読もうとしている
    • なにがいいのかよくわからん
  • Effective Go - The Go Programming Language
  • パタヘネ
  • OAuth2.0のクライアント書く
  • OAuth 2.0/OIDC関連仕様全部読む
  • WebAuthnのドキュメント読む

2020年1月にやったこと

基本WebAuthnをやってた

マイクロサービスアーキテクチャ

今更ながら読みおわった もっと早く読んでおいてよかったかんじ

まずなんでマイクロサービスなのか?についてかなり整理されている あとはモノリスをマイクロサービスにわけるときにDBをどう分けていくかの手順とかがよかった イベント駆動だとどうなる?の話とか

WebAuthn仕様

最初から再度真面目に読み直している terminologyがかなりつらいがとりあえず読み終わって5章の半ばまで読んだ

はたしてこれはRPの実装者が読む必要があるのかは疑問ではある でもtimeoutの値が入力値そのままじゃなくて現実的な可能な時間に補正される話とか、そういう細かいところはこれを読まないとわからなさそうな感じ

割とWebAuthnのAPIの入力、出力の値がそれぞれなんなのか?、とかデータの構造はどうなってるのか?とかは理解できてきた気がする

2月も多分ずっとこれを読んでいる気がする

www.w3.org

WebAuthn写経

gihyo.jp

WEB+DB PRESS Vol.114のWebAuthn特集を読みながらコードをみながらとりあえず登録したり認証器でログインしたりできる状態まで写経した あとはなんかパラメーターいじってプラットフォーム認証機限定にしたらどうなるんだっけなとかそういうのを試していた

コードの写経はともかくこの特集はめちゃくちゃいい感じにまとまっていて素晴らしいのでWebAuthn気になる実装してみたいという人にはめちゃくちゃおすすめしたい

あとはmdnのWebAuthnのページもよい

developer.mozilla.org

しかしAPIの入力と出力の定義がよくわからんというか、Credential Management APIに対する実装として作られているせいで定義を追いかけるのがなかなかにめんどくさい気がする というところもふくめてWEB+DB PRESS Vol.114はめちゃくちゃわかりやすい

OAuth 2.0/OIDC関連仕様読む

RFC 7636: Proof Key for Code Exchange by OAuth Public Clients

いわゆるPKCE

フローとかは理解してるつもりだったが真面目に仕様読んだらこれはなかなか面白かったので別途まとめた

inabajunmr.hatenablog.com

OAuth 2.0 Form Post Response Mode

認可レスポンスでコールバックに戻ってくるときにリダイレクトじゃなくてPOSTでやっちゃおうぜってやつ これ自体はまあそれだけな感じでふーんって感じで読んでたがsamesite=laxもしくはstrictとの相性が悪い問題を知ってふーんってなった みんなどうすんだろうなこれってかんじ

英語

www.amazon.co.jp

これを英語の勉強のつもりでだいぶ前に買って積んでたが読み始めた

割と難しい単語がいっぱいでてくるが文章的には割と読みやすい気がする 内容の面白さで難しい単語を調べるだるさを打破していきたいところである

これからやること

  • プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
    • 停滞気味
  • Linuxの仕組み
  • Goならわかるシステムプログラミング
  • 英語
  • 中国語
    • Toeic900超えるまで止める予定
  • ここ最近ほとんど業務でプログラミングをしなくなって、調整とかレビューとかばっかしてるがかなり雰囲気でやってるので、マネジメント系の本を読もうとしている
    • なにがいいのかよくわからん
  • Effective Go - The Go Programming Language
  • パタヘネ
  • OAuth2.0のクライアント書く
  • OAuth 2.0/OIDC関連仕様全部読む
  • WebAuthnのドキュメント読む

WebAuthnの仕様を4章まで読んだ

これを読んでいる Web Authentication: An API for accessing Public Key Credentials Level 1

4章まで読んだとはつまりまだ本編に入っていないという意味である

TerminologyがTerminologyだけで理解できないところがいくつかあり、今後を読み進めながら理解した上で再度読み直し、ある程度噛み砕いた説明をできるようになったら会社のブログにまとめる予定

以下、読みながらとっていたメモ

Introduction

  • webauthnは認証のための公開鍵ベースのクレデンシャルを作るAPIだよ
  • 公開鍵はRPに所属するOriginからしかさわれないよ
  • 他のRPからはデータの中身とか存在性とか見れないよ
  • Web Authentication APIはRegistrationとAuthenticationの2つの区分があるよ
    • Registrationでは認証機によって公開鍵クレデンシャルが作られるよ
      • 公開鍵クレデンシャルはRPのユーザーアカウントに紐づけられるよ
        • 公開鍵クレデンシャルはアカウント登録時か、登録後に生成して紐付けとけばおk
    • AuthenticationではRPは認証アサーションを提示されるよ
      • これは公開鍵を登録したユーザーの存在と同意を証明します
    • それぞれのAPInavigator.credentials.create()navigator.credentials.get()
  • 認証機はWeb Authentication APIを使ってUAとやりとりする
    • バイス自体(スマホとかPCとか)に実装されてる認証器(プラットフォーム認証器)とUSBとかBLEとかNFCでデバイスと接続して使う認証器(ローミング認証器、いわゆるセキュリティキー)があるよ

1.1 Specification Roadmap

  • 想定してる読み手がUAの開発者とかRPの開発者とか認証器の開発者とかいろいろいるけどどの辺読んだらいいんだ?が書いてある

1.2 Use Cases

いわゆるユースケース

1.2.1 Registration

  • 携帯電話で
    • サイトにアクセスしてパスワードでログインして
    • 画面にデバイス登録する?って出るので
    • ユーザーが同意して
    • 事前に設定した認証ジェスチャーバイオメトリクスとかPINとか)にあわせてユーザーがなんかして
    • 登録おkって表示される

1.2.2 Authentication

  • PCでスマホにBLEでつないでスマホで認証フロー進めたらPC側で認証完了してる、みたいな話書いてあるんだが、そんなことできんの? // TODO

1.2.3 New Device Registration

  • ローミング認証器とプラットフォーム認証器どっちも登録するような場合のユースケース
    • 最初にプラットフォーム認証器が実装されてないPCでローミング認証器を登録して、その後別のデバイスでプラットフォーム認証器を登録する
    • これをやるとパスワードリカバリで便利だったりする
  • フロー
    • デスクトップPC側
      • デスクトップPCでパスワードログイン
      • セキュリティキーの登録ページに行く
      • USBのセキュリティキーを刺すとセキュリティキーがチカチカするのでタッチすると、登録完了
    • ラップトップ側
      • サインイン画面でユーザーがUSBキーを刺してボタンをおす
      • サインイン後の画面でPCのプラットフォーム認証器を登録するか聞いてくる
      • ユーザーがOKして事前設定した認証ジェスチャーを行う
      • 登録完了し、サインアウト
    • 再びラップトップ
      • サインインしてねプロンプトがでるので、認証ジェスチャーをするとサインインする

1.2.4 Other Use Cases and Configurations

1.3 Platform-Specific Implementation Guidance

一般的なユースケースについて定義してるけど特定のプラットフォームでサポートする場合はプラットフォーム側の仕様とか制約とか見てくれよな

2 Conformance

  • 各要素が何に適合してないとダメか、みたいな話

2.1 User Agents

  • UAの実装者は、仕様を守ってくれよな!

2.2 Authenticators

  • 認証器の実装者は、仕様を守ってくれよな!

2.2.1 Backwards Compatibility with FIDO U2F

  • U2Fしかサポートしない場合、UserHandleは常にnullにしてくれよな!
    • UserHandleは要するに認証器側が持ってるユーザーIDみたいなやつ
    • U2FはIDレス認証ないので

2.3 WebAuthn Relying Parties

  • 認証器の実装者は、仕様を守ってくれよな!

2.4 All Conformance Classes

  • CBORの仕様を守ってくれよな!
  • 守ってないやつは、許すな!

3 Dependencies

  • WebAuthnが依存してる他の仕様一覧
    • Base64url encodingはこの定義に合わせてるぞ、とか
    • ここでいうCBORはこれのことだぞ、みたいな

4 Terminology

  • アテステーション
    • 認証器や、認証器が出力したデータ(credeitnal idとかキーペアとか署名回数とか)の出どころを証明する文章
    • 登録時にアテステーションオブジェクトの中に入れて送信する
  • アテステーション証明書
    • 認証器が自身の製造元とか性能を証明するために認証器自体が利用するアテステーションキーペアのためのX.509証明書
    • 登録時に認証器はアテステーション秘密鍵をRP専用の公開鍵(と追加データ)に署名するために利用する。この公開鍵はauthenticatorMakeCredentialを通じて生成される
    • RPはアテステーション署名検証のために証明書のアテステーション公開鍵を利用する
  • 認証式
    • ユーザーとユーザーのクライアント(1つ以上の認証器)が一緒になって、ユーザーが登録した公開鍵クレデンシャルに紐づく秘密鍵を管理下においていることを暗号学的に証明すること。
    • この秘密鍵はあの公開鍵クレデンシャルを登録した俺だ!を証明するための式。しきたりに合わせた一連作業なので、式、っぽい。方程式の式じゃなくて、卒業式の式
  • 認証アサーション
  • 認証器
    • RPに登録する公開鍵クレデンシャルを生成し、潜在的なユーザー検証によって認証を行い、RPによって提示されたデータ、チャレンジ、認証アサーションを暗号で署名して返却するWebAuthnクライアントによって利用される、暗号化エンティティ
  • 認証ジェスチャー
    • ユーザーが認証器に対して物理的に行うインタラクション
      • ユーザーが同意を示すために利用する
      • 登録と認証時にジェスチャーする
      • タップするだけだったり、認証器側が対応していればユーザー認証もできる(指紋とか)
  • バイオメトリクス認証
    • 個人の生態学的もしくは行動パターンを元にした自動的な認証
  • バイオメトリクス認証
  • Bound credential
    • Boundは境界の方じゃなくてBindの過去分子
    • 管理認証器だけが認証器に紐づけられた公開鍵クレデンシャルソースのためのアサーションを生成できること
  • セレモニー
    • 人間とか物理デバイスとかコンピューティングとかが連携してよしなに頑張ること(多分・・・)
      • の一連の流れのことをセレモニーという、という認識でよさそう
    • WebAuthnの文脈では登録と認証のこと
  • クライアントプラットフォーム
    • クライアントデバイスとクライアントであわせてクライアントプラットフォーム
      • 1つのハードウェアデバイスも、OSやクライアントが異なる別のコンテキストで実行されれば、複数のクライアントプラットフォームとなる
  • クライアントサイド
    • 認証器とクライアントプラットフォーム
  • レジデントクレデンシャル / クライアントサイドレジデント公開鍵クレデンシャルソース
    • 認証器、クライアントもしくはクライアントデバイスに保存されているクレデンシャル秘密鍵が属する公開鍵クレデンシャルソースのこと。 // TODO 関係性がよくわからんのでわかったら追記
    • そのようなクライアント再度のストレージはレジデントクレデンシャルに対応している認証器を必要とし、認証器がRP IDだけを渡された場合に、ユーザーとやりとりすることで秘密鍵を選択できる必要がある
    • 定義では、クレデンシャル秘密鍵は認証器によってのみ常にコントロールされる。レジデントクレデンシャルの場合、認証器は認証器自身からラップされたキーマテリアルのストレージをクライアントデバイスにオフロードするが、クライアントデバイスはそのキーストレージをリモートエンティティ(RPサーバーとか)には送信しない
  • Conforming User Agent
    • WebAuthn対応のUA
    • JSのAPIが叩けて、認証器と接続できる
  • クレデンシャルID
    • 公開鍵クレデンシャルソースとその認証アサーションのID
      • 認証器が生成する
  • クレデンシャル公開鍵
    • RPに登録するときにRPに対して発行されるキーペアの公開鍵の方
    • 公開鍵の方はRPに送る
  • Human Palatability
    • 人間が理解できて、覚えられるようなID
    • ランダムなバイトシーケンスとかじゃないやつ
  • 公開鍵クレデンシャルソース
    • 認証アサーション生成のために認証器が利用するクレデンシャルソース
    • authenticatorMakeCredentialが公開鍵クレデンシャルソースを生成し、管理している認証器に紐づけ、秘密鍵に紐づいた公開鍵を返す。RPはこの公開鍵を、公開鍵クレデンシャルソースによって作成される認証アサーションの検証に使う。
    • あやふや。// TODO
  • 公開鍵クレデンシャル
    • 公開鍵クレデンシャルソース、公開鍵クレデンシャルソースに対応する認証可能な公開鍵、または認証アサーションのいずれか
    • どれなのか?はコンテキストによる
    • よくわからん // TODO
    • 登録時に認証器は非対称鍵を生成し、秘密鍵の部分とRPからの情報を公開鍵クレデンシャルソースへ保存する
    • 公開鍵の部分はRPに返され、RPはユーザーアカウントと一緒に公開鍵を保存する
    • RP IDによって特定できるRPだけが認証セレモニー時にget()メソッドによって公開鍵クレデンシャルを利用できる。
    • RPは保存した公開鍵のコピー認証アサーションの検証に利用する
  • Rate Limiting
    • いわゆるレートリミット
    • 認証器にブルートフォース対策として実装される
    • 間違えすぎると指数的に遅くなったり禁止されたり
  • 登録 / 登録セレモニー
    • ユーザー、RP、ユーザーのクライアント(1つ以上の認証器を含む)が一緒に頑張って公開鍵クレデンシャルをつくってそれをRPのアカウントに紐づける一連の行為
    • ユーザーの存在チェックとかユーザー認証も含む
  • Relying Party / WebAuthn Relying Party.
    • Web Authentication API で登録、認証をやるWebアプリをもつエンティティ
  • Relying Party Identifier / RP ID *登録、認証セレモニーが実行されるRPを特定する有効なドメイン文字列
  • Test of User Presence
    • シンプルな認証ジェスチャ
      • 要するにユーザーが認証器にタッチするやつ(タッチじゃなくてもよい)
        • Booleanの結果が返る
    • 存在性チェックだけで、user verification ではない
  • User consent
  • User Handle
    • RPがuser.idとして提供し、公開鍵クレデンシャルとRPのユーザーアカウントをマッピングするのに使う
    • 認証器具は公開鍵クレデンシャルソースにユーザーハンドルとRP IDをマッピングする
  • User Verification
    • 認証器が authenticatorMakeCredential と authenticatorGetAssertion でローカルで認証するやつ
    • いくつかの認証ジェスチャーによって行われる
      • タッチしてPIN入力とかパスワード入れたりとかバイオメトリック認証とか
    • 各ユーザーの区別に使える
  • User Present / UP
    • user presence testによる、ユーザーの、「自分、いますよ」
  • User Verified / UV
    • User Verificationによる、ユーザーの、「自分、本当に自分ですよ」
  • Client / WebAuthn Client
    • UAに実装されている中間エージェント
      • WebAuthnのJSのAPIの裏で動いてる何か?
      • 認証器操作のためのインプットを整理したり、Web Authentication APIの呼び出し元に DiscoverFromExternalSourceの操作の結果を返したりする
    • WebAuthn ClientはWebAuthn Client Device上で実行されるが、これらはイコールではなく区別される
  • Client Device / WebAuthn Client Device
    • WebAuthn Clientを実行するスマートフォン、ラップトップ、デスクトップコンピュータなどのハードウェアデバイスと、その上でうごくOS

PKCEについて気になった仕様いくつか

PKCEなんなの?

https://tools.ietf.org/html/rfc7636

スマホアプリがカスタムURLスキームで認可レスポンスを受信する場合、悪意のあるアプリがクライアントのアプリと同じカスタムURLスキームを利用していると、リダイレクト先が意図しないアプリになる可能性があって、その場合認可コードが盗まれる。 スマホアプリの場合、Clientのシークレットは安全ではないので、シークレットと認可コードを盗まれると、悪意のあるアプリがアクセストークンを取得できてしまう。

特に、Clientのシークレットがアプリに対して固定されてる場合、悪意のあるアプリ開発者はClientのアプリを自分で解析したりしてよしなにできちゃう。 という文脈で、Dynamic Client Registrationのが安全なんだな、という風に理解している。(が、そもそもアプリ側が脆弱だったりするとやっぱりシークレットは漏れる)

で、これをなんとかするための仕様がPKCE。

どうやるか?

  1. クライアントはcode_verifierという暗号学的に安全な乱数を生成し、そこからcode_challengeを生成して、認可リクエストに含める
    • このときcode_challenge_method、というパラメータを含めても良い
    • code_challenge_methodが指定もしくはPLAINの場合、code_challengeはcode_verifier
    • code_challenge_methodがSHA256の場合、code_challengeはBASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
  2. サーバーは認可コードをレスポンスする
    • このとき発行した認可コードと、クライアントが送信したcode_challenge、code_challenge_methodの値を紐づけて保持しておく
  3. クライアントはトークンリクエストの際に、認可リクエストの時に生成したcode_verifierをパラメーターを含める
  4. サーバーはトークンリクエストに含まれるcode_verifierから生成したcode_challengeが、認可リクエストで送信されてきたcode_challengeと同じかどうかを検証する
    • 異なっていた場合、エラーにする

これでなんでトークンが盗まれるのを防げるのか

  • 悪意のあるアプリは、認可コードは盗めるが、認可リクエストの内容は盗めない(盗めるケースについては後述)
  • ので、悪意のあるアプリはトークンリクエストで送信すべきcode_challengeの値がわからない
  • ので、悪意のあるアプリはトークンを発行できない

気になった仕様

サーバーが認可コードとクライアントが送信したcode_challenge、code_challenge_methodの値をどう保持するか

具体的に仕様では規定されてないんだけど、

Typically, the "code_challenge" and "code_challenge_method" values are stored in encrypted form in the "code" itself but could alternatively be stored on the server associated with the code. The server MUST NOT include the "code_challenge" value in client requests in a form that other entities can extract.

とあって、認可コードに暗号化して埋め込んじゃう話がある 認可コードをJWEにしちゃう、とかでいいはず ここの実装時にここの永続化がだるそうだなと思っていて、なるほど感があった

code_challenge_methodがSHA256だと何を守れるのか

 4b. A more sophisticated attack scenario allows the attacker to
      observe requests (in addition to responses) to the
      authorization endpoint.  The attacker is, however, not able to
      act as a man in the middle.  This was caused by leaking http
      log information in the OS.  To mitigate this,
      "code_challenge_method" value must be set either to "S256" or
      a value defined by a cryptographically secure
      "code_challenge_method" extension.

攻撃者が認可リクエストも見れちゃった場合、code_challenge=code_verifierだと認可リクエストに含まれるcode_challengeをそのままトークンリクエストに含めればトークンが取得できてしまう。 が、code_challengeがSHA256でハッシュ化してあると攻撃者はcode_verifierがわからないので、トークンを取得できない。

クライアントが認可リクエストにcode_challengeを指定しなかった場合は?後からPKCE対応したらどうなる?

If the server requires Proof Key for Code Exchange (PKCE) by OAuth public clients and the client does not send the "code_challenge" in the request, the authorization endpoint MUST return the authorization error response with the "error" value set to "invalid_request".

なので、エラーにしないといけない、が、5. Compatibilityに

Server implementations of this specification MAY accept OAuth2.0 clients that do not implement this extension. If the "code_verifier" is not received from the client in the Authorization Request, servers supporting backwards compatibility revert to the OAuth 2.0 [RFC6749] protocol without this extension.

とある。

認可リクエストで送信するのが"code_verifier"となっている意味がよくわからない(認可リクエストで送るのは"code_challenge"じゃないのか?)が、認可リクエストに"code_challenge"が含まれてなければPKCEしない、で良いのかな。 トークンリクエストに"code_verifier"がなかったら検証なし、だとそもそも成立しない(悪意のあるアプリがトークンを取得できてしまう)ので、それは違うと思うんだけども・・・。

qiita.com

この記事で紹介されているコードだと、認可リクエストに"code_challenge"が指定されてなかったらトークンリクエストの"code_verifier"をスキップしてるっぽいので、多分そういうことなんだろうな、と思う。(多分・・・)