🔑

GoでWebauthを試してWeb Authenticationで登録する流れを追う

2023/08/02に公開

概要

下記で提供されているWebAuthn関係のライブラリのexampleの動くものを作って、体系的にWebAuthnの理解をしたかった。
https://github.com/go-webauthn/webauthn

動くサンプルのソースコードは下記。
https://github.com/subkaitaku/webauthn-example

goのversionを合わせて、下記のコマンドを実行し、http://http://localhost:8080/にアクセスすれば再現できると思います。

$ go mod tidy
$ go run .

UI

登録







ログイン



registerしていないログインは失敗する

コード解説

私はセキュリティの専門家ではないので、情報の正当性については責任を負いかねます。

登録

BeginRegistration()

webauthnライブラリに依存する部分は下記です。
①: registerOptionsという無名関数を定義、webauthnのprotocolのPublicKeyCredentialCreationOptionsを引数にとって、CredentialExcludeListにuser.CredentialExcludeList()を代入。

②: ユーザーと①で作成した無名関数を渡して、返却値で使用するoptionsと、クッキーで使用するセッションデータを作成。あとで"registration"という名前のクッキーでHTTPヘッダーに込めて返却。

func BeginRegistration(w http.ResponseWriter, r *http.Request) {
..
        // ①
	registerOptions := func(credCreationOpts *protocol.PublicKeyCredentialCreationOptions) {
		credCreationOpts.CredentialExcludeList = user.CredentialExcludeList()
	}
	..
	// ②
	options, sessionData, err := Wc.BeginRegistration(
		user,
		registerOptions,
	)

webauthnのメソッドである、BeginRegistrationを見ていきます。
https://github.com/go-webauthn/webauthn/blob/master/webauthn/registration.go#L22

  • サーバーでchallengeというランダム値を生成
  • 渡したuserとconfigから、構造体を作成
  • defaultRegistrationCredentialParametersはアルゴリズム達がある
  • 初期化した上記の構造体達を使って、登録時の公開鍵生成の構造体を作成
  • urlエンコードされたchallengeやuser情報をセッションデータを作成
  • 秘密鍵生成の構造体とセッションデータを返却

これで、jsonでクライントに一旦返却します。

BeginRegistration()後のクライアント(index.js記載の処理)
  • 返却された公開鍵生成の構造体をデコードして、チャレンジ/ユーザーID/公開鍵を取り出し、公開鍵を持って標準化されたウェブ認証APIを呼び出す
  • navigator.credentials.create()で認証器(MacbookやYubiKey)に登録
  • navigator.credentials.create()の返却値の認証情報を用いて、サーバーにPOSTでFinishRegistration()を叩く
FinishRegistration()
  • "registration"という名前で保存したクッキーから、セッション情報を復元
  • クライアントからの認証情報をライブラリでパースし、ユーザー情報/セッション/パースされた認証情報を照合し、Credential構造体を作成
  • Credential構造体をuserのcredentialsに入れて保存し、セッションを削除し登録完了です。(※credentialsはuser.goに下記で定義されており、名前は任意)
type User struct {
	id          uint64
	name        string
	displayName string
	credentials []webauthn.Credential
}

次回はログイン周りを見ていきたいと思います。
読んでいただきありがとうございました!

参考

https://techblog.yahoo.co.jp/advent-calendar-2018/webauthn/#navigatorcredentialscreate
https://gihyo.jp/dev/column/newyear/2019/webauthn
https://qiita.com/okamoai/items/bee403e3311cda20fe03

Discussion