music-assistant-server

Branch:dev-lidarr-plugin

Commit Details

Add JWT-based authentication with backward compatibility (#2891)

* Add JWT-based authentication with backward compatibility

Migrates from hash-based tokens to JWT (JSON Web Tokens) while maintaining
full backward compatibility with existing tokens. This enables stateless
authentication with embedded user claims for better integration with
external systems and OAuth2/OIDC compliance.

JWT Claims Structure:
- Standard claims: sub (user_id), jti (token_id), iat, exp
- Custom claims: username, role, player_filter, provider_filter,
  token_name, is_long_lived

Token Types:
- Short-lived (30 days, auto-renewing on use, sliding window)
- Long-lived (10 years, no auto-renewal for API integrations)

Implementation:
- JWTHelper class for encoding/decoding with HS256 algorithm
- JWT secret key generated and stored in auth.db settings table
- Token verification tries JWT first, falls back to legacy hash lookup
- Database still stores tokens for revocation checking

Benefits:
- Stateless authentication (user info embedded in token)
- Permission scopes available without database lookup
- OAuth2/OIDC compatibility for external integrations
- Standard JWT format for third-party verification

Migration Strategy:
- Automatic: Old tokens work until expiration
- New logins get JWT tokens automatically
- No breaking changes for existing clients

* Fix JWT token expiration check to honor database expiration

Database expiration is the source of truth for token validity, not just
the JWT expiration claim. This ensures manual token expiration (via
database update) works correctly even when JWT exp is still valid.

* Add documentation for future OIDC support

Notes on consuming external OIDC vs acting as OIDC provider, and
refresh token requirements for the latter.

* Clean up JWT implementation: remove dead code and verbose comments

- Remove unused methods: refresh_short_lived_token(), get_user_from_token()
- Remove unused imports: timedelta, UserRole
- Move User import to TYPE_CHECKING block
- Remove TODO comment about refresh tokens (not implementing)
- Simplify inline comments and reduce verbosity
- All tests still passing (36/36)

* Remove player_filter and provider_filter from JWT claims

These values can be dynamically updated, so storing them in the token
would result in stale data. The current values are available from the
database lookup during token validation.

---------

Co-authored-by: Ztripez von Matérn <[email protected]>
Forgejo

Author

January 28, 2026 at 07:58 AM UTC

Committer

January 28, 2026 at 07:58 AM UTC
91additions
12deletions
4files changed

Parent commits

Changes

4 files
+91-12

Changed Files (4)

music_assistant/controllers/webserver/
music_assistant/helpers/
music_assistant/controllers/webserver/auth.py
+90-12
music_assistant/helpers/jwt_auth.py
pyproject.toml
requirements_all.txt
+1