Token Issue
This example shows how to issue a token for a registered user with rix/auth.
The example uses the public Rix facade:
#include <rix.hpp>and accesses auth through:
rix.authIt uses an in-memory auth service, so it is useful for examples, tests, and local development.
Create the file
mkdir -p ~/rix-auth-token-example
cd ~/rix-auth-token-example
touch token_issue.cppAdd:
#include <rix.hpp>
int main()
{
rix.debug.print("== rix/auth token issue ==");
auto auth = rix.auth.memory();
auto registered = auth.register_user({
"linus@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 token = auth.issue_token(
registered.value().id());
if (token.failed())
{
const auto &error = token.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message());
return 1;
}
rix.debug.print("OK:", "token issued");
rix.debug.print("user id:", token.value().user_id());
rix.debug.print("issuer:", token.value().issuer());
rix.debug.print("issued at:", token.value().issued_at());
rix.debug.print("expires at:", token.value().expires_at());
return 0;
}Run it:
vix run token_issue.cppIf Rix is not available yet for single-file usage:
vix install -g rix/rix
vix run token_issue.cppExpected output shape:
== rix/auth token issue ==
OK: token issued
user id: user_...
issuer: rix/auth
issued at: ...
expires at: ...What this example does
The example creates an in-memory auth service:
auto auth = rix.auth.memory();It registers a user:
auto registered = auth.register_user({
"linus@example.com",
"correct-password"});It issues a token for the registered user:
auto token = auth.issue_token(
registered.value().id());Then it prints token metadata:
rix.debug.print("user id:", token.value().user_id());
rix.debug.print("issuer:", token.value().issuer());
rix.debug.print("issued at:", token.value().issued_at());
rix.debug.print("expires at:", token.value().expires_at());Issue a token
Use:
auto token = auth.issue_token(user_id);The user_id must identify a valid user.
A token result contains a token value on success.
Check the result before using it:
if (token.failed())
{
const auto &error = token.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message());
return 1;
}Then access:
token.value()Token fields
A token contains:
value
user id
issuer
issued timestamp
expiration timestamp
revocation stateIn examples, it is safe to print metadata such as issuer and timestamps.
Avoid printing the raw token value in production logs.
Token value is sensitive
The raw token value is sensitive.
Avoid logging:
token.value().value()In production, do not print raw token values, passwords, password hashes, or session ids.
This example prints only:
user id
issuer
issued at
expires atToken issuer
The issuer identifies the auth system that created the token.
By default:
rix/authRead it with:
token.value().issuer()You can configure the issuer through auth config:
auto config = rix.auth.config.development();
config.set_issuer("my-app");
auto auth = rix.auth.memory(config);Token expiration
Tokens are short-lived.
Read the expiration timestamp with:
token.value().expires_at()Read the issue timestamp with:
token.value().issued_at()The timestamps are Unix timestamps in seconds.
Token lifetime
Token lifetime is controlled by auth configuration:
auto config = rix.auth.config.development();
config.set_token_ttl_seconds(60 * 15);
auto auth = rix.auth.memory(config);This creates tokens that last 15 minutes.
Session lifetime is separate:
config.set_session_ttl_seconds(60 * 60 * 24 * 7);The token can be short-lived while the server-side session lasts longer.
Complete custom token lifetime example
#include <rix.hpp>
int main()
{
auto config = rix.auth.config.development();
config.set_token_ttl_seconds(60 * 5);
config.set_issuer("rix/auth/example");
auto auth = rix.auth.memory(config);
auto registered = auth.register_user({
"linus@example.com",
"correct-password"});
if (registered.failed())
{
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(registered.error()),
registered.error().message());
return 1;
}
auto token = auth.issue_token(
registered.value().id());
if (token.failed())
{
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(token.error()),
token.error().message());
return 1;
}
rix.debug.print("issuer:", token.value().issuer());
rix.debug.print("expires at:", token.value().expires_at());
return 0;
}Run:
vix run token_issue.cppIssue a token after login
A successful login already returns a token:
auto login = auth.login({
"linus@example.com",
"correct-password"});Access it with:
login.value().tokenExample:
auto login = auth.login({
"linus@example.com",
"correct-password"});
if (login.failed())
{
return 1;
}
rix.debug.print(
"login token issuer:",
login.value().token.issuer());Use issue_token when you need to issue a new token for an already known user id.
Issue token for missing user
Issuing a token for a missing user should fail:
#include <rix.hpp>
int main()
{
auto auth = rix.auth.memory();
auto token = auth.issue_token("missing-user");
if (token.failed())
{
rix.debug.eprint(
"expected auth error:",
rix.auth.error.to_string(token.error()),
token.error().message());
return 0;
}
return 1;
}Run:
vix run token_issue.cppThe failure is expected because the user does not exist.
Check token usability
A token object can be checked at a given time:
const auto now = token.value().issued_at();
if (token.value().usable(now))
{
rix.debug.print("token is usable");
}A usable token must be:
valid
not revoked
not expiredCheck token ownership
Use:
token.value().belongs_to(user_id)Example:
if (token.value().belongs_to(registered.value().id()))
{
rix.debug.print("token belongs to user");
}Check token issuer
Use:
token.value().issued_by("rix/auth")Example:
if (token.value().issued_by("rix/auth"))
{
rix.debug.print("token issuer accepted");
}Revoke a token object
A token object can be revoked in memory:
auto value = token.value();
value.revoke();
if (!value.usable(value.issued_at()))
{
rix.debug.print("token revoked");
}This changes the token object.
It does not revoke every copy of that token in an external token store.
For durable token revocation in a real application, use an application-level store or token tracking strategy.
Error handling pattern
Use this pattern for token operations:
auto result = auth.issue_token(user_id);
if (result.failed())
{
const auto &error = result.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message());
return 1;
}Then use:
result.value()Only after checking success.
Use in a Vix project
Create a project:
vix new rix-auth-token --app
cd rix-auth-tokenAdd Rix:
vix add rix/rix
vix installMake sure vix.app contains:
deps = [
"rix/rix",
]A minimal vix.app can look like this:
name = "rix-auth-token"
type = "executable"
standard = "c++20"
output_dir = "bin"
sources = [
"src/main.cpp",
]
include_dirs = [
"include",
"src",
]
deps = [
"rix/rix",
]
packages = [
"vix",
]
links = [
"vix::vix",
]Put the example code in:
src/main.cppBuild and run:
vix build
vix runSingle-file usage
For examples, tests, and quick experiments:
vix run token_issue.cppIf needed:
vix install -g rix/rix
vix run token_issue.cppFor project usage, prefer:
vix add rix/rix
vix installand keep the dependency in vix.app:
deps = [
"rix/rix",
]Use only auth with the facade
If you want the rix.* facade style but only want auth mounted, define the feature macro before including rix.hpp:
#define RIX_ENABLE_AUTH
#include <rix.hpp>
int main()
{
auto auth = rix.auth.memory();
auto registered = auth.register_user({
"linus@example.com",
"correct-password"});
if (registered.failed())
{
return 1;
}
auto token = auth.issue_token(
registered.value().id());
return token.ok() ? 0 : 1;
}When at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.
If you also want debug output:
#define RIX_ENABLE_AUTH
#define RIX_ENABLE_DEBUG
#include <rix.hpp>
int main()
{
auto auth = rix.auth.memory();
auto registered = auth.register_user({
"linus@example.com",
"correct-password"});
if (registered.failed())
{
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(registered.error()),
registered.error().message());
return 1;
}
auto token = auth.issue_token(
registered.value().id());
if (token.failed())
{
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(token.error()),
token.error().message());
return 1;
}
rix.debug.print("token issued");
return 0;
}Use the independent package
For independent usage, install:
vix add rix/auth
vix installIn vix.app:
deps = [
"rix/auth",
]Then include auth package headers directly.
The examples in this documentation prefer the public facade:
#include <rix.hpp>and:
rix.authCommon mistakes
Forgetting to install Rix
If rix.hpp is not found, install Rix first.
For a project:
vix add rix/rix
vix installFor single-file usage:
vix install -g rix/rixPutting Rix in packages
Wrong:
packages = [
"rix/rix",
]Correct:
deps = [
"rix/rix",
]deps is for Vix Registry packages.
packages is for CMake package discovery.
Calling value() before checking success
Wrong:
auto token = auth.issue_token(user_id);
rix.debug.print(token.value().issuer());Correct:
auto token = auth.issue_token(user_id);
if (token.failed())
{
return 1;
}
rix.debug.print(token.value().issuer());Printing raw token values
Avoid printing:
token.value().value()The raw token value is sensitive.
Use metadata such as issuer and expiration in examples.
Expecting tokens and sessions to be the same thing
A session is server-side authentication state.
A token is a short-lived value issued for a user.
They have separate lifetimes:
config.set_session_ttl_seconds(...);
config.set_token_ttl_seconds(...);Issuing a token for a missing user
This should fail:
auto token = auth.issue_token("missing-user");Use a real user id from registration or login.
Expecting memory auth to persist data
Memory auth does not persist users or sessions after the process exits.
Use database-backed stores for real applications.
What you should remember
Create memory auth:
auto auth = rix.auth.memory();Register a user:
auto registered = auth.register_user({
"linus@example.com",
"correct-password"});Issue a token:
auto token = auth.issue_token(
registered.value().id());Check errors before using values:
if (token.failed())
{
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(token.error()),
token.error().message());
return 1;
}Avoid logging raw token values.
For project usage:
vix add rix/rix
vix installand keep:
deps = [
"rix/rix",
]Next step
Continue with PDF examples.
Next: Basic PDF