Skip to main content

kiarina-lib-firebase

PyPI version Python License: MIT

English | 日本語

[!NOTE] What is this? An asynchronous Firebase Authentication client for exchanging custom tokens and keeping ID tokens fresh.

Dependencies

Package Version License
HTTPX >=0.28.1 BSD-3-Clause
kiarina-utils-common >=2.10.0 MIT
kiarina-utils-file >=2.3.1 MIT
Pydantic >=2.10.6 MIT
Pydantic Settings >=2.10.1 MIT
pydantic-settings-manager >=3.2.0 MIT

Installation

pip install kiarina-lib-firebase

Features

  • Exchanging a Custom Token Exchange a Firebase custom token for a token set.
  • Refreshing an ID Token Retrieve a new token set from a refresh token.
  • Managing the Token Lifecycle Refresh an ID token before expiration and serialize concurrent refreshes.
  • Persisting the Token Keep the token set in a file, in memory, or in a store of your own.
  • Sharing a Token Manager Build a token manager from settings and get it anywhere in the application.
  • Managing Multiple Configurations Manage multiple Firebase configurations with pydantic-settings-manager.

Exchanging a Custom Token

Exchange a custom token issued by the Firebase Admin SDK or another trusted environment.

from kiarina.lib.firebase import exchange_custom_token

token = await exchange_custom_token(
    custom_token="firebase-custom-token",
    api_key="firebase-web-api-key",
)

print(token.uid, token.project_id, token.expires_at)

Token stores only refresh_token and id_token. Everything else is read from the ID token, so the values can never disagree with it.

An invalid custom token raises InvalidCustomTokenError. Other Firebase API errors and communication failures raise FirebaseAPIError.

Refreshing an ID Token

Retrieve a new token set from an existing one. TokenManager does this on its own, so call it directly only when managing the lifecycle yourself.

from kiarina.lib.firebase import refresh_id_token

token = await refresh_id_token(token, api_key="firebase-web-api-key")

The refresh token in the returned set carries over. An invalid or expired refresh token raises InvalidRefreshTokenError.

Managing the Token Lifecycle

TokenManager refreshes an ID token before it expires. By default, it refreshes when no more than 300 seconds remain.

from kiarina.lib.firebase import InMemoryTokenStore, TokenManager

manager = TokenManager(
    api_key="firebase-web-api-key",
    token_store=InMemoryTokenStore(token),
)

token = await manager.get_token()

The manager reads and writes the token set through a TokenStore, and holds no other state.

Persisting the Token

FileTokenStore keeps the token set in a JSON file, so a restart resumes from the stored refresh token.

from kiarina.lib.firebase import FileTokenStore, TokenManager

manager = TokenManager(
    api_key="firebase-web-api-key",
    token_store=FileTokenStore("~/.config/your-app/token.json"),
)

token = await manager.get_token()

InMemoryTokenStore keeps the token set in the process only. Implement TokenStore for any other backend.

Sharing a Token Manager

create_token_manager builds a TokenManager from the settings, so the API key and the token file live in one place.

kiarina.lib.firebase:
  default: production
  configs:
    production:
      api_key: production-api-key
      token_file_path: ~/.config/your-app/token.json
from kiarina.lib.firebase import create_token_manager

manager = create_token_manager()
token = await manager.get_token()

token_manager_registry does the same, and keeps the manager so the whole application shares one.

from kiarina.lib.firebase import token_manager_registry

# Anywhere in the application
token = await token_manager_registry.get().get_token()

get() without a name uses the same settings as settings_manager, so it follows default and settings_manager.active_key. Each name is built once and reused.

Register an instance to use a different TokenStore. A registered instance takes priority over the settings.

from kiarina.lib.firebase import TokenManager, token_manager_registry

token_manager_registry.register(
    "production",
    TokenManager(
        api_key="firebase-web-api-key",
        token_store=your_token_store,
    ),
)

Managing Multiple Configurations

settings_manager uses multi-configuration mode. In the pydantic-settings-manager v3 structured format, named settings are placed under configs.

kiarina.lib.firebase:
  default: production
  configs:
    development:
      api_key: development-api-key
      token_file_path: ~/.config/your-app/development.json
    production:
      api_key: production-api-key
      token_file_path: ~/.config/your-app/production.json

Load the configuration during application bootstrap.

import yaml
from pydantic_settings_manager import load_user_configs

from kiarina.lib.firebase import settings_manager

with open("config.yaml", encoding="utf-8") as file:
    load_user_configs(yaml.safe_load(file) or {})

settings = settings_manager.get_settings("production")

To configure only this package directly, assign the structured format to settings_manager.user_config.

from kiarina.lib.firebase import settings_manager

settings_manager.user_config = {
    "default": "production",
    "configs": {
        "development": {"api_key": "development-api-key"},
        "production": {"api_key": "production-api-key"},
    },
}

settings = settings_manager.get_settings()

A single configuration can also be supplied through environment variables.

export KIARINA_LIB_FIREBASE_API_KEY="your-api-key"
export KIARINA_LIB_FIREBASE_TOKEN_FILE_PATH="~/.config/your-app/token.json"

API Reference

kiarina.lib.firebase

from kiarina.lib.firebase import (
    FileTokenStore,
    FirebaseAPIError,
    FirebaseAuthError,
    FirebaseSettings,
    InMemoryTokenStore,
    InvalidCustomTokenError,
    InvalidRefreshTokenError,
    Token,
    TokenManager,
    TokenStore,
    create_token_manager,
    exchange_custom_token,
    refresh_id_token,
    settings_manager,
    token_manager_registry,
)

exchange_custom_token

async def exchange_custom_token(
    custom_token: str,
    api_key: str,
) -> Token: ...

Exchange a Firebase custom token for a token set.

Raises

  • InvalidCustomTokenError: The custom token is invalid
  • FirebaseAPIError: The Firebase API returns another error or communication fails

refresh_id_token

async def refresh_id_token(
    token: Token,
    api_key: str,
) -> Token: ...

Retrieve a new token set with the refresh token in token.

Raises

  • InvalidRefreshTokenError: The refresh token is invalid or expired
  • FirebaseAPIError: The Firebase API returns another error or communication fails

create_token_manager

def create_token_manager(
    firebase_settings_key: str | None = None,
    *,
    token_store: TokenStore | Token | None = None,
    refresh_buffer_seconds: int = 300,
) -> TokenManager: ...

Build a TokenManager from the FirebaseSettings of the given key. token_store accepts a TokenStore or a Token; when it is omitted, a FileTokenStore is built from token_file_path.

Raises

  • ValueError: No settings exist under the key, or the token store cannot be resolved

TokenManager

class TokenManager:
    def __init__(
        self,
        *,
        api_key: str,
        token_store: TokenStore,
        refresh_buffer_seconds: int = 300,
    ) -> None: ...

    async def get_token(self) -> Token: ...

    async def refresh(self) -> Token: ...

Read the token set from token_store and refresh it when no more than refresh_buffer_seconds remain. The manager caches the token set in memory and uses it while it stays valid. Once it needs a refresh, the manager reads token_store again first, so a value refreshed elsewhere is picked up before a new refresh is requested. Store reads and refreshes are serialized with a lock when multiple coroutines use the manager concurrently.

get_token() and refresh() propagate the exceptions raised by refresh_id_token.

Token

class Token(BaseModel):
    model_config = ConfigDict(frozen=True)

    refresh_token: str
    id_token: str

    @cached_property
    def project_id(self) -> str: ...

    @cached_property
    def uid(self) -> str: ...

    @cached_property
    def expires_at(self) -> datetime: ...

A Firebase Authentication token set. project_id, uid, and expires_at are read from the aud, sub, and exp claims in id_token, so only the two tokens are stored and persisted. The model is frozen, which keeps the cached values consistent with id_token.

Raises

  • ValueError: The claim cannot be read from id_token, or it has an unexpected type

FileTokenStore

class FileTokenStore(TokenStore):
    file_path: str

    def __init__(self, file_path: str) -> None: ...

A TokenStore that keeps the token set in a JSON file. Writes are atomic and locked between processes, and a new file is created with owner-only permissions.

Raises

  • FileNotFoundError: get() is called before the file exists

InMemoryTokenStore

class InMemoryTokenStore(TokenStore):
    def __init__(self, token: Token) -> None: ...

A TokenStore that keeps the token set in the process only.

TokenStore

class TokenStore(Protocol):
    async def get(self) -> Token: ...

    async def set(self, token: Token) -> None: ...

An interface for reading and writing a persistent token set. TokenManager treats it as the authoritative source of the token set.

FirebaseSettings

class FirebaseSettings(BaseSettings):
    api_key: SecretStr
    token_file_path: str | None = None

Firebase Authentication settings that support environment variables with the KIARINA_LIB_FIREBASE_ prefix.

Fields

  • api_key (SecretStr): Firebase Web API key
  • token_file_path (str | None): Path of the file that the token set is stored in

token_manager_registry

token_manager_registry: ObjectRegistry[TokenManager, FirebaseSettings]

A registry of TokenManager instances. Use register(), get(), unregister(), is_registered(), list_names(), and clear().

get(name) returns the registered instance, or builds one from the FirebaseSettings of the same name and keeps it. Names and aliases are those of settings_manager, and get() without a name resolves in the same order: settings_manager.active_key, then the default in the settings, then "default".

resolve() is unusable because it does not read registered instances.

Raises

  • ValueError: No settings exist under the name, or token_file_path is not configured in them

settings_manager

settings_manager: SettingsManager[FirebaseSettings] = SettingsManager(
    FirebaseSettings,
    multi=True,
)

The public instance that manages multiple named FirebaseSettings.

FirebaseAuthError

class FirebaseAuthError(Exception): ...

The base class for Firebase Authentication exceptions raised by this package.

InvalidCustomTokenError

class InvalidCustomTokenError(FirebaseAuthError): ...

Raised when a custom token is invalid.

InvalidRefreshTokenError

class InvalidRefreshTokenError(FirebaseAuthError): ...

Raised when a refresh token is invalid or expired.

FirebaseAPIError

class FirebaseAPIError(FirebaseAuthError):
    status_code: int | None
    error_code: str | None

    def __init__(
        self,
        message: str,
        status_code: int | None = None,
        error_code: str | None = None,
    ) -> None: ...

Represents other Firebase API errors and communication failures. When available, the HTTP status code is stored in status_code and the Firebase error code is stored in error_code.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kiarina_lib_firebase-2.27.0.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kiarina_lib_firebase-2.27.0-py3-none-any.whl (14.3 kB view details)

Uploaded Python 3

File details

Details for the file kiarina_lib_firebase-2.27.0.tar.gz.

File metadata

  • Download URL: kiarina_lib_firebase-2.27.0.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for kiarina_lib_firebase-2.27.0.tar.gz
Algorithm Hash digest
SHA256 8ab40d31556b6f70fa38838c3e81ac19ea33fe85a41a9e43ca9250dba1c5bd53
MD5 3996e754f4e7c9e51831f0bcbb581372
BLAKE2b-256 4ff6324dec77f137f3bbc35e8abd1cdec9f18f1f357d86134909ce530353f0a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for kiarina_lib_firebase-2.27.0.tar.gz:

Publisher: release-pypi.yml on kiarina/kiarina-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kiarina_lib_firebase-2.27.0-py3-none-any.whl.

File metadata

File hashes

Hashes for kiarina_lib_firebase-2.27.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a83ff9f59549370b9e5c99d2e2ce7f66f7053ef02833afbea07908b617eac476
MD5 b48cbcf65966972c8abfce6099696c87
BLAKE2b-256 f8a713236915d86b536533c537281d671739e2885c5763ee0da6b8ecdedb36ab

See more details on using hashes here.

Provenance

The following attestation bundles were made for kiarina_lib_firebase-2.27.0-py3-none-any.whl:

Publisher: release-pypi.yml on kiarina/kiarina-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

2.27.0 This release

2 files

2.26.0

2 files

2.24.0

2 files

2.23.0

2 files

2.3.1

2 files

2.1.0

2 files

2.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page