Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Firebase Authenticationのセッション管理術
Search
SatohJohn
July 07, 2023
Programming
2.7k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Firebase Authenticationのセッション管理術
7/7 PORT Firebase meetup
https://connpass.com/event/285741/
発表させていただいた資料です
SatohJohn
July 07, 2023
More Decks by SatohJohn
See All by SatohJohn
BigQuery を検索ソースとした AI Agent の作り方って 〇〇 通りあんねん
satohjohn
0
190
Claude Codeで評価を楽にする
satohjohn
0
99
A2UI という光を覗いてみる
satohjohn
1
210
_Architecture_Modernization_から学ぶ現状理解から設計への道のり.pdf
satohjohn
2
1.3k
アーキテクチャモダナイゼーションを実現する組織
satohjohn
1
1.6k
Vertex_AI_Searchを使いこなす実践テクニック
satohjohn
1
260
アーキテクチャモダナイゼーションの書籍紹介
satohjohn
0
70
NVIDIA NeMo Agent Tooklit を使ってみた
satohjohn
0
150
Gemini Enterprise を恐れない - Securityと監査-
satohjohn
0
230
Other Decks in Programming
See All in Programming
Webエンジニアなのにブラウザの仕組みがわからないので、Pythonで自作してみた
tatsuki12
4
1.1k
FastAPI の並行処理モデルを完全に理解する
hoto17296
8
3.2k
高専キャリア LT 発表内容
crysta1221
4
4.3k
複数の Claude Code が"放置"されてしまう問題をCLI ダッシュボードを自作して解決した話
sumihiro3
1
740
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
650
DynamoDBの基礎を振り返りながらベクトル検索機能を理解する
musan
3
240
プロポーザルを書いてもらう
pvcresin
0
590
自動化したのに回らない テスト運用の壁―AI時代の品質責任と生産性
mfunaki
0
530
ソフトウェアラスタライザ
fadis
1
720
KotlinConf Extended South Korea 2026 Keynote
l2hyunwoo
0
120
「つくるAI」だけではバグは見つからない ~テストに必要な「見つけるAI」を分離させる戦略~
mfunaki
0
200
業務時間外もAIに働いてもらう話
colorful12
2
8.7k
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
670
ラッコキーワード サービス紹介資料
rakko
1
4.6M
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
260
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
390
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.5k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
What does AI have to do with Human Rights?
axbom
PRO
1
2.3k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.6k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
Transcript
Firebase Authenticationの セッション管理術 2023/07/07 PORT Firebase meetup 株式会社スリーシェイク 佐藤慧太
自己紹介 • 株式会社スリーシェイク Sreake事業部 • 佐藤慧太@SatohJohn • SREとしてお客様の労苦<Toil>を減らす仕事 • Google
Cloudの製品が好き • FirebaseでのWebアプリケーション経験4年ぐらい
株式会社スリーシェイクについて Copyright © 3-shake, Inc. All Rights Reserved. xOps
Plattform DesignOps IaaS DevOps / SRE RevOps (Revenue Ops) HR(Engineer Hiring) HROps Data Engineering DataOps Security DevSecOps SecOps 事業者が抱える セキュリティリスクを無くす 本格的な脆弱性診断を 無料で手軽に セキュリファイ Security 良いエンジニアに良い案件を フリーランスエンジニアに 「今よりいい条件」を リランス HR(Engineer Hiring) あらゆるサービスを連携する ハブになる クラウド型ETL/データパイプ ラインサービスの決定版 レコナー Data Engineering 日本のSREをリード SRE総合支援からセキュリティ 対策を全方位支援 スリーク SRE スリーシェイク = xOps領域のプラットフォーマーへ
Session管理って めんどくさいですよね?
本日伝えたいこと • Webアプリケーションでの Firebase Authenticationのセッション管理方法について ◦ Cookie ◦ idTokenとService Worker
本日伝えたいこと • Webアプリケーションでの Firebase Authenticationのセッション管理方法について ◦ Cookie ◦ idTokenとService Worker
実装できる(気がする)まで持っていく
話さないこと • Service workerの詳しい説明 ◦ fetchしかでてきません • Firebase Authenticationの詳しい説明 ◦
Login後のどう管理するかだけです
超概略的まとめ • idTokenはaccess tokenのようなもので、有効期限がとても短い • idTokenをcookieに変換して利用する ◦ サーバ側で検証、処理をするイメージ • service
workerを使って、idTokenのまま利用する ◦ フロント側で検証、処理をするイメージ
Cookieの利用
Cookieでの管理のメリット • ブラウザが保存、取り出しをしてくれるため フロントで処理を記載する必要がない • 初回アクセス時にサーバ側で処理できる • 古いブラウザでも対応している
Cookieでの管理のデメリット • Cookieの作成の口を用意しないといけない • 色々なアプリで展開している場合、Cookie用の検証用の口を サーバサイドで用意しないと行けない • 他Firebase製品をフロントで使う場合や、Password変更など 組み合わせる際に、セッション管理が別になり、複雑になる
Cookieシーケンス Login部分 • Firebaseでのログインをした後 idTokenを取得する • idTokenをもとにCookieを サーバで作成してもらう • ログイン状態の2重管理になるた
め以下を注意する ◦ Firebase Authentication の情報保存をoffにするこ と ◦ Cookieの保存後に Firebase Authentication でログアウトすること
Cookieシーケンス Login部分 • Firebaseでのログインをした後 idTokenを取得する • idTokenをもとにCookieを サーバで作成してもらう • ログイン状態の2重管理になるた
め以下を注意する ◦ Firebase Authentication の情報保存をoffにするこ と ◦ Cookieの保存後に Firebase Authentication でログアウトすること
実装(フロント) • ログイン方法は別になんでもよく idTokenが取得できれば良い • Cookie取得のリクエストが成功す ればCookieが自動的に ブラウザに保存される import {
signInWithEmailAndPassword, } from "firebase/auth"; export const loginWithEmailAndPassword = (auth, email, password) => { return signInWithEmailAndPassword(auth, email, password) .then(async (result) => { const idToken = await result.user.getIdToken(); return login(idToken); }) }; export const login = (idToken) => { return fetch("/auth/authenticate", { method: "POST", data: { id_token: idToken, }, }).then((data) => data.json()) };
実装(サーバ) • フロントから送られてきたidToken を使ってCookieを 組み立てる • CookieにHTTP OnlyとSecure属 性をつけることを忘れない def
authenticate(request): id_token = request.POST.get("id_token") if id_token is None or len(id_token) == 0: return HttpResponse("id token not found", status=400) session_cookie = create_session_cookie(id_token) if session_cookie is None: return HttpResponse("Failed to create a session cookie", status=401) response = HttpResponse() response.set_cookie( session_cookie["name"], value=session_cookie["value"], expires=session_cookie["expires"], secure=True, httponly=True, samesite="Lax", ) return response
実装(サーバ) • idTokenをデコードすると認証した 時間が取れる • 認証した時間から公式では 5分以内であることで不正ではな いことを担保している • Cookieで使える値は最大14日間
の有効期限なのでCookieもその 時点で消えるようにしておく from firebase_admin import auth def create_session_cookie(id_token): decoded_claims = auth.verify_id_token(id_token) if time.time() - decoded_claims["auth_time"] < 5 * 60: expires_in = datetime.timedelta(days=14) expires = datetime.datetime.now() + expires_in session_cookie = auth.create_session_cookie(id_token, expires_in=expires_in) return build_session_cookie(expires, session_cookie) return None def build_session_cookie(expires, session_cookie): return {"expires": expires, "value": session_cookie, "name": LOGIN_COOKIE_NAME}
cookieシーケンス リクエスト部分 • ブラウザがリクエスト時にCookie をつける • 検証結果に応じて処理を 実施する
実装(サーバ) • Cookieからclaim取得して それからUserを取得する • userが取得できない場合は 403エラーとしても良いし 未ログインでも使えるように してもよい •
Pythonの例ではあるが FrameworkのMiddleware上で 実装するのが良い class RequiredAuthorizedMiddleware: get_response = None REQUIRED = "required" KEY = "auth" REQUIRED_DICT = {KEY: REQUIRED} def __init__(self, get_response): self.get_response = get_response def process_view(self, request, view_func, view_args, view_kwargs): claim = auth.verify_session_cookie(request.COOKIES.get(LOGIN_COOKIE_NAME)) if self.authorized(claim, request): request.login_user = convert_login_user(claime) return None return HttpResponse("fobidden", status=403) def authorized(self, claim, request): if claim is None: return False return True
idTokenとservice worker
idTokenとservice workerのメリット • 作成の変換コストがcookieより少ない • client、Firebase間でidTokenの更新をするため、サーバ側での期限切れがパ ターンが少ない • idToken作成に使うrefresh tokenがcookieよりも生存する期間が長いため
再度Loginページ表示が少なくて済む • iOS、Androidと同じような処理で、サーバ側で認証ができる
idTokenとservice workerのデメリット • idTokenの期限が1時間なので、作り直しはcookieより多い • 古いブラウザなどでService Workerに対応していない可能性がある • 初回アクセス時にサーバ側で処理しないため、要件とは合わない可能性がある
service worker シーケンス • Cookieのときと、ログインまでは 変わらない • HTMLを受け取りservice worker を、インストールする部分が入って
いる
実装(フロント) • Firebase Authenticationで ログインをするだけ import { signInWithEmailAndPassword } from
"firebase/auth"; export const loginWithEmailAndPassword = (auth, email, password, afterLogin) => { return signInWithEmailAndPassword(auth, email, password) .then(async (result) => { return afterLogin(); }) };
service worker シーケンス • idTokenが取得できない場合は Loginページに遷移させる ◦ サーバで処理する場合も 検証は必要なので 2箇所見る必要がある
実装(フロント) • getIdTokenの際にtokenが取得で きるかをみて リダイレクトさせる • httpRequestの際にリクエストをプ ロキシすることができるので同じ ホストの場合 Headerに追加する
• 公式で公開されているコードがあ るのでそちらを見ながら 触ってみると良いかと self.addEventListener("fetch", (event: Event) => { const fetchEvent = event as FetchEvent; const requestProcessor = (idToken: string | null) => { let req = fetchEvent.request; let processRequestPromise = Promise.resolve(); if (self.location.origin == getOriginFromUrl(fetchEvent.request.url)) { const headers = new Headers(); for (let entry of req.headers.entries()) { headers.append(entry[0], entry[1]); } headers.append("Authorization", "Bearer " + idToken); processRequestPromise = getBodyContent(req).then((body) => { req = new Request(req.url, { method: req.method, headers: headers, mode: "same-origin", credentials: req.credentials, cache: req.cache, redirect: req.redirect, referrer: req.referrer, body: body as string, }); }); } return processRequestPromise.then(() => fetch(req)); }; fetchEvent.respondWith(getIdToken().then(requestProcessor)); });
実装(サーバ) • headerからidTokenを取得し フロントで行えないユーザ別の処 理を行う事ができる • この形はアプリでも同じ形に なるはず function getIdToken(req)
{ const authorizationHeader = req.headers.authorization || ''; const components = authorizationHeader.split(' '); return components.length > 1 ? components[1] : ''; } app.get("/something", (req, res) => { const idToken = getIdToken(req); admin .auth() .verifyIdToken(idToken) .then((decodedClaims) => { return res.json(something(decodedClaims)) }) .catch((error) => { console.log(error); res.status(403); res.json({ error: "You must be logged in to continue!" }); }); });
実装(フロント) • サーバとの通信とは関係なく ログイン中のユーザの情報を 取得できる • ログイン中のユーザ情報はauthイ ンスタンスから取得する ◦ idTokenから取得できるレ
ベルではある export const getLoginUser = (auth): Promise<User | null> => { return new Promise((resolve, reject) => { const subscribe = auth.onAuthStateChanged((user) => { subscribe(); resolve(user); }); }); };
まとめ • どっちが良いということはなく、サービスの特性に合わせて利用する ◦ idTokenをcookieに変換して利用する ▪ 処理をサーバで実施するようなパターン ▪ MPAのアプリケーションと相性が良い ◦
service workerを使って、idTokenのまま利用する ▪ 処理をフロントで実施するようなパターン ▪ SPAのアプリケーションと相性が良い
一緒にSREとして働きませんか? • 社会から労苦<Toil>をなくしましょう ◦ 気になりましたら会社ホームページやどんなメンバがいるのか を見ていただき 申し込みしていただければ! ◦ または、私の方にtwitterとかでメンションなどでご相談していただければ!
おわり