buddyのユーザ認証周りのデータ構造 -...

29
buddyのユーザ認証周りのデータ構造 使われているデータの取り回しについてのお話 2017/11/17 clj-ebisu #1

Upload: kazuhiro-hara

Post on 28-Jan-2018

136 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

buddyのユーザ認証周りのデータ構造使われているデータの取り回しについてのお話

2017/11/17clj-ebisu #1

Page 2: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

出演

{:company “Greative.GK” :name “Kazuhiro Hara” :twitter “@kara_d” :interest “SPA, WebVR, Clojure, Design research”}

Page 3: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

Clojure / ClojureScript で

Electronアプリケーションを

作るためのスタートキット / プラットホーム

● オープンソースにてGitHubにて公開

● MITライセンス

● 現在のスター数 : 329http://descjop.org/

Page 4: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

今日お話しすること

Page 5: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

今日お話しすること

buddy-authのidentity実装をみてたときに、

リクエストマップに対するmiddlewareの使い方で

アハ体験した話

Page 6: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

buddyってなにさ、というあたりから

Page 7: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

buddyについて

buddy is a complete security library for clojure. With support for:

● authentication, authorization & access rules (ring/compojure extensions)

● secure hash functions (digest)

● password hashing algorithms (bcrypt, pbkdf2, scrypt)

● message/text signing (high level interface)

● signature & authentication (mac & digital signature)

● encryption (block, stream ciphers, nonces, salts)

● key derivation functions (kdf)

Page 8: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

buddyのパッケージ

● buddy-core

● buddy-auth

● buddy-hashers

● buddy-sign

Page 9: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

buddyのパッケージ

● buddy-core

● buddy-auth ⇦ 今日はこのあたりの話

● buddy-hashers

● buddy-sign

Page 10: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

ユーザの認証・認可を実装するとき、お世話に

● 認証スタイルも、Basic、セッション、トークン、JWS、JWEといろいろ

● 特定ルート以下に適用するとかも楽

(def access-rules {:pattern #"^/admin.*" :handler authenticated-user?})

(-> app-routes (wrap-access-rules {:rules [ access-rules]}) (wrap-authentication backend) (wrap-authorization backend) (wrap-session {:store (session-cookie/cookie-store {:key key}) :cookie-attrs attr :cookie-name name})

Page 11: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

buddy-authを使った認証の一例セッションベース

Page 12: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

buddy-authを使った認証の一例(リクエスト編)

1. 認証対象のパスへアクセス( /admin とか)

2. セッションから認証済みかどうか確認

3. 認証済みであれば、リクエストマップへ :identity キーを追加3.1. 必要な処理をして、レスポンスを返す

4. 認証済みでなければ、:unauthorized-handler を実行4.1. エラー表示など

(defn wrap-authentication [handler & backends] (fn [request] (if-let [authdata (authenticate-request request backends)] (handler (assoc request :identity authdata)) (handler request))))

Page 13: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

buddy-authを使った認証の一例(ログイン編)

1. ログインフォームから、認証に必要な情報を送信

2. 認証に必要な情報を照会

3. 認証OKであれば :identity キーをセッションに書き込む3.1. 適切な処理を行う、もしくはリダイレクト

3.2. identity のセッションへの書き込みは、自前で行う

4. 認証NGであれば、ログインフォームに戻るなどの処理をする

(-> (redirect next) (assoc :session updated-session))

Page 14: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

認証されたリクエストかの確認

authenticated?関数でチェックができる

やっていることはシンプル

(defn authenticated-user? [request] (if (auth/authenticated? request) (accessrules/success) (accessrules/error)))

(defn authenticated? [request] (boolean (:identity request)))

Page 15: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

更に、identityについて

Page 16: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

identityには何が格納できる?

よくあるサンプルでは「ユーザー名」

中身は、edn形式の {:identity :admin} になる

そこで生まれる疑問、ユーザー名じゃないとだめなのか

結局、edn形式になるので、ednとして表現できるものならなんでもつっこめる

Page 17: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

identityにマップを入れたらどうなる?

:identityに {:username :user, :role :admin} を入れてみる

cookieのセッション領域には、H/XbI0K3JU9TGMoyoGN16Ud2q4n8paIavLMFO+PQcqtXd3PtBIh9jmkg04FvqFuDXSYBlCbYAfMu8GhzE9ZFYQ==--BxvDyxfR0dtzjBiZqVPihT

ld/sLIYvI9hRycPtTQ1nM=などが入り、

中身は、{:identity {:username :user, :role :admin}} となる

Page 18: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

identityに関数をつっこむと?

:identity に、例えば (fn [a] (println a)) を入れてみる

シリアライズに失敗してランタイムエラー

java.lang.RuntimeExceptionNo reader function for tag object

Page 19: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

identityの不思議さ

今まで使ってきたWebアプリケーションフレームワークのリクエスト情報の利用スタイルで

は、リクエストオブジェクト的なものは、読みこんで利用するだけ

public Result index() { String username = session("identity"); if(username != null) { return ok("Hello " + username); } else { return unauthorized("Oops, you are not connected"); }}

Page 20: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

よくあるリクエスト情報の処理

リクエストは、専用のコンテキストオブジェクトなどに格納され、それがコントローラを通じ

て、モデルなどで利用される

request controller

service

model

Page 21: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

リクエストデータとミドルウェアパターン

最初、Clojureを触ったときは、requestには手を触れなかったが(ミドルウェアは利用して

いたものの)、変えるだけでなく、キーの追加もいいという驚き。

Middleware Patterns · ring-clojure/ring Wiki

https://github.com/ring-clojure/ring/wiki/Middleware-Patterns

request wrap-foo request wrap-bar request wrap-baz request

Page 22: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

まとめ

Page 23: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

ベルトコンベアのような認証プロセス

requestをもらって、コントローラ受け取って処理をして、responseを返すというスタイルだ

けでないやりかたに感銘を受けた。

個人的には、buddy-authのidentity実装には、Clojureで開発をしていく上でヒントになる

と感じたものが見れた。

フラグを立てるところと、フラグに基づいた処理をするところは別でもいい

受け取ってたらい回しにして処理するしかないようなものも、ミドルウェアとして組み合わ

せることで、独立性が高い実装が行える

Page 24: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

こぼれ話

Page 25: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

セッションの中身はどうなるのか?

Page 26: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

セッションに書き込まれたidentityは信用できるか

ring.middleware.session.cookie に実装がある

● HmacSHA256○ SHA-256で構築された、ハッシュメッセージ認証コードとして使用可能なキー付きハッシュアルゴリ

ズムの一種

● AES/CBC/PKCS5Padding○ データ本体はAES暗号化

Page 27: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

セッションの中を見る

開発側からは見れます

中身は、edn形式の {:identity :admin} になる

(let [cookieStore (session-cookie/cookie-store {:key "d41d8cd98f00b204"}) cookie-read (session-store/read-session cookieStore "LcgrPJu3zE0/Pvd0cSFo29jE/IlLlwRAa6Jo99FCZF9WKoJj/5bOLbp8g2mAB585--QB0LJInHfOCBH8kUwSIcOnrWqq7Ldk6wcHwinX/Kqug=")] (println (str cookie-read)))

Page 28: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

CookieStore本体は見れない

ns-unmapされている

中身はこう

(deftype CookieStore [secret-key] SessionStore (read-session [_ data] (if data (unseal secret-key data))) (write-session [_ _ data] (seal secret-key data)) (delete-session [_ _] (seal secret-key {})))

(ns-unmap *ns* '->CookieStore)

Page 29: buddyのユーザ認証周りのデータ構造 - 使われているデータの取り回しについてのお話

- END -ありがとうございました

2017/11/17clj-ebisu #1