How Credential Session Support Handles Token Refresh in OpenHuman
The session support module retrieves the current access token from the session profile but delegates the actual OAuth refresh to AuthService, which exchanges the refresh token and updates the stored credentials.
The tinyhumansai/openhuman repository manages authentication through credential profiles, using a dedicated session profile—identified by the constant APP_SESSION_PROVIDER—to supply bearer tokens for RPC and UI layers. When tokens expire, the system employs a strict separation of concerns: lightweight read operations reside in session_support.rs while the complex token renewal logic lives in AuthService.
Understanding the Session Architecture
The Session Profile and TokenSet
Authentication data in OpenHuman is organized into credential profiles defined in src/openhuman/credentials/profiles.rs. The session profile stores an AuthProfile containing a TokenSet struct that holds the access token, refresh token, and associated metadata. This profile serves as the single source of truth for active authentication state, consumed by both the core RPC layer and the user interface.
Separation of Concerns: Reader vs. Refresher
The session_support module at src/openhuman/credentials/session_support.rs operates strictly as a read-only view. According to the OpenHuman source code, the get_session_token function queries the session profile but never modifies it. This design keeps session handling lightweight and stateless, delegating all mutable OAuth operations—including token refresh—to AuthService in src/openhuman/credentials/auth_service.rs.
The Token Refresh Cycle
Step 1: Retrieving the Stored Access Token
The session support helper extracts the current token through the get_session_token function (lines 118–124 in src/openhuman/credentials/session_support.rs):
// Returns Ok(Some(token)) or Ok(None) if profile missing
Ok(profile.and_then(|entry| entry.token))
This simply returns whatever access token is currently stored in the profile, or None if the session profile does not exist.
Step 2: Detecting Expiration via 401 Responses
The session support module does not validate expiration timestamps or automatically trigger refreshes. Instead, callers such as RPC handlers detect expired tokens when they receive 401 Unauthorized responses from upstream services. The detection happens outside session_support, keeping the module focused solely on credential retrieval.
Step 3: Performing the OAuth Refresh
When expiration is detected, AuthService executes the refresh flow. The service reads the stored refresh_token from the profile's TokenSet, calls the OAuth provider's token endpoint, and receives a new access_token. This logic is implemented in methods like refresh_oauth_token, which handles network communication, response parsing, and error recovery independently of the session support code.
Step 4: Persisting and Subsequent Reads
After obtaining fresh credentials, AuthService::store_provider_token updates the session profile with the new access token and optional new refresh token. Because get_session_token performs a simple read of profile.token, subsequent calls automatically return the refreshed credentials without requiring changes to the caller's logic.
Code Implementation in OpenHuman
The following pattern demonstrates how RPC handlers coordinate with these components:
use openhuman_core::openhuman::credentials::session_support::get_session_token;
// Initial token retrieval
let token = match get_session_token(&config)? {
Some(t) => t,
None => return Err("session JWT required".into()),
};
// If the downstream call returns 401, trigger refresh
auth_service.refresh_oauth_token(&config)?; // Exchanges refresh_token
// After successful refresh, retrieve updated token
let new_token = get_session_token(&config)?
.ok_or("token unavailable after refresh")?;
Higher-level operations in src/openhuman/credentials/ops.rs such as auth_get_session_token_json ultimately wrap get_session_token, providing JSON interfaces for the UI and RPC layers while maintaining the same underlying refresh semantics.
Key Files and Responsibilities
src/openhuman/credentials/session_support.rs: Implementsget_session_tokenfor read-only access to the session profile.src/openhuman/credentials/profiles.rs: DefinesAuthProfile,AuthProfileKind, andTokenSetstructures.src/openhuman/credentials/auth_service.rs: Implementsrefresh_oauth_tokenandstore_provider_tokenfor OAuth flows and credential persistence.src/openhuman/credentials/ops.rs: Exposes high-level operations likeauth_get_session_token_jsonthat callers use to retrieve session tokens.
Summary
- The session support module functions as a read-only accessor, returning the current token from the session profile without performing validation or refresh.
- Token refresh is handled exclusively by AuthService, which exchanges the
refresh_tokenfrom theTokenSetwith the OAuth provider. - After refresh,
AuthServicepersists the new access token to the session profile, ensuring subsequentget_session_tokencalls return fresh credentials. - This architecture keeps credential retrieval lightweight while centralizing complex OAuth mutation logic in a dedicated service.
Frequently Asked Questions
Does session_support.rs automatically refresh expired tokens?
No. The module only reads the stored access token from the session profile. It does not check expiration timestamps or initiate OAuth flows. Token refresh must be explicitly triggered by callers (such as RPC handlers) through AuthService.
What triggers the token refresh process in OpenHuman?
When an RPC handler or UI component receives a 401 Unauthorized response indicating an expired access token, it invokes AuthService::refresh_oauth_token. This method performs the actual OAuth refresh using the stored refresh_token from the credential profile.
Where is the refresh token stored in the credential system?
The refresh token is stored within the TokenSet struct inside the session AuthProfile, defined in src/openhuman/credentials/profiles.rs. The TokenSet contains both the access token and refresh token, along with metadata required for the OAuth flow.
How does the RPC layer obtain tokens after a refresh?
The RPC layer calls get_session_token from session_support.rs (or the higher-level auth_get_session_token_json from ops.rs) whenever it needs a bearer token. Because AuthService updates the underlying session profile during refresh, these read operations automatically return the new access token without requiring the RPC layer to track refresh state.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →