## Session Identifiers OAuth uses session identifiers, even if they are given other names. There is no other way to make it work. So not having your own session ID is not going to make any difference. ## Secure Session Identifier on Client's Side You have several ways to save the session ID on the client's computer. There is, however, only one way considered safe: Secure HTTPS Cookies. I want to make it clearer here: * Secure -- this means the browser manages the cookie, JavaScript has no access to it and therefore a 3rd party script cannot read it and send it to their own server (and thus break your top secret secure cookie). * HTTPS¹ -- send cookies only over HTTPS, this way the cookie data travels encrypted; here we have an issue with MitM² if you do a redirection from HTTP to HTTPS because the MitM² can proxy the encryption... so you must force HTTPS from the start * Cookies -- this is a way to have data attached to each transactions between the client and the server; this is the most effective way to handle the situation where you want a user to be logged in _¹ There is now an option to make the browser select HTTPS by setting the [`Strict-Transport-Security` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security); also browsers are now expected to test HTTPS first._ _² **Man in the Middle** (MitM) attack where someone intercepts an HTTP request and prevents you from directly going to the HTTPS site. In this way, they can return all the data unencrypted without you knowing and capture all your data._ ## Generating/Managing Session IDs Strengthening from there: * Random Tokens -- your session ID (a.k.a. "Token") must be as random as possible; the reason why we do not use sessions with incremented identifiers (1, 2, 3...) is because a hacker could very easily know what comes next; very random identifiers are best (i.e. think 16 bytes from `/dev/random`) * Fresh Tokens -- here you have to be careful; when you update a token, all the transactions are affected; more and more browsers send multiple requests in parallel and that means you may get some perfectly valid transactions with the old token when you already _refreshed_ the token within another transaction. This is useful really only if point one is followed (i.e. the tokens are quite random) * Session State -- you should have a session state and possibly other statistics such as a counter (number of times used), when it was created, how long it can be used, etc. when you logout or timeout, the session is not deleted, it is marked as "old" and cannot be reused; leaving this session in your database is important to avoid reusing the same unique identifier for a while (in case the user's ID was compromised) -- **this is something missing in your own list** * Form State -- whenever you create a form (especially for a user to log in), you must include a Form Session ID; if the user replies without that specific ID, the form POST fails * Form Timeout -- if you want to make the Login form even more secure, it should timeout _quickly_ (5 min.); on a timeout, you can at least reset the form (delete the username and password fields), you can also disable the form and tell the user they have to reload it if they want to log in (which is why now a day you can get a popup—it makes sense to hide a popup and when the user clicks Login again, it reloads a new fresh form); the problem here is that your grandma entered her credentials, got a call on the other side of the room, then wandered to do the laundry... the grand child comes in from school hours later and just clicks Login and gains access!) ## OAuth2, JWT, OpenID, etc. These are _all the same thing_. It is a way to create a session identifier but in many cases you let another system take care of the session. It changes nothing on how a session should be managed. However, using such a library may save you time if you do not want to handle all the nitty gritty of a user login feature and it will also make sure that it is properly implemented. ## _«Bank Level Security»_ Most of what you call _«Bank Level Security»_ is different from what you are talking about. Banks (and really any business out there with an Internet presence) want to prevent hackers from accessing their systems. Therefore this doesn't have much to do with people accessing an account on their website. Internet businesses want to have systems in place to prevent _illegal_ access to their systems. For example, if you use PHPMyAdmin (I think newer versions are pretty safe now?), you can protect your computer from intrusion by using a static IP address. If the user trying to access PHPMyAdmin does not have that IP address, they will not even know that the website offers that ability. You can block the IP at your firewall level (drop packets going to port 4443 unless they come from that static IP address) or in your website settings (in Apache it would be a `Require <ip-address>`). In order to make sure that the bank/business server is secure, you use third part penetration systems that run a battery of tests to verify whether your server can be hacked. The PCI-DSS tests, for example, will tell you that you have to hide the Apache2 signature (_security by obfuscation_). It also detects whether your server uses SSL or TLS 1.0, which are now deprecated. It will detect all the ports that you have open and see whether they consider this one or that one insecure. Many services are considered insecure (an old one, called `finger`, is banned in most places since it otherwise can be used to lists your users).