Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Firebase Authenticationのセッション管理術
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
Managed Agents API は Google Cloud の運用の夢を見ることはできるか?
satohjohn
0
37
BigQuery を検索ソースとした AI Agent の作り方って 〇〇 通りあんねん
satohjohn
0
250
Claude Codeで評価を楽にする
satohjohn
0
120
A2UI という光を覗いてみる
satohjohn
1
270
_Architecture_Modernization_から学ぶ現状理解から設計への道のり.pdf
satohjohn
2
1.4k
アーキテクチャモダナイゼーションを実現する組織
satohjohn
1
1.8k
Vertex_AI_Searchを使いこなす実践テクニック
satohjohn
1
330
アーキテクチャモダナイゼーションの書籍紹介
satohjohn
0
90
NVIDIA NeMo Agent Tooklit を使ってみた
satohjohn
0
190
Other Decks in Programming
See All in Programming
flutter_test のその先へ — Flutter アプリの LLM 機能に「評価」という品質保証を
kosukesaigusa
0
180
[2026-10-14](C)Re:ゼロから始める異世界生活〜始まりの終わりと終わりの始まり〜
tosite
0
310
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
14
11k
Enforcing Your Architecture with Unit Tests in the AI Era (Swift Connection X)
steliosf
PRO
1
120
エージェントを使い続けるためのメタワーク / Meta-work for keeping using the agent
rkaga
6
2.2k
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
4
3k
Performance Optimization With LLMs
xleitix
0
240
Vue.jsで作る空間解析アプリとCapacitorプラグインのData Bridge
hal_spidernight
1
160
Event is what happens
moro
2
3.4k
AI-Powered Domain-Driven Design
ziobrando
0
380
Inertia Rails: The One-Person Framework with React & Friends
skryukov
0
380
Python Lambdaにおけるテストしやすい設計とAI支援の活用 / Designing Testable Python Lambda Functions with AI
kitano_yuichi
1
290
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.9k
For a Future-Friendly Web
brad_frost
184
11k
Marketing to machines
jonoalderson
1
6k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
GitHub's CSS Performance
jonrohan
1033
470k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
320
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
310
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
450
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
620
Designing for Timeless Needs
cassininazir
1
550
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
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とかでメンションなどでご相談していただければ!
おわり