# Nova Auth
Authentication library for the [Nova](https://github.com/novaframework/nova) ecosystem.
Provides a unified actor session, claims mapping, authorization policies, and optional password-based authentication. Works standalone or as the foundation for [nova_auth_oidc](https://github.com/Taure/nova_auth_oidc).
## Features
- **Unified actor session** -- Strategy-agnostic session storage. Password auth, OIDC, JWT -- all produce the same actor map in the session.
- **Claims mapping** -- Transform provider-specific claims to actor maps with static maps or callback functions.
- **Security callbacks** -- Drop-in Nova security function for protecting route groups.
- **Policy helpers** -- Composable authorization policies (role-based, claim-based, ownership, authenticated).
- **Rate limiting** -- Nova plugin with configurable sliding-window rate limiting via Seki.
- **Password auth** (optional, requires [Kura](https://github.com/Taure/kura)) -- PBKDF2-SHA256 hashing, session tokens, email confirmation, password reset.
- **Timing-safe** -- Dummy verification on failed lookups to prevent user enumeration.
## Quick Start
Add `nova_auth` to your deps:
```erlang
{deps, [
{nova_auth, {git, "https://github.com/Taure/nova_auth.git", {branch, "main"}}}
]}.
```
### OIDC-only (no database)
If you only need actor sessions and policies (e.g., with [nova_auth_oidc](https://github.com/Taure/nova_auth_oidc)):
```erlang
%% Protect routes -- works with any auth strategy that stores an actor
#{prefix => ~"/dashboard",
security => nova_auth_security:require_authenticated(),
routes => [
{~"/profile", fun my_controller:profile/1, #{methods => [get]}}
]}
%% Access actor in controller
profile(#{auth_data := Actor} = _Req) ->
Email = maps:get(email, Actor, ~"unknown"),
{json, #{email => Email}}.
```
### Password auth (requires Kura)
Create a config module implementing the `nova_auth` behaviour:
```erlang
-module(my_auth).
-behaviour(nova_auth).
-export([config/0]).
config() ->
#{
repo => my_repo,
user_schema => my_user,
token_schema => my_user_token
}.
```
Register and authenticate:
```erlang
%% Register
{ok, User} = nova_auth_accounts:register(
my_auth, fun my_user:registration_changeset/2, Params
).
%% Authenticate and store actor in session
{ok, User} = nova_auth_accounts:authenticate(my_auth, ~"user@example.com", ~"password123456").
ok = nova_auth_actor:store(Req, #{id => maps:get(id, User), provider => password, email => maps:get(email, User)}).
%% Session token (database-backed)
{ok, Token} = nova_auth_session:generate_session_token(my_auth, User).
```
## Modules
### Core (no dependencies beyond Nova)
| Module | Description |
|--------|-------------|
| `nova_auth_actor` | Store/fetch actor maps from Nova session |
| `nova_auth_claims` | Transform provider claims to actor maps |
| `nova_auth_security` | Route-level security callbacks |
| `nova_auth_policy` | Authorization policies for nova_resource |
| `nova_auth_rate_limit` | Rate limiting Nova plugin |
### Password auth (requires Kura)
| Module | Description |
|--------|-------------|
| `nova_auth_accounts` | Registration, authentication, password/identity changes |
| `nova_auth_session` | Database-backed session token management |
| `nova_auth_password` | PBKDF2-SHA256 password hashing |
| `nova_auth_token` | Token generation and validation |
| `nova_auth_confirm` | Email confirmation flow |
| `nova_auth_reset` | Password reset flow |
## Configuration
Password auth options (all optional with defaults):
| Option | Default | Description |
|--------|---------|-------------|
| `repo` | -- | Kura repo module (required for password auth) |
| `user_schema` | -- | Kura user schema module |
| `token_schema` | -- | Kura token schema module |
| `user_identity_field` | `email` | Field used for login lookup |
| `user_password_field` | `hashed_password` | Field storing the password hash |
| `session_validity_days` | `14` | Days before session tokens expire |
| `confirm_validity_days` | `3` | Days before confirmation tokens expire |
| `reset_validity_hours` | `1` | Hours before reset tokens expire |
| `hash_algorithm` | `pbkdf2_sha256` | Password hashing algorithm |
| `token_bytes` | `32` | Random bytes for token generation |
## Guides
- [Getting Started](guides/getting-started.md) -- Installation and first setup
- [Configuration](guides/configuration.md) -- Full configuration reference
- [Actor Session](guides/actor-session.md) -- How the unified actor session works
- [Claims Mapping](guides/claims-mapping.md) -- Transforming provider claims
- [Policies](guides/policies.md) -- Authorization with nova_resource
- [Rate Limiting](guides/rate-limiting.md) -- Protecting routes from abuse
## Related Libraries
- [nova_auth_oidc](https://github.com/Taure/nova_auth_oidc) -- OIDC login, JWT bearer validation, token introspection, client credentials
- [Nova](https://github.com/novaframework/nova) -- Web framework
- [Kura](https://github.com/Taure/kura) -- Database layer (optional)
- [Seki](https://github.com/Taure/seki) -- Rate limiting
## Requirements
- Erlang/OTP 28+
- PostgreSQL via Kura + pgo (only for password auth)
## License
MIT