Session Refresh and Logout
This example shows how to refresh a session and log out 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-session-example
cd ~/rix-auth-session-example
touch session_refresh_logout.cppAdd:
#include <rix.hpp>
int main()
{
rix.debug.print("== rix/auth session refresh and logout ==");
auto auth = rix.auth.memory();
auto registered = auth.register_user({
"grace@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({
"grace@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;
}
const auto session_id = login.value().session.id();
rix.debug.print("created session:", session_id);
rix.debug.print("expires at:", login.value().session.expires_at());
auto refreshed = auth.refresh_session(session_id);
if (refreshed.failed())
{
const auto &error = refreshed.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message());
return 1;
}
rix.debug.print("----------------------------------------");
rix.debug.print("OK:", "session refreshed");
rix.debug.print("new expires at:", refreshed.value().expires_at());
auto logout = auth.logout(session_id);
if (logout.failed())
{
const auto &error = logout.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message());
return 1;
}
rix.debug.print("----------------------------------------");
rix.debug.print("OK:", "logout successful");
auto after_logout = auth.authenticate_session(session_id);
if (after_logout.ok())
{
rix.debug.eprint("ERROR:", "session should not be valid after logout");
return 1;
}
rix.debug.print("session rejected after logout");
return 0;
}Run it:
vix run session_refresh_logout.cppIf Rix is not available yet for single-file usage:
vix install -g rix/rix
vix run session_refresh_logout.cppExpected output shape:
== rix/auth session refresh and logout ==
created session: session_...
expires at: ...
----------------------------------------
OK: session refreshed
new expires at: ...
----------------------------------------
OK: logout successful
session rejected after logoutWhat 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({
"grace@example.com",
"correct-password"});It logs the user in:
auto login = auth.login({
"grace@example.com",
"correct-password"});It stores the session id:
const auto session_id = login.value().session.id();It refreshes the session:
auto refreshed = auth.refresh_session(session_id);It logs out:
auto logout = auth.logout(session_id);Then it checks that the session is rejected after logout:
auto after_logout = auth.authenticate_session(session_id);Create a session
A session is created when login succeeds.
auto login = auth.login({
"grace@example.com",
"correct-password"});The login result contains:
user
session
tokenAccess the session with:
login.value().sessionUse the session id for later session operations:
const auto session_id = login.value().session.id();Refresh a session
Use:
auto refreshed = auth.refresh_session(session_id);If the session is valid, not expired, and not revoked, refresh succeeds.
The refreshed session has an updated expiration timestamp.
rix.debug.print(
"new expires at:",
refreshed.value().expires_at());Check refresh errors
refresh_session returns a result.
Check it before using the refreshed session:
if (refreshed.failed())
{
const auto &error = refreshed.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message());
return 1;
}Then use:
refreshed.value()Logout
Use:
auto logout = auth.logout(session_id);Logout revokes the session.
A revoked session remains stored, but it can no longer be used for authentication.
Check logout errors
logout returns a status.
Use:
logout.ok()
logout.failed()
logout.error()Example:
if (logout.failed())
{
const auto &error = logout.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message());
return 1;
}Authenticate after logout
After logout, this should fail:
auto after_logout = auth.authenticate_session(session_id);Check it:
if (after_logout.ok())
{
rix.debug.eprint("ERROR:", "session should not be valid after logout");
return 1;
}This confirms that logout revoked the session.
Normal session flow
The normal flow is:
register user
login user
get session id
refresh session when needed
logout when done
reject session after logoutIn code:
auto auth = rix.auth.memory();
auto registered = auth.register_user({
"grace@example.com",
"correct-password"});
auto login = auth.login({
"grace@example.com",
"correct-password"});
const auto session_id = login.value().session.id();
auto refreshed = auth.refresh_session(session_id);
auto logout = auth.logout(session_id);In real code, check every result before calling value().
Error handling pattern
Use this pattern for session operations that return a value:
auto result = auth.refresh_session(session_id);
if (result.failed())
{
const auto &error = result.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message());
return 1;
}Use this pattern for operations that only return a status:
auto status = auth.logout(session_id);
if (status.failed())
{
const auto &error = status.error();
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(error),
error.message());
return 1;
}Refresh before logout
This is valid:
auto refreshed = auth.refresh_session(session_id);
if (refreshed.failed())
{
return 1;
}
auto logout = auth.logout(session_id);Refresh keeps the session alive.
Logout revokes it.
After logout, refresh should fail because the session is no longer usable.
Refresh after logout example
#include <rix.hpp>
int main()
{
auto auth = rix.auth.memory();
auto registered = auth.register_user({
"grace@example.com",
"correct-password"});
if (registered.failed())
{
return 1;
}
auto login = auth.login({
"grace@example.com",
"correct-password"});
if (login.failed())
{
return 1;
}
const auto session_id = login.value().session.id();
auto logout = auth.logout(session_id);
if (logout.failed())
{
return 1;
}
auto refreshed = auth.refresh_session(session_id);
if (refreshed.failed())
{
rix.debug.eprint(
"expected auth error:",
rix.auth.error.to_string(refreshed.error()),
refreshed.error().message());
return 0;
}
return 1;
}Run:
vix run session_refresh_logout.cppThe refresh after logout should fail.
Logout all sessions for a user
Use:
auto status = auth.logout_user(user_id);Example:
auto registered = auth.register_user({
"grace@example.com",
"correct-password"});
if (registered.failed())
{
return 1;
}
auto login1 = auth.login({
"grace@example.com",
"correct-password"});
auto login2 = auth.login({
"grace@example.com",
"correct-password"});
if (login1.failed() || login2.failed())
{
return 1;
}
auto status = auth.logout_user(registered.value().id());
if (status.failed())
{
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(status.error()),
status.error().message());
return 1;
}logout_user revokes all sessions belonging to the given user.
Authenticate session directly
Use:
auto session = auth.authenticate_session(session_id);This checks that the session:
exists
is valid
is not expired
is not revokedExample:
if (session.ok())
{
rix.debug.print("session user id:", session.value().user_id());
}Custom session lifetime
You can configure session lifetime with auth config:
auto config = rix.auth.config.development();
config.set_session_ttl_seconds(60 * 60);
auto auth = rix.auth.memory(config);This creates sessions that last one hour.
Use this when testing session expiration behavior or changing application policy.
Token lifetime is separate
Session lifetime and token lifetime are separate settings.
config.set_session_ttl_seconds(60 * 60 * 24 * 7);
config.set_token_ttl_seconds(60 * 15);The session controls server-side authentication.
The token is a short-lived value issued for a user.
Safe output
Session ids are sensitive.
This example prints the session id so the flow is easy to see.
For production logs, avoid printing:
session ids
raw token values
passwords
password hashesUse stable user ids, event ids, or redacted values instead.
Use in a Vix project
Create a project:
vix new rix-auth-session --app
cd rix-auth-sessionAdd 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-session"
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 session_refresh_logout.cppIf needed:
vix install -g rix/rix
vix run session_refresh_logout.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({
"grace@example.com",
"correct-password"});
if (registered.failed())
{
return 1;
}
auto login = auth.login({
"grace@example.com",
"correct-password"});
if (login.failed())
{
return 1;
}
auto logout = auth.logout(login.value().session.id());
return logout.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({
"grace@example.com",
"correct-password"});
if (registered.failed())
{
rix.debug.eprint(
"auth error:",
rix.auth.error.to_string(registered.error()),
registered.error().message());
return 1;
}
rix.debug.print("registered:", registered.value().email());
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 refreshed = auth.refresh_session(session_id);
rix.debug.print(refreshed.value().expires_at());Correct:
auto refreshed = auth.refresh_session(session_id);
if (refreshed.failed())
{
return 1;
}
rix.debug.print(refreshed.value().expires_at());Expecting logout to delete the session
Logout revokes the session.
A revoked session can remain stored, but it is not usable.
This makes logout behavior safer and easier to audit.
Refreshing a revoked session
This should fail:
auth.logout(session_id);
auto refreshed = auth.refresh_session(session_id);A revoked session is not refreshable.
Printing session ids in production
Avoid logging raw session ids.
They are sensitive authentication values.
The example prints them only to make the flow visible.
Expecting memory sessions to persist
Memory sessions disappear when the process exits.
Use database-backed stores for durable auth.
What you should remember
Create memory auth:
auto auth = rix.auth.memory();Login creates a session:
auto login = auth.login({
"grace@example.com",
"correct-password"});Refresh the session:
auto refreshed = auth.refresh_session(
login.value().session.id());Logout revokes the session:
auto logout = auth.logout(
login.value().session.id());After logout, authentication should fail:
auto after_logout = auth.authenticate_session(
login.value().session.id());Check every result before using value().
For project usage:
vix add rix/rix
vix installand keep:
deps = [
"rix/rix",
]Next step
Continue with token issue.
Next: Token issue