9

I've been reading up on this for months and it seems like the whole thing could converge on what I'm summarizing below. I'm trying to arrive at the most ideal:

  • OAuth2
  • OpenID Connect
  • SPA / Mobile Client
  • JWT

Solution that has banking level security quality as the above component are concerned. So this is what seems to make sense.

  • Use the Authorization Code Grant without using server side sessions and cookies since this OAuth flow is more secure than the implicit flow.
  • Do not create server side sessions or cookies (Besides perhaps remember me cookies to identify whether the client has been authenticated before). This is better for scaling and overall simplicity.
  • Return a JWT / OpenID connect token to the client so that the client can use it to make API requests and for making authorization decisions within the client. (I think this is what the OAuth2 hybrid Authorization Code Grant / Implicit flow is?). Store the JWT / OpenID connect token in the clients session storage.
  • Have short lived JWT tokens and also offer up refresh token until the user logs out. The client would automatically receive refresh tokens unless it times out / the client side session expires or the user logs out.
  • On logout (Or timeout), remove the token from browser session storage.

Is any of this crazy / does it sound reasonable? It skips over invalidating tokens, but it seems ok to do this if the tokens have very short life times and the client can get refresh tokens. I'd like to implement this using Spring-Boot / Spring Security and Angular 4/5 and I'm wondering if I missed anything obvious or perhaps there is an even simpler approach that does not sacrifice/lower security?

Also do you think this would pass "Banking" level security standards check?

Ole
  • 529
  • 5
  • 10
  • 1
    Can you explain what you think "Banking level security standards check" means. Are you referring to PCI-DSS, other standards such as ISF' SoGP or NIST's relevant sections, or something else? – Rory Alsop Oct 08 '17 at 08:32
  • I'm not really referring to any specific standard ... more of a general feeling type of response - if you were a security developer for a bank would you recommend this as a reasonably safe approach, or would it need to be tighter because ... – Ole Oct 09 '17 at 00:23
  • This question is related to a question I asked: https://security.stackexchange.com/questions/204858/does-an-authorization-code-grant-rely-on-sessions (50 point bounty!) – Andy N Apr 25 '19 at 15:35

1 Answers1

0

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 MTM¹ if you do a redirection from HTTP to HTTPS because the MTM¹ 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

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).

Alexis Wilke
  • 862
  • 5
  • 19