Skip to content

PlaceBrain/auth

Repository files navigation

auth

gRPC authentication service for PlaceBrain — JWT issuance, OTP email verification, user management.

License: Apache 2.0 Python 3.14 gRPC

This service owns the auth_db schema and is the single source of truth for user identity in the PlaceBrain platform. It signs access and refresh tokens that every other service trusts.

Role in PlaceBrain

PlaceBrain is an open-source IoT platform for smart buildings. See the organization profile for the full architecture.

  • auth is called over gRPC by the gateway for every sign-in, token refresh, profile read, and email-based member lookup.
  • It does not depend on other PlaceBrain services and does not publish Kafka events.
  • The JWT secret it uses to sign access tokens is shared with the gateway, which validates every incoming request against it.

Tech stack

  • Python 3.14, uv for dependency management
  • gRPC (grpcio)
  • Dishka for DI (APP scope for singletons, REQUEST scope for per-request UoW)
  • SQLAlchemy 2.0 async + asyncpg, Alembic migrations
  • Pydantic Settings with __-nested environment keys
  • aiosmtplib for outbound OTP email (fire-and-forget via asyncio.create_task)
  • Async bcrypt via loop.run_in_executor() — hashing never blocks the event loop

gRPC methods (port 50051)

Method Access Purpose
Register public Create a user, send first OTP
SendOtp / VerifyOtp public Email verification flow
Login public Password login → (access_token, refresh_token)
RefreshTokens public Rotate refresh token
Logout authenticated Revoke refresh token
GetMe authenticated Current user profile
ValidateToken internal Verify a token signature, return claims
GetUserByEmail internal Member lookup for the places service

Proto definitions live in placebrain-contracts (auth.proto).

Local development

Full stack (recommended): clone infra and run make dev — auth, its Postgres database, the gateway, and the rest of the platform come up together.

Service-only mode:

uv sync
cp .env.example .env          # set JWT__SECRET, DATABASE__URL, SMTP__*
uv run alembic upgrade head
uv run python -m src

You will need a reachable PostgreSQL instance with a pre-created auth_db database and an SMTP relay for OTP delivery.

Environment variables

All keys use __ as the nested delimiter (e.g. DATABASE__URLsettings.database.url). See .env.example for the complete list — the highlights:

Variable Purpose
DATABASE__URL postgresql+asyncpg://... DSN for auth_db
JWT__SECRET HS256 signing key — must match gateway's JWT_SECRET
JWT__ACCESS_TOKEN_EXPIRE_MINUTES default 15
JWT__REFRESH_TOKEN_EXPIRE_DAYS default 30
SMTP__* outbound SMTP used for OTP email
OTP__EXPIRE_MINUTES / OTP__MAX_ATTEMPTS / OTP__RESEND_COOLDOWN_SECONDS OTP policy

Project layout

src/
├── main.py                  gRPC server + DI container wiring
├── core/                    Settings, DTOs, typed exceptions, JWT & password helpers
├── dependencies/            Dishka providers (config, db/uow, auth, otp)
├── handlers/auth.py         gRPC AuthHandler — maps typed exceptions to StatusCode
├── services/{auth,otp}.py   Business logic
└── infra/
    ├── db/                  SQLAlchemy helper, UoW, models (User, RefreshToken, OtpRequest), repositories
    └── email/sender.py      SMTP client, fire-and-forget dispatch

Error model

Services raise typed exceptions from core/exceptions.py; the handler maps them deterministically:

Exception gRPC StatusCode
NotFoundError NOT_FOUND
AlreadyExistsError ALREADY_EXISTS
InvalidCredentialsError UNAUTHENTICATED
EmailNotVerifiedError FAILED_PRECONDITION
CooldownError / MaxAttemptsExceededError RESOURCE_EXHAUSTED
InvalidCodeError / ValueError INVALID_ARGUMENT

License

Apache License 2.0 — see LICENSE.

About

gRPC authentication service for PlaceBrain - JWT, OTP email verification, user management

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors