@hackage firebase-hs0.3.0.0
Firebase Auth, Firestore, and Servant integration for Haskell
Categories
License
BSD-3-Clause
Maintainer
devon.tomlin@novavero.ai
Links
Versions
Installation
Tested Compilers
Dependencies (15)
- aeson >=2.0 && <2.4
- base >=4.18 && <5
- base64-bytestring >=1.2 && <1.3
- bytestring >=0.11 && <0.13
- containers >=0.6 && <0.9
- crypton >=0.31 && <2 Show all…
Dependents (0)
Package Flags
wai
(off by default)
Enable WAI auth middleware (Firebase.Auth.WAI)
servant
(off by default)
Enable Servant auth combinator (Firebase.Servant)
firebase-hs
Firebase for Haskell:
- Auth: Firebase ID token (JWT) verification against Google's public keys, with RS256 via crypton and automatic key caching
- Firestore: CRUD, structured queries, and atomic transactions over the REST API
- WAI / Servant: auth middleware and an auth combinator, each behind an optional cabal flag
Full API documentation lives on Hackage.
Install
build-depends: firebase-hs
The web integrations are off by default; enable the ones you use:
cabal build -f wai # Firebase.Auth.WAI
cabal build -f servant # Firebase.Servant
Auth
import Firebase.Auth
main :: IO ()
main = do
cache <- newTlsKeyCache
let cfg = defaultFirebaseConfig "my-project-id"
result <- verifyIdTokenCached cache cfg tokenBytes
case result of
Left err -> putStrLn ("Auth failed: " ++ show err)
Right user -> putStrLn ("UID: " ++ show (fuUid user))
Build one KeyCache at startup and share it across threads; keys refresh
automatically per Google's Cache-Control header.
A token is accepted only if every one of these holds:
| Check | Rule |
|---|---|
| Algorithm | RS256 only |
| Signature | Must match a Google public key |
| Issuer | https://securetoken.google.com/<projectId> |
| Audience | Must equal your Firebase project ID |
| Expiry / issued-at | exp in the future, iat in the past, within clock skew |
| Subject | sub non-empty (becomes the Firebase UID) |
Roles live in custom claims, set by the Admin SDK's setCustomUserClaims:
if hasClaim "admin" user then handleAdmin user else refuse
Firestore
import qualified Data.Map.Strict as Map
import Firebase.Firestore
main :: IO ()
main = do
fs <- newFirestore (ProjectId "my-project") (AccessToken "ya29...")
let path = DocumentPath (CollectionPath "users") (DocumentId "alice")
_ <- createDocument fs (CollectionPath "users") (DocumentId "alice")
(Map.fromList [("name", StringValue "Alice"), ("age", IntegerValue 30)])
_ <- updateDocument fs path ["age"] (Map.fromList [("age", IntegerValue 31)])
doc <- getDocument fs path
print doc
Build one Firestore handle and share it; it holds a pooled connection
manager. Access tokens expire, so swap in a fresh one with withToken
rather than rebuilding the handle.
Queries compose with (&); subcollections are addressed by path:
import Data.Function ((&))
result <- runQuery fs $
query (CollectionPath "users")
& where_ (fieldFilter "age" OpGreaterThan (IntegerValue 18))
& orderBy "age" Ascending
& limit 10
Transactions read with the transaction ID and return the writes to commit.
On any failure the transaction is rolled back, and losing a contention race
surfaces as TransactionAborted:
result <- runTransaction fs ReadWrite $ \txnId -> runExceptT $ do
doc <- ExceptT (getDocumentInTransaction fs txnId path)
pure [mkUpdateWrite (fsProject fs) path (applyDebit 100 (docFields doc))]
WAI
import Firebase.Auth (newTlsKeyCache, defaultFirebaseConfig)
import Firebase.Auth.WAI (requireAuth)
import Network.Wai.Handler.Warp (run)
main :: IO ()
main = do
cache <- newTlsKeyCache
let cfg = defaultFirebaseConfig "my-project-id"
run 3000 (requireAuth cache cfg myApp)
firebaseAuth additionally stores the verified FirebaseUser in the
request vault for lookupFirebaseUser to read downstream.
Servant
import Firebase.Auth (newTlsKeyCache, defaultFirebaseConfig)
import Firebase.Servant (firebaseAuthHandler)
import Servant.Server (Context (..))
main :: IO ()
main = do
cache <- newTlsKeyCache
let cfg = defaultFirebaseConfig "my-project-id"
ctx = firebaseAuthHandler cache cfg :. EmptyContext
runSettings defaultSettings (serveWithContext api ctx server)
Build and Test
cabal build all -f wai -f servant --enable-tests --ghc-options="-Werror"
cabal test
BSD-3-Clause. Maintained by Gondola Bros Entertainment.