Secure By Design: Secure Session Management for Web and Mobile Apps

Learn how to manage sessions securely across web and mobile apps. Discover best practices, real-world breach examples, and secure code in ASP.NET Core.

🔐 Why Session Management Matters

Session management is a cornerstone of secure web and mobile applications. Sessions keep users authenticated after login, often using cookies or tokens. Poor session handling can allow attackers to impersonate users, hijack sessions, or bypass authentication entirely.

So, session is how a system “remembers” a user after they authenticate.Think of it like this: You log into a site → the server creates a session → it stores this session ID (often in a cookie or header token) → every time you interact again, your browser or app includes that session info so the server knows it’s you.

Session Management Overview

🚨 Why Is It Critical to Protect?

A compromised session = user impersonation. That’s game over. Attackers don’t need to crack passwords—they just hijack valid sessions.

Here’s why it’s dangerous:

  • Session Hijacking: Attackers steal a valid session ID via XSS, insecure Wi-Fi, or sniffing traffic. Now they’re logged in as the user without credentials.
  • Session Fixation: The attacker sets a known session ID before a user logs in. If the app doesn’t regenerate it post-login, the attacker can use the same ID afterward.
  • Cross-Site Request Forgery (CSRF): If session cookies aren’t scoped tightly (e.g., with SameSite flags), a malicious site can forge authenticated requests on a user’s behalf.
  • Session Replay Attacks: Without proper expiration or anomaly detection, stolen tokens can be reused long after they’re compromised.

⚠️ Real-World Breaches

🔓 Uber 2022: Social Engineering + Token Abuse

Attackers tricked an employee into revealing credentials or clicking a malicious link, gaining access to a valid session token. Since Uber's internal systems accepted that token without verifying via multi-factor authentication (MFA), the attacker bypassed other safeguards. Read more.

  • The danger of treating session tokens as permanent keys
  • Why session tokens should expire or be invalidated quickly after high-risk activity

Impact: Uber had to shut down several internal tools, investigate lateral movement across services, and respond to global scrutiny over its security maturity and internal access controls.

💡 Lesson: Always validate session tokens on sensitive actions and combine them with behavioral analytics or step-up MFA to detect unusual activity.

🕵️ Facebook 2018: Access Token Exploitation

The attackers abused a bug in the “View As” feature to harvest access tokens tied to user sessions—about 50 million of them. These tokens functioned like active session IDs and granted full access without needing passwords. Read more.

  • Why sessions must be tightly scoped and revocable
  • The risk of not monitoring session token creation and reuse at scale

Impact: Facebook forced logout for 90M accounts, faced regulatory investigations, and had its handling of access token security questioned globally, especially under GDPR scrutiny.

💡 Lesson: Design session systems with limited lifespan and revocation capability. Monitor token activity patterns and scope tokens based on usage.

📱 Reddit 2018: 2FA Isn’t Enough Without Cookie Protection

Even with SMS-based two-factor authentication (2FA), attackers stole session cookies, likely via phishing or device compromise. Once they had the cookies, they could impersonate employees.Read more.

  • Secure cookies (with HttpOnly, Secure, and SameSite) are essential
  • Session protection must complement, not replace, strong authentication

Impact: Reddit confirmed the breach included email digests with user content and username linkage. It impacted user trust and reinforced the need to move away from SMS-based 2FA.

💡 Lesson: Harden session cookies with proper flags and ensure authentication is layered, including phishing-resistant MFA and session anomaly detection.

✅ Core Best Practices (With Examples)

1. Use Strong, Unpredictable Session IDs

Session IDs should be randomly generated and long enough to resist brute-force attacks. Avoid sequential or predictable formats.

// ASP.NET Core does this by default when using cookie authentication
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie();

2. Rotate Session ID After Login or Privilege Change

This prevents session fixation, where an attacker sets a known session ID before login and hijacks it after authentication.

// Force regeneration of session ID
await HttpContext.SignOutAsync();
await HttpContext.SignInAsync(userPrincipal);

3. Set Inactivity and Absolute Timeouts

Limit how long a session stays valid to reduce risk if the session is stolen.

services.ConfigureApplicationCookie(options => {
    options.ExpireTimeSpan = TimeSpan.FromMinutes(15);
    options.SlidingExpiration = true;
});

4. Secure Cookies with Flags

Ensure session cookies cannot be accessed via JavaScript or sent over unencrypted channels.

options.Cookie.HttpOnly = true;   // Prevent access via JS
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // HTTPS only
options.Cookie.SameSite = SameSiteMode.Strict; // Block CSRF

5. Avoid Storing Sensitive Data in Sessions

Only store essential session data like user ID or role. Never store passwords or full profile details.

HttpContext.Session.SetString("UserId", user.Id);
// Don't do: HttpContext.Session.SetString("Password", user.Password);

📱 Mobile Considerations

  • Use access + refresh tokens: Avoid long-lived sessions; rotate tokens securely.
  • Store tokens securely: Use Keychain (iOS) or Keystore (Android).
  • Wipe sessions on logout: Clear secure storage and revoke tokens server-side.

📌 Example: Using Access + Refresh Tokens

// Pseudocode for secure token handling
const loginResponse = await api.login(username, password);
secureStorage.set('access_token', loginResponse.accessToken);
secureStorage.set('refresh_token', loginResponse.refreshToken);

📌 Example: Secure Token Storage (Android - Keystore)

val sharedPreferences = EncryptedSharedPreferences.create(
  "auth_prefs",
  MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
  context,
  EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
  EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
sharedPreferences.edit().putString("access_token", token).apply()

📌 Example: Wipe Tokens on Logout

// Clear tokens from secure storage
secureStorage.remove('access_token');
secureStorage.remove('refresh_token');

// Optionally revoke on server
await api.revokeToken(refreshToken);

🔍 Web vs Mobile Session Handling

Feature Web Apps (Cookies) Mobile Apps (Tokens)
Storage Browser cookies Secure local storage (Keychain/Keystore)
Transport Sent automatically Sent manually via headers (e.g., Authorization)
Rotation method Server-controlled (cookie regen) Client fetches new access + refresh tokens

🛠 Tools and Implementation Options

  • Distributed session stores: Redis, SQL Server, or cloud-managed caches for scaling.
  • Session audits: Track active sessions, IP, device, and expiration metadata.
  • Use secure headers: Add Set-Cookie with proper attributes in all responses.
  • Token introspection endpoints: Useful for validating tokens in mobile apps.

🧠 Final Tips

  • Always destroy session data on logout using HttpContext.SignOutAsync().
  • Notify users of new logins from unrecognized devices (e.g., via email).
  • Combine secure session handling with proper authentication and authorization controls.
  • Monitor for anomalies (e.g., concurrent sessions from different countries).

Series: Secure by Design → Next: Secure Config Management