Auth
rix/auth provides authentication helpers for Vix.cpp applications.
It gives applications a simple public API for:
- user registration
- login
- password hashing
- server-side sessions
- session refresh
- logout
- logout all sessions for a user
- short-lived tokens
- memory-backed stores
- database-backed stores
- explicit error handling
The recommended public API is through the Rix facade:
#include <rix.hpp>Then use:
rix.authBasic example
#include <rix.hpp>
int main()
{
auto auth = rix.auth.memory();
auto registered = auth.register_user({"ada@example.com", "correct-password"});
if (registered.failed())
{
const auto &error = registered.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message()
);
return 1;
}
auto login = auth.login({"ada@example.com", "correct-password"});
if (login.failed())
{
const auto &error = login.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message()
);
return 1;
}
auto session = auth.authenticate_session(login.value().session.id());
if (session.failed())
{
return 1;
}
rix.debug.print("authenticated:", session.value().user_id());
return 0;
}Install
For the facade API, install:
vix add rix/rix
vix installIf the project uses vix.app, declare the dependency in deps:
deps = [
"rix/rix",
]deps is for Vix Registry packages.
Do not put Rix packages in packages.
Auth-only dependency
If a project or library only needs Auth, it can depend on the independent package:
vix add rix/auth
vix installThen declare:
deps = [
"rix/auth",
]However, the documentation examples use the unified facade:
#include <rix.hpp>and:
rix.authSo when following these docs, prefer:
deps = [
"rix/rix",
]Single-file usage
For a quick test, create one file:
mkdir -p ~/rix-auth-example
cd ~/rix-auth-example
touch auth.cppAdd:
#include <rix.hpp>
int main()
{
auto auth = rix.auth.memory();
auto registered = auth.register_user({"ada@example.com","correct-password"});
return registered.failed() ? 1 : 0;
}Run:
vix run auth.cppIf Rix is not available yet for single-file usage, install the facade globally:
vix install -g rix/rixThen run again:
vix run auth.cppMemory auth
The easiest way to start is:
auto auth = rix.auth.memory();Memory auth creates an authentication service backed by in-memory user and session stores.
Use it for:
- examples
- tests
- local experiments
- small temporary tools
Memory auth does not persist data.
When the process stops, users and sessions are lost.
Database auth
For real applications, use database-backed auth:
auto auth = rix.auth.database(db);With production configuration:
auto config = rix.auth.config.production();
auto auth = rix.auth.database(db, config);Database auth stores users and sessions through Vix database storage.
Use it when authentication data must survive process restarts.
Main operations
Register a user
auto registered = auth.register_user({"ada@example.com","correct-password"});A successful registration returns a User.
registered.value().id()
registered.value().email()
registered.value().email_verified()
registered.value().active()Login
auto login = auth.login({"ada@example.com","correct-password"});A successful login returns:
login.value().user
login.value().session
login.value().tokenThe user contains the authenticated identity.
The session represents server-side login state.
The token is a short-lived value attached to the user.
Authenticate a session
auto session = auth.authenticate_session(session_id);A session is usable when it is:
valid
not revoked
not expiredRefresh a session
auto refreshed = auth.refresh_session(session_id);Refreshing updates the session expiration and last-seen time.
Logout
auto status = auth.logout(session_id);Logout revokes the session.
A revoked session remains stored but can no longer be used.
Logout all sessions for a user
auto status = auth.logout_user(user_id);Use this when a user changes password, signs out from all devices, or an account must be immediately disconnected.
Issue a token
auto token = auth.issue_token(user_id);A token contains:
token.value().value()
token.value().user_id()
token.value().issuer()
token.value().issued_at()
token.value().expires_at()The token value is sensitive.
Do not log raw token values in production.
Password hashing
rix/auth exposes password helpers through:
rix.auth.passwordHash a password:
auto hashed = rix.auth.password.hash("correct-password");Verify a password:
bool valid = rix.auth.password.verify("correct-password",hashed.value());Check a wrong password:
bool invalid = rix.auth.password.verify("wrong-password",hashed.value());Check whether a password is accepted by the policy:
bool accepted = rix.auth.password.accepts("correct-password");Password hashing returns explicit results.
Always check the result before using the hash value.
Configuration
Auth configuration is available through:
rix.auth.configDevelopment configuration:
auto config = rix.auth.config.development();Production configuration:
auto config = rix.auth.config.production();Example:
auto config = rix.auth.config.production();
config.set_min_password_length(12);
config.set_issuer("my-app");
auto auth = rix.auth.memory(config);Configuration controls:
- minimum password length
- maximum password length
- session lifetime
- token lifetime
- password hash iterations
- password salt size
- password hash size
- token issuer
- email verification requirement
- session rotation
- inactive user rejection
Explicit errors
Rix Auth does not use exceptions for normal authentication failures.
It uses explicit result and status objects.
Operations that return data use result objects:
auto result = auth.login({"ada@example.com","correct-password"});
if (result.failed())
{
const auto &error = result.error();
}Operations that only return success or failure use status objects:
auto status = auth.logout(session_id);
if (status.failed())
{
const auto &error = status.error();
}Convert an error to a stable string:
rix.auth.error.to_string(error)Read the human-readable message:
error.message()Common error codes
Auth errors use stable error codes.
Common codes include:
InvalidInput
InvalidEmail
InvalidPassword
UserNotFound
UserAlreadyExists
InvalidCredentials
EmailVerificationRequired
UserDisabled
InvalidSession
SessionExpired
SessionRevoked
InvalidToken
TokenExpired
TokenRevoked
StoreError
CryptoError
ValidationError
ConfigurationError
UnknownUse the code for programmatic decisions.
Use the message for diagnostics and developer feedback.
Stores
Auth storage is abstracted behind stores.
User storage:
UserStore
MemoryUserStore
DbUserStoreSession storage:
SessionStore
MemorySessionStore
DbSessionStoreThe facade gives helpers:
auto users = rix.auth.stores.memory_users();
auto sessions = rix.auth.stores.memory_sessions();Database stores:
auto users = rix.auth.stores.database_users(db);
auto sessions = rix.auth.stores.database_sessions(db);For most applications, use:
auto auth = rix.auth.memory();or:
auto auth = rix.auth.database(db);Managed auth
ManagedAuth owns its stores and exposes the Auth API safely.
The easiest managed APIs are:
auto auth = rix.auth.memory();and:
auto auth = rix.auth.database(db);For custom owned stores:
auto users = rix.auth.stores.memory_users();
auto sessions = rix.auth.stores.memory_sessions();
auto managed = rix.auth.managed(
std::move(users),
std::move(sessions)
);
if (managed.failed())
{
return 1;
}
auto auth = managed.move_value();Use managed when you want to create stores yourself but still let the returned auth service own them.
Caller-owned auth
Advanced code can create an auth service with caller-owned stores:
auto users = rix.auth.stores.memory_users();
auto sessions = rix.auth.stores.memory_sessions();
auto auth = rix.auth.create(*users, *sessions);In this case, the caller owns the stores.
The stores must stay alive for as long as auth is used.
For normal application code, prefer rix.auth.memory() or rix.auth.database(db).
Security notes
Do not log sensitive values in production.
Avoid logging:
plain-text passwords
password hashes
session ids
raw token valuesUse memory auth only for development, examples, tests, and temporary tools.
Use database auth for real applications.
Use production configuration for real deployments:
auto config = rix.auth.config.production();What you should remember
Use Auth through the facade:
#include <rix.hpp>auto auth = rix.auth.memory();Register users:
auth.register_user(...)Login users:
auth.login(...)Authenticate sessions:
auth.authenticate_session(...)Hash passwords:
rix.auth.password.hash(...)Always check results before using .value().
Use memory auth for examples and tests.
Use database auth for durable applications.
Next step
Create your first Auth example.
Next: Auth Quick Start