Session Token is a unique identifier that the server creates after successful user authentication and uses to identify subsequent requests. Unlike self-contained tokens (JWT), a session token is a random string that does not contain data by itself: all session information is stored on the server in RAM or a database. According to OAuth.com, 2025, the session token remains the most common authentication mechanism in server-side web applications and hybrid mobile architectures.
Key Takeaways
Session Token (session identifier) is a unique string that the server generates and associates with session data after user authentication. The token does not contain any user information — it is simply a key to the data stored on the server. This approach is called stateful authentication: the server stores the state of each active session and verifies it on every request.
Session data includes: user ID, login time, IP address, user-agent, permission list, last activity time. When the client sends a request with a session token, the server finds the corresponding record in the session store, checks its validity, and retrieves the data to process the request. If the session record is missing or has expired, the server returns an authentication error and requires re-login.
According to OWASP, 2025, the session token remains the standard for applications requiring immediate access revocation — for example, in banking systems and corporate portals where an administrator must be able to terminate a user session instantly. In such systems, the session token provides full control over access that is unattainable for stateless tokens without additional blocking mechanisms.
The process begins when the client sends credentials to the authentication server. The server verifies the login and password, creates a session record in the store (usually Redis or a database), and returns a unique session token to the client. The client saves the token and sends it with every subsequent request, and the server checks the session existence and validity each time.
Redis is the most popular session store thanks to in-memory storage and TTL (time-to-live) support. Each session is stored as a key-value pair, where the key is the session token and the value is a JSON object with session data. TTL automatically removes expired sessions. Alternatives: Memcached (memory only, no disk persistence), PostgreSQL/MySQL (persistent but slower), and DynamoDB (for AWS infrastructure).
Example of a session structure in Redis: session:{token} → {“userId”: 42, “role”: “admin”, “createdAt”: 1812345678, “lastAccess”: 1812345678}. The server updates lastAccess on each request, which allows implementing an inactivity timeout — automatic session termination after a period of inactivity.
Session Token can be transmitted in two ways: via HTTP cookie or via the Authorization HTTP header. Cookies are the traditional method for web applications: the server sets a cookie with HttpOnly (inaccessible to JavaScript), Secure (HTTPS only), and SameSite (CSRF protection) flags. For mobile applications, the Authorization: Bearer <session_token> header is more commonly used, since the cookie mechanism is not always convenient in native clients.
The lifecycle of a session token includes three stages: creation, maintaining an active session, and termination. Each stage requires proper security configuration to prevent token leakage or interception.
Creation — the server generates a cryptographically strong random string of 128–256 bits (for example, via SecureRandom in Java or os.urandom in Python). The token must be unpredictable — using UUID or timestamp without entropy is unacceptable. Storage on the client: on iOS — Keychain, on Android — EncryptedSharedPreferences, on the web — HttpOnly cookie. Deletion occurs on logout: the client removes the token from storage, the server deletes the session record from Redis. After logout, the session token becomes useless — the server will not find a corresponding record.
According to SANS Institute, 2025, proper implementation of session termination (logout with server-side cleanup) prevents up to 70% of attacks using stolen tokens. It is critical not just to delete the token on the client side, but also to invalidate the session on the server.
Session Token and JWT represent two different approaches to authentication. Session Token is stateful (the server stores the state), JWT is stateless (data inside the token). The choice between them depends on the application architecture and security requirements.
| Criterion | Session Token | JWT |
|---|---|---|
| Model | Stateful (data on server) | Stateless (data in token) |
| Revocation | Instant — delete session from Redis | Requires blacklist or short TTL |
| Size | 16–64 bytes | 500–2000 bytes |
| Data Storage | Server only (secure) | Inside token (base64, not encrypted) |
| Scaling | Requires shared storage (Redis) | Not required — token validated locally |
| CSRF Protection | Requires SameSite cookie + CSRF token | Not required (token in header) |
Session Token is preferable when: instant session revocation is required (banking, admin panels), the application runs on one or several servers with a shared Redis, session data is large and does not fit in JWT, or the team wants to minimize the risk of data leakage through token decoding. In such scenarios, the session token provides immediate access blocking upon suspicious activity — just delete one record from Redis, and all user sessions become invalid.
According to Redis, 2025, using TTL at the session key level (EXPIRE command) automatically clears expired sessions without overhead on background tasks. For sessions with a TTL of 1 hour and a load of 10,000 concurrent users, Redis consumes about 1 GB of RAM with a session size of 1 KB, making it cost-effective for most applications.
Security of session tokens is based on two principles: the token must be unpredictable and protected during transmission and storage. The main threats are token interception (man-in-the-middle, XSS), token prediction (weak generation), and session fixation.
Protection includes: using HTTPS for all requests with a token, setting a short session TTL (15–60 minutes of inactivity), binding the session to IP and user-agent (additional verification on each request), using Secure and HttpOnly flags for cookies, and regular rotation of the session token after sensitive operations (password change, privilege escalation). OWASP also recommends implementing Session Management with invalidation of the old session when creating a new one after login — this prevents session fixation.
According to OWASP ASVS, 2025, a session must be bound to at least two factors: the token itself (what the client has) and IP/user-agent (what the server knows). If these factors do not match, the server should terminate the session and require re-authentication.
Below is an example of a server-side session token implementation in Kotlin using Spring Boot and Redis. The server generates a cryptographically strong token via SecureRandom, saves the session in Redis with TTL, and verifies it on each request. The code demonstrates three main operations: session creation, validation, and invalidation.
data class Session(
val userId: Long,
val role: String,
val createdAt: Long,
val lastAccess: Long
)
object SessionManager {
private val redis = JedisPool("localhost", 6379)
fun createSession(userId: Long, role: String): String {
val token = generateSecureToken()
val session = Session(userId, role, now(), now())
redis.resource.use { conn ->
conn.setex("session:$token", 3600, toJson(session))
}
return token
}
fun validateSession(token: String): Session? {
redis.resource.use { conn ->
val json = conn.get("session:$token") ?: return null
return fromJson(json)
}
}
fun invalidateSession(token: String) {
redis.resource.use { it.del("session:$token") }
}
private fun generateSecureToken(): String {
val bytes = ByteArray(32)
SecureRandom().nextBytes(bytes)
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes)
}
}
This implementation uses JedisPool for thread-safe connection to Redis. The createSession method sets a TTL of 1 hour (3600 seconds) — after this period Redis will automatically delete the record. The validateSession method returns null for non-existent or expired sessions, allowing the server to correctly handle a request with an invalid token and return HTTP 401.
Frequently Asked Questions
Session token is a server-side session identifier (stateful). An access token is credentials for API access (can be JWT or opaque). Session tokens are typically used for web sessions, while access tokens are used for API requests in mobile and SPA applications. They can coexist: session token for the web, access token for the API.
The main protection is setting the HttpOnly flag on the cookie containing the session token. This flag prevents JavaScript from accessing the cookie, making XSS attacks useless for stealing the token. Additionally, the SameSite=Strict flag prevents the cookie from being sent with cross-site requests, protecting against CSRF.
Two timeouts are recommended: an absolute timeout (8–24 hours — maximum session lifetime) and a relative timeout (15–30 minutes of inactivity — after which the session ends). For banking applications, the absolute timeout is reduced to 1–2 hours; for email clients, it can reach 7 days.
Session fixation is an attack where an attacker forces a user to use a known session identifier. Protection: after successful authentication, the server must create a new session token rather than continue using the one passed by the client. The old token must be invalidated regardless of its origin.
Yes, a session token is suitable for REST API if the client sends it in the Authorization header (not a cookie). For mobile applications, this is a common practice. The downside: when scaling to multiple servers, a shared session store (Redis) is required, which adds a single point of failure to the architecture.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also