Web Security (OWASP Top 10:2025) Module 8 – A07:2025 Authentication Failures
Sessions: IDs, fixation, timeouts and logout
Issue session IDs that cannot be guessed, replace them at sign-in, end sessions by time and by logout, and check each rule against a weak and a fixed store.
What you will learn
- Choose between server-side sessions and signed cookie sessions by what each can end
- Generate session IDs from a secure random source and replace them at sign-in and at re-authentication
- Implement idle and absolute timeouts, a logout that deletes the record and sign out everywhere
- Handle concurrent sessions, device lists, re-authentication for sensitive changes and a remember-me cookie
- Log a fingerprint of a session ID instead of the ID, and keep IDs out of URLs
Before you start
What you’ll learn · Before you start
What you will learn
- Choose between server-side sessions and signed cookie sessions by what each can end
- Generate session IDs from a secure random source and replace them at sign-in and at re-authentication
- Implement idle and absolute timeouts, a logout that deletes the record and sign out everywhere
- Handle concurrent sessions, device lists, re-authentication for sensitive changes and a remember-me cookie
- Log a fingerprint of a session ID instead of the ID, and keep IDs out of URLs
Before you start
On this page
Asha clicks Log out on a shared computer and walks away. In the first program below, a copy of her session ID, taken from a log line, still opens her account 145 minutes later, because the app cleared her cookie and left its own record of the session alone. The fixed app answers the same request with a 401.
A session is the server’s memory that a run of requests belongs to one signed-in person, and its ID is the key to that memory. The key can be trusted when it is random and long, when sign-in replaces it, when time and logout end it, and when ending it deletes the server’s record. Each rule comes with a check that fails on the weak store and passes on the fixed one.
A session ID is a bearer secret, so the server must be able to end it
After a person signs in, the server stores a record of who they are and gives the browser an ID that names the record. The browser sends the ID with every request, and the server believes whoever sends it. The ID is a bearer secret: A value that works for whoever presents it, with no proof that they are the one it was issued to. A session ID, an API key and an access token are bearer secrets: a copy is as good as the original., as good as the password for as long as the record exists. Step through one session, from the sign-in to a late copy of its ID:
The drawing shows the whole scene; its 8 steps are listed below.
Every step as text
- Sign in. Asha sends her name and password. The app checks them first, and only a success makes a session.
- A record under an ID. The app writes a record to its table, "asha", under an ID of 128 random bits. The ID is a key to the record, and the record is the session.
- The browser keeps the key. The ID travels to the browser in a Set-Cookie header. From now on the browser sends it with every request to the site, so it is a bearer secret that anyone who holds it can use.
- Every request is a lookup. Each request carries the cookie. The app asks the table who the ID belongs to, and the table is the only thing that can answer.
- Logout. Asha clicks Log out. The browser tells the app, and the app has to end the session in the one place where it exists.
- The record is deleted. The app deletes the record from its table. Clearing the cookie in the browser is a courtesy to Asha. The deleted record is what ends the session.
- A copy of the ID arrives. Someone sends a copy of the ID, from a log line or another browser. The app asks the table, and there is no record under that ID.
- The answer. The table has nothing, so the app answers 401. The copy opens nothing, and so would a copy made yesterday. A server that did not delete the record would have answered 200.
The record in the table is the session, and four rules keep the table honest. Each has a part of this lesson to itself:
- The ID cannot be guessed. It holds at least 128 bits from a secure random generator, as ASVS 5.0.0 requirement 7.2.3 asks.
- Sign-in replaces the ID. A new ID at every sign-in means that an ID someone knew before it, a case of session fixation: An attack on a session whose ID someone knew before the person signed in. If the app keeps that ID after the sign-in, whoever knew it holds a signed-in session. MITRE files it as CWE-384., opens nothing.
- Time ends the session. An idle limit and an absolute limit, both checked by the server against its own clock, end the sessions that nobody ended.
- Logout deletes the record. A logout, a disabled account and a sign out everywhere all delete the record, because clearing a cookie ends nothing on the server.
The OWASP Top 10 names three of these failures in its category A07:2025: an ID reused after sign-in, an ID in the URL, and sessions that a logout or a period of inactivity does not end.
Where the record lives is a choice as well: in a table the server keeps, or inside a signed cookie that the server cannot take back. The program gives two small apps the same five requests. Both ask the browser to drop the cookie at logout, and only one deletes its record:
// Two small apps keep sessions in a table. Both clear the cookie at logout; only one deletes its record.
// A request is answered 200 when its session ID is in the table and 401 when it is not. Neither app has a timeout,
// so the minute only labels the step.
function makeApp({ deletesRecordAtLogout }) {
const sessions = new Map(); // session ID -> user
return {
signIn(user, id) {
sessions.set(id, user);
return 200;
},
get(id) {
return sessions.has(id) ? 200 : 401;
},
logout(id) {
// Either way the response says "Set-Cookie: sid=; Max-Age=0", so the person's browser forgets the ID.
if (deletesRecordAtLogout) sessions.delete(id);
return 204;
},
};
}
const weak = makeApp({ deletesRecordAtLogout: false });
const fixed = makeApp({ deletesRecordAtLogout: true });
// A copy of Asha's ID, such as one that a proxy wrote to a log line. In a real app the ID is 128 random bits.
const ID = 'Zk3rV9mQ-demo-id';
const steps = [
[0, 'sign in as asha', (app) => app.signIn('asha', ID)],
[5, 'GET /account with the cookie', (app) => app.get(ID)],
[10, 'Asha clicks Log out', (app) => app.logout(ID)],
[20, 'GET /account with the copied ID', (app) => app.get(ID)],
[155, 'GET /account with the copied ID', (app) => app.get(ID)],
];
console.log('minute request weak app fixed app');
for (const [minute, what, run] of steps) {
console.log(`${String(minute).padStart(6)} ${what.padEnd(32)} ${String(run(weak)).padStart(8)} ${String(run(fixed)).padStart(9)}`);
} Output
minute request weak app fixed app
0 sign in as asha 200 200
5 GET /account with the cookie 200 200
10 Asha clicks Log out 204 204
20 GET /account with the copied ID 200 401
155 GET /account with the copied ID 200 401
Recorded with Node.js 24.21.0 on macOS 26 arm64. To run it yourself: mise exec node@24.21.0 -- node logout_replay.mjs
Runs on this device, in your browser. The first run downloads JavaScript (about 0.6 MB), which is kept for the next runs.
Your run, in this browser
The weak app answered the copy with 200 at minute 20 and again at minute 155, which is 145 minutes after the logout, while the fixed app answered 401 both times. Neither app has a timeout, so the minute only labels the step: the weak app would have answered in the same way a year later.
Checkpoint
Check: A session ID is a bearer secret
Flashcards · 4 cards
Recall it, then check
Say the answer to yourself before you look: recalling it is what makes it stick.
-
Why is a session ID a bearer secret, and which four rules keep it trustworthy?
The server believes whoever sends the ID, so it is as good as the password while the record exists. The ID cannot be guessed (ASVS 5.0.0 7.2.3: 128 bits or more, from a cryptographically secure generator); sign-in replaces it, so a known ID opens nothing (session fixation); time ends the session, with idle and absolute limits checked on the server's clock; and logout deletes the server's record.
-
Why does clearing the cookie at logout not end a session?
It ends nothing on the server. In the lesson a copy of Asha's session ID taken from a log line still opened her account 145 minutes after logout in the weak app, while the fixed app, which deleted its record, answered 401. A logout, a disabled account and a sign out everywhere all delete the record.
-
Which three session failures does A07:2025 name?
An ID reused after sign-in, an ID in the URL, and sessions that a logout or a period of inactivity does not end.
-
Where can the session record live, and why did the logout test separate two apps?
In a table the server keeps, or inside a signed cookie that the server cannot take back. Both apps asked the browser to drop the cookie at logout, and only the one that deleted its record could refuse the copy of the ID.
Guessing an ID is a numbers game, and 128 random bits win it Pro: opens with a Pro, Premium or Ultimate pass
In this part:
- A new ID at every sign-in ends fixation, and only IDs the server issued are accepted
- The server enforces an idle limit and an absolute limit, whatever the cookie says
- Logout, a ban and a password change all delete records
- A signed cookie cannot be taken back, so choose the design by what you must end
- Devices, sensitive changes and remember-me each need a rule of their own
- Keep session IDs out of URLs and logs
- One request, checked in order
- Practise: a session store you can trust
- A session store with limits and a real logout
- Interview questions
- What is session fixation, and how do you prevent it?
- An auditor signs in on a kiosk, clicks Log out, then replays the old session cookie from another machine and is still signed in. What is wrong, how do you fix it, and which test keeps it fixed?
- Your app keeps sessions in signed cookies. Support needs "sign out everywhere" and "ban this user now", and the team will not add a lookup to every request. What can you offer, and what does each option cost?
- A banking-style app and an internal wiki both need sessions. Choose idle and absolute limits, when to ask for a fresh sign-in, and whether to offer remember-me for each, and defend the difference.
- Key takeaways
2 diagrams · 5 runnable examples (JavaScript (checks.mjs), JavaScript (fixed.mjs), JavaScript (weak.mjs), Python) · 1 exercise with sample tests · 3 interview answers · about 52 minutes
Opening this part with your pass…
This part opens with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so this part can’t be opened at the moment. The free part above stands on its own. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
Terms in this lesson
- absolute timeout
- The time from the sign-in after which the server ends a session however active it has been. No request restarts it, so it ends the sessions that are used for ever.
- bearer secret
- A value that works for whoever presents it, with no proof that they are the one it was issued to. A session ID, an API key and an access token are bearer secrets: a copy is as good as the original.
- idle timeout
- The time without a request after which the server ends a session. Each request restarts it, so it ends the sessions that someone left open.
- session epoch
- A number that the server keeps for each user and that a signed cookie carries. When the server raises its number, every cookie that carries an older one is refused.
- session fixation
- An attack on a session whose ID someone knew before the person signed in. If the app keeps that ID after the sign-in, whoever knew it holds a signed-in session. MITRE files it as CWE-384.
References
- Session Management Cheat Sheet (OWASP Foundation)
- ASVS 5.0.0, V7 Session Management (7.1.1 to 7.5.3) (OWASP Foundation)
- ASVS 5.0.0, V14 Data Protection (14.2.1, 14.3.1, 14.3.2) (OWASP Foundation)
- ASVS 5.0.0, V16 Security Logging and Error Handling (16.2.5) (OWASP Foundation)
- NIST SP 800-63B-4, section 5: Session Management, and the timeouts of sections 2.1.3, 2.2.3 and 2.3.3 (NIST)
- A07:2025 Authentication Failures (OWASP Foundation)
- Clear-Site-Data header (MDN Web Docs (Mozilla))
- Cookies: HTTP State Management Mechanism (draft-ietf-httpbis-rfc6265bis-22) (IETF HTTP Working Group)
- Sessions (Flask quickstart) (Pallets)
Related tools
Report a problem with this lesson
Kept only in this browser. Your Learn progress