Ask HN: What do you use for authentication and authorization?
I am currently starting work on a new app/website. Currently planning to have 1 BE API set to start, probably graphql (which will be user data/information and need to check with the auth server about being protected). I will also have many client apps (web, mobile, potential partners) that will need to make queries to that BE. Do you usually roll your own authentication or use something like auth0/fusionauth/gluu/etc? This product is going to need to be secure as it will be in the healthcare space (so think oidc).
246 comments
[ 3.5 ms ] story [ 254 ms ] thread- For web, user/pass login exchanged for plain session cookies. Should be marked httpOnly/Secure, and bonus points for SameSite and __Host prefix [1]
- For web, deploy a preloaded Strict-Transport-Security header [2]
- For api clients, use a bearer token. Enforce TLS (either don't listen on port 80, or if someone makes a request over port 80 revoke that token).
- If you go with OpenID/Oauth for client sign-ins then require https callbacks and provide scoped permissions.
- Don't use JWT [3]. Don't use CORS [4].
Again these are broad strokes - if you gave more information you'd get a better response.
[1]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Se...
[2]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/St...
[3]: https://en.wikipedia.org/wiki/JSON_Web_Token
[4]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
It is also correct that JWT 1) supports far more cryptography than is necessary; and 2) supports weak cryptography. You can do better than JWT for session management security and performance merely by generating pseudorandom tokens, associating them to sessions and performing lookups.
More generally speaking: signed, stateless tokens are attractive for a variety of technical reasons. They have legitimate uses. But it's typically a poor security decision to choose them in lieu of revocation, for reasons which are mostly uncontroversial among those who work in security.
That's technically false. JWT features multiple systems of revocation, including the use of nonces. Token revocation also features prominently in JWT's basic workflow.
The key aspect is that there is no turnkey implementation, and thus projects need to roll their own implementation, which is frowned upon some developers.
JWT is stateless. Revocation is stateful. This is a fundamental tension in both cryptography and access control. Yes, you can retrofit your stateless authentication system with a stateful revocation system. But at that point you're back to square one and the architect working on this should consider why they're undoing the legitimate benefits JWT provides.
Nonce based revocation is an active process. Timestamp expiry is not actually revocation, it's expiry. If your token is compromised prior to expiry, you're out of luck.
That's patently false.
JWT's basic workflow features token refreshes, issue and expiration timestamps, and even nonces, and the backend workflow also supports arbitrary token rejections to trigger token refreshes.
The only aspect of JWT's workflow that is left as an implementation detail is tracking revoked tokens.
> JWT is stateless. Revocation is stateful. This is a fundamental tension in both cryptography and access control.
This sort of argument is ivory tower nitpicking stated disingenuously. JWT include issue and revocation timestamps, which already renders the workflow stateless. The only stateful aspect, which is silly nitpicking and technically irrelevant, is keeping track of nonces and arbitrarily revoked tokens, which require keeping a database to track revocations.
The actual issue here is that a lookup needs to be performed at all. For every request, you need to pay the latency of one DB round-trip as well as maintaining code that does this lookup. And if you're going to do that anyway, why bother with this complexity of "stateless" tokens?
If the token blacklist is budgeted and never allowed to grow to a size of more than say 10-200, then it can probably be safely maintained over the lifetime of the project in a way that doesn't require a round-trip, in the source code for the service or otherwise gated behind a release barrier.
I don't know if I agree with that (I've never implemented JWT) but at least I think I've heard of the idea that's how the architecture is supposed to be planned for JWTs.
In this case, the list of revoked tokens will take little space, and update very rarely!
If you're authenticating users logging into your website and you decide user logouts should be implemented by token revocation, you're going to have a great many revoked tokens - perhaps within an order of magnitude of the number of active users you have.
I suspect a lot of the disagreement here is between people who are thinking of different situations.
For that reason I don’t know that it’s fair to say the disagreement throughout this thread is due to people talking about different things. Microservice authentication notwithstanding, session management is not optimally handled by JWT.
No. Tracking revoked tokens is only necessary if for some reason a server wants to reject a valid token, and that's only required until the token expires.
The use of nonces to avoid replay attacks is also a widely established practice, thus we're not talking about extra infrastructure.
Tracking revoked tokens also doesn't take up any resources as tokens are designed to be short-lived.
I’ll recuse myself from further “nitpicking” I suppose, because this isn’t going anywhere. If you’re interested in actually following why your suggestions are a poor fit for session authentication, I’ll direct you to this flowchart: http://cryto.net/%7Ejoepie91/blog/2016/06/19/stop-using-jwt-....
1. The specification has points of ambiguity that have led to a number of flawed implementations. 2. JWT is saddled with unnecessary complexity which also contributes to recurring implementation flaws. 3. JWT increases the complexity of session revocation in contrast to a simple, stateless session ID.
The arguments and counter-arguments are a bit more involved, but be aware that by the time you account for the downsides, you may have negated the value you hoped to gain from stateless web tokens.
If you can use a simple session id, use it. If you need JWT to support external authentication providers, use a short expiration and swap the (fully verified) token for a session id.
Anyway HTTP2 would hopefully address that (through header compression), and things like zero-RTT TLS and keep-alive further minimize the overhead of an additional request.
Plus doesn't CORS only make preflight requests periodically, not for every request?
Among many things you get from http/2, it cannot eliminate round trip time. Sure, you can keep a connection alive but that's possible with http 1.1 too.
Header compression is HPACK. If the header changes even the slightest bit, it's not cached. Dynamic URLs and headers can easily bust HPACK compression.
As a concrete example: people occasionally misuse the Origin header, thinking that they can use it as a form of client authentication. The idea is that any client request from a non-whitelisted origin will fail. But any user can spoof their own Origin header, and the Origin header is primarily intended to protect users from making CORS requests they didn’t intend (because in most cases an attacker cannot coerce a browser to forge a header).
In 2018 it is fully possible to use authentication libraries which natively support granular control for things like revocation using strong, turnkey cryptography. I would argue most people who think they should be using stateless and signed sessions for e.g. performance are heavily discounting the revocation liability and neglecting to optimize their lookups sufficiently (such as by caching).
That statement is false.
JWT were specifically designed to store a payload JSON object which among the many standardized fields include the token's expiry time, and JWT were specifically designed with a workflow which includes not only client-side token refreshing but also server-side token rejection that triggers client-side token refreshes.
In fact, JWT token refreshes and token rejections feature in any basic intro tutorial to JWT, including the design principle that tokens should be discarded and refreshed by the client as soon as possible and also the use of nonces.
The exp payload field is even specified in JWT's RFC along with the token rejection workflow.
https://tools.ietf.org/html/rfc7519
The same document also specifies the jti field which is the JWT's nonce.
And the jti field is not intended for what you think it is. Anti-replay is not at all the same as revocation. Those are different things entirely.
I certainly believe (and have seen) the jti field used in the manner you describe. But no, that workflow is not intended for revocation. Which makes sense given the design intentions of JWT, because anti-replay can be accomplished as a stateless process, while revocation cannot.
Issue and expiration timestamps are used along with nonces to enforce single use tokens. Once a token is used then the client is expected to discard and refresh the token.
Implementations are also free to keep track of issued tokens and that does not pose any problem in the real world.
> And the jti field is not intended for what you think it is. Anti-replay is not at all the same as revocation.
Why are you expecting to revoke a token in a scenario where the token is supposed to be used once?
Either the token is deemed valid and accepted or it's invalidated and rejected, which triggers clients to refresh the token and retry the request.
An attacker was able to somehow issue a bunch of tokens for himself. Now you want to invalidate them even though they're not used yet.
> Either the token is deemed valid and accepted or it's invalidated and rejected, which triggers clients to refresh the token and retry the request.
The other point here is that you are probably (not always, not in every possible case, but in most common cases) better off using just a bearer token (refresh it on every use if need be). There's no performance benefit in using stateless tokens when they can be used only once, and handling bearer tokens is much easier from a gun-to-shoot-your-feet-with perspective.
I'm not expert in JWT and just jumping in here, but wouldn't that imply total compromise of the PKI if this ever happens?
I'm saying, if this scenario comes to pass, with basically any old authentication system, isn't it now time to roll the master keys and invalidate _every previously issued_ token/session the old-fashioned way, by disavowing the prior signing key, and then bouncing every user/ requiring to re-auth freshly and establish brand new sessions within the totally new PKI?
I assume this is always still possible even with JWT from what I've read so far, but I'm happy to be educated if either of you don't mind sharing.
Not necessarily. Let's say I steal your password and use it against the auth endpoint to get 10 one-time tokens for your account. Re-rolling the master key is a solution, but a very radical one if I can just invalidate all your tokens don't you think? ;)
The tokens are valid, thus there is no objective reason to reject them other than there was an unrelated security failure elsewhere in the system.
Additionally, tokens are generated per request and are short-lived, with an expiration timestamp that is just enough to send a request to the server.
When the token is passed to the server, the nonce is added to the server's scratchpad memory to revoke the token and thus avoid replay attacks. If anyone for some reason wants to revoke a token, they only need to add the token's nonce to the revoked list. If the nonce is present in the list then the server rejects the token and triggers a token refresh.
"It's a common practice to add expiry timestamp for such tokens so each token will expire after certain interval."
With this:
"That's dandy, but it's a solution which is neither standardized nor native to JWT."
People are providing evidence that token expiration is native to JWT to refute that statement, while you are arguing in parallel that "expiry is not revocation" which is related but separate.
If not a service to validate tokens against a blacklist is again trivial and will scale to all but the top 0.1% of organizations. And it only needs to be in the blacklist long enough for the period until the token expires.
Yes, jwt is not ideal. But this talk that you should never ever use them and your service will be immediately hacked etc is silly internet bandwagoning.
For a huge percentage of services jwts are just fine. Anyone reading this, please do not over think this advice and just ship with jwts if that is what you have.
I never said you should never ever use JWT or that your service will be hacked if you do so. In fact, if you kindly reread what I wrote you'll see that I explicitly mentioned there are legitimate use cases for JWT. I am specifically refuting the use of JWT as an authenticated session management system.
> Anyone reading this, please do not over think this advice and just ship with jwts if that is what you have.
This is poor advice.
1) Authentication is sufficiently solved for most workflows and applications that you can use turnkey solutions for more secure and more performant authentication than JWT.
2) What exactly is the scenario you envision in which JWT is all someone has? Do you mean they're forced to use stateless session management, or that JWT is literally all they can do for authentication because nothing else is available?
Good luck using session cookies with Cordova on iOS, for example [1]. In cases like these JWT is perhaps your only option.
[1] https://issues.apache.org/jira/browse/CB-12074
So — getting back to the OP — which libraries?
But either way, if you really can't afford a database or cache layer lookup to see if a token is still valid, then you accept that by using a bearer token, that is only validated by signature alone, that it is possible a user will have their session hijacked without possibility of revokation.
The usual way this is mitigated is by use of a small expiry time (I've commonly seen <=5 min) and a revokable refresh token. This still gives a hijacker a possible 5 minutes (assuming 5 minute expiry) if a user revoked the refresh token, but it does mitigate the damage while still reducing DB lookups since you only do a lookup in token refresh. Hope that clears things up. Again your application needs should drive these decisions.
You don't need the ID. You can simply store the token's signature. In fact, some implementations store the whole JWT to avoid roundtrips to the auth service, and revoking the token is just a matter of flipping an attribute in the database.
The token expiry determines the baseline accuracy of banning across all services.
JWT and sessionIds are totally different beasts. JWT are used per request, are designed to expire and be refreshed, are specific to each individual endpoint and store authorization info in a specialized third party service.
In such a system, a user would be logged out after one minute of closing the connection... Probably good enough for online banking. In a way, this is safer than standard sessionId-based auth because once you've issued the token, you don't need to worry about scenarios where the user has gone offline suddenly.
There are very few systems that need banning with down-to-the-millisecond accuracy.
With JWT, you only need to do a single database lookup when the user logs in with their password at the beginning... You don't need to do any other lookup afterwards to reissue the token; just having the old (still valid but soon-to-expire) JWT in memory is enough of a basis to issue a fresh token with an updated expiry.
It scales better because if you have multiple servers, they don't need to share a database/datastore to manage sessionIds.
Also, this is a security consideration because a malicious user could intentionally send fake sessionIds to make us DoS our database. With JWT, verification of the signature only uses CPU on the workers which are easier to scale.
You can steal a JWT token the same way you can steal a session token.
If you can live with quickly expiring, quickly reissued crypto tokens like JWT, it's a boon.
But JWT definitely don't work for web auth. They can be used as CSRF tokens, though.
How will you deal with the usability problem introduced by expiring all sessions for users who are offline (closed tab, spotty internet connection, etc) for at least 50 seconds? It actually seems like you really should be wondering how to interpret users being offline temporarily.
You could just accept this as working as intended, but you don’t need to accept it if you just use normal session IDs. Is your application really so latency sensitive that it can’t tolerate a DB lookup? What is an example workflow in which users on a web or mobile application cannot be tolerably authenticated with standard DB lookups?
You can also use a refresh token, but this brings you back to the revocation problem, but with longer term tokens. Likewise, there is a material difference between millisecond revocation and sub-minute revocation. There are good reasons to care about sub-minute revocation.
JWTs as bearer tokens aren't bad in their own right, but if you aren't careful you can screw yourself and therefore many security experts avoid them for use in securing systems. Plus a lot of people mistake it for an encrypted token which it isn't. You can imagine how bad that can get.
Tbh I'm with the parent commenter. I avoid them, but if you avoid common pitfalls they should work for your system no problem.
I'm on mobile and can't be arsed to gather sources, but you can search the claims I made and you'll see several articles about these problems. There's even a defcon talk about a new proposed standard (called Paseto I think) that starts by highlighting the major issues with JOSE and JWT specifically.
Like JWT?
I feel like that argument goes around in circles.
I feel that the problem is that some users are talking about stuff they know nothing about, but still feel compelled to be very vocal and opinionated.
https://news.ycombinator.com/item?id=13866983
https://news.ycombinator.com/item?id=14292223
If you get somebody's JWT, you can get everything stored in the token as well.
If you want it to be encrypted, you have to encrypt the token (presumably following JWE).
You simply get a bearer token (non JWT) onto the client and use that from local storage instead of a cookie.
Your JavaScript code then makes api calls using the same bearer pathway as other api clients.
The token can still expire, be revoked, etc. it just prevents you having to handle cookie auth on your api.
The parent comment saying “that sounds like JWT” is implying it’s just as bad or has the same shortfalls as using JWT.
HttpOnly is a joke, and people should stop claiming it helps with XSS. It does not help. It's security benefit is at most neutral. In fact, people often seem to think that it prevents XSS, and get lulled into a false sense of security. For that reason, HttpOnly seems to be worse than neutral.
That statement is not true. JWT do support revocation. In short, servers are free to reject any token, which triggers a token refresh on the client-side. Token revocation is even an intrinsic aspect of JWT as they suport issue and expiry timestamps, along with a nonce to avoid replay attacks.
It seems some users have an axe to grind regarding the idea of having to keep track of some tokens that were poorly designed (i.e., absurdly long expiry dates without a nonce) but the solution quite obviously is to not misuse the technology. In the very least, if a developer feels compelled to use a broken bearer token scheme that does not expire tokens based on issue date then quite obviously he needs to keep a scratchpad database of blacklisted tokens to compensate for that design mistake.
Servers can of course implement whatever custom behaviour they desire, but the protocol itself (and common implementing libraries) does not have any direct support for revocation.
Furthermore, any revocation implementation will inherently have to compromise the statelessness that is JWT's most prominent selling point.
> Token revocation is even an intrinsic aspect of JWT as they suport issue and expiry timestamps, along with a nonce to avoid replay attacks.
JWT does indeed support expiry and nonces. But these are not the same thing as revocation.
> It seems some users have an axe to grind regarding the idea of having to keep track of some tokens that were poorly designed (i.e., absurdly long expiry dates without a nonce) but the solution quite obviously is to not misuse the technology. In the very least, if a developer feels compelled to use a broken bearer token scheme that does not expire tokens based on issue date then quite obviously he needs to keep a scratchpad database of blacklisted tokens to compensate for that design mistake.
Insults and "obviously"s are not a good way to convince people of your point of view.
That's patently false. The protocol does support revocation. In fact, its basic usage specifically states that servers are free to force the client to refresh its tokens by simply rejecting it. If a JWT is expected to be ephemeral and servers are free to trigger token reissues, what lead you to believe that JWT didn't supported one of its basic use cases?
> Furthermore, any revocation implementation will inherently have to compromise the statelessness that is JWT's most prominent selling point.
That's false as well for a number of reasons, including the fact that JWT use nonces to avoid replay attacks. And additionally JWT's main selling point is that's a bearer token that's actually standardised, extendable, provided as a third party service, and is usable by both web and mobile apps.
> JWT does indeed support expiry and nonces. But these are not the same thing as revocation.
Expiration timestamps and nonces automatically invalidate tokens, which are supposed to be ephemeral, and nonces are a specific strategy to revoke single-use tokens. As it's easy to understand a bearer token implementation that supports revoking single-use tokens is also an implementation that supports revoking tokens, don't you agree?
> Insults and "obviously"s are not a good way to convince people of your point of view.
Perhaps educating yourself on the issues you're discussing is a more fruitful approach, particularly if you don't feel confortable with some basic aspects of the technology and some obvious properties.
I remember building a service when I was experimenting with web development that used randomly generated tokens in a custom HTTP header, and that is closer to Bearer Token (the standard) than Bearer Token is to JWT.
If you believe JWT is "precisely" the same as mere presentation of a token, then you're woefully ignorant of JWT.
> ... it makes no sense to present that workflow as an alternative to the JWT workflow ...
But that's not what happened, is it? In fact, it's the opposite. As I read it, [1] suggests a bearer token workflow, to which [2] replies that the suggestion is "an awful lot like JWT", whereupon [3] clarifies that the original suggestion is just a normal bearer token scheme, which, I claim, shares nothing with "JWT" except the "T".
> ... JWT, which is a bearer token scheme ...
The "T" in "JWT" is the least interesting bit of JWT, and merely a necessity.
> It's irrelevant if the workflow is specific to JWT or is shared by other bearer token schemes
When not talking about any specific bearer token scheme, it is absolutely relevant. Only the generic point was under discussion, until JWT was introduced. JWT is not just another bearer token scheme. It comes with its own additional obligations, restrictions, and extra steps, not to mention the purpose-defeating pitfalls.
----
[1]: https://news.ycombinator.com/item?id=18768173
[2]: https://news.ycombinator.com/item?id=18768212
[3]: https://news.ycombinator.com/item?id=18768242
Care to provide an example?
The security impact of automatic client-side expiry is tiny, since token expiration must be done server-side anyway.
The HttpOnly flag as an XSS mitigation is almost useless; competent attackers will simply run their code from the victim's browser and session. To protect against XSS, HttpOnly doesn't really help you at all. You should be setting a CSP that prevents inline and 3rd party scripts by default, and whitelist what you must.
Overall, cookies may seem like they have a lot of security features, but in reality they are just patches over poor original design. IMHO, using local storage is probably better, because there's less room to get it wrong.
Here's one glaring problem with local storage: literally any script on your page can access it (for example, vendor scripts). Cookies can only be accessed by scripts from the same domain from which they're created.
Why should those scripts limit themselves to stealing tokens when they can send authenticated requests from the browser? To put it another way, why would you care about knowing the root password when you have a way to run a root shell at will?
Let's get specific: let's say you have a page on mysite.com. When a user signs in, the server sets a HttpOnly session cookie to authenticate later requests from the user.
Now let's assume your page loads evilsite.com/tracker.js. The code in tracker.js can now send requests to mysite.com, and your HttpOnly session cookie will be sent. There is no extra protection for cookies that would check if the JS code doing the sending came from mysite.com.
Obviously tracker.js cannot read the value of your session cookie (and, indeed, neither can your own code), but mysite.com is more or less totally compromised.
If you don't set HttpOnly on your cookies and ignore the cookie header on your backend (i.e. only use cookies for storage, not for transport), cookies are strictly better than local storage, since the only difference between the two is now local storage's lax access policy.
The scenario you're describing can also be solved by using a CSRF token retrieved from the backend. Meanwhile, there is literally no way to secure secrets kept in local storage from third party scripts.
I don't believe a situation exists where using cookies for client-side storage is more secure than local storage. Could you please explain this in more detail?
Now assume your page loads evilsitem.com/tracker.js. They can send requests to your backend, and the cookie will be included, but since your backend ignores the cookie header it doesn't matter. The malicious script, however, cannot access the cookie directly, since the script's origin is not the same.
That's why I say cookies used this way are strictly more secure than local storage: the fact that they're included with every request is irrelevant, and they're protected from direct access by third party scripts. Local storage is not. Even if you use JWT for auth, you should still store it in a cookie.
The same-origin policy only limits access between windows and frames. All scripts loaded on a page will have the same "origin".
What do you mean? JS even on the same page can't read HTTPOnly cookies. If you are assuming that the browser has been hacked then it is pretty much game over regardless of what you use.
Why do you think so? I would guess it's a tradeoff about what you think is more likely to happen. XSS or CSRF.
Local storage (and session storage) is vulnerable to XSS. Use a strict content security policy and escape (htmlspecialchars in php and similar functions in other languages) output to combat that.
Cookies are vulnerable to CSRF but can't be read from JS if they are http only (no XSS). To combat CSRF most frameworks already have built-in csrf token support. In case of a API use a double submit cookie. Frameworks like AngularJs/Angular support that out of the box. Also use the secure flag SameSite and __Host prefix [0][1]
[0] https://www.youtube.com/watch?v=2uvrGQEy8i4
[1] the slides from the video: https://www.owasp.org/images/3/32/David_Johansson-Double_Def...
It's true that a attacker simply can generate requests from the XSS'ed browser, my understanding was that the session/token is more valuable to an attacker then only an XSS exploit.
However it seems that someone in the past had the same understanding as me and tptacek disagreed [0]. Oh well. Also reading the linked article [1] (are you the author since you use the same wording?) and it's linked articles it seems both cookies and webstorage are not ideal solutions, but local storage might be preferable since CSRF is not a problem, so one thing less to worry about.
[0] https://news.ycombinator.com/item?id=11898525
[1] https://portswigger.net/blog/web-storage-the-lesser-evil-for...
I really like this trick! Not only do you now have a log of "shady stuff" happening, but you've gotten rid of the now compromised tokens instantly!
HTTPS runs over port 443, and port 80 is normally for HTTP only.
Most people setup their webservers to serve HTTPS over 443 and redirect port 80 to 443 so anyone that sends something to `http://example.com` automatically gets forwarded to `https://example.com` (and then the browser can tell them to ONLY use the HTTPS version from that point forward)
This is a generally "acceptable" tradeoff between usability and security.
But when you control the API and the client, you can know that you will never send credentials over HTTP, only HTTPS. So you should have nothing coming over port 80.
Then, with a simple script, you could set it up so that it will accept everything on port 80, and if it includes a token of some kind from your app, it logs the request, then marks the token in your database as "expired" so it can no longer be used anywhere (even on port 443).
There's a kind of attack sometimes called "SSLStrip" which can block all requests for someone to an HTTPS version of the site, and in many cases can trick the client into trying the HTTP version if the HTTPS fails. This kind of thing would not only stop that attack, but it would also log it and ensure that any tokens sent that way would be instantly expired, so that the attacker (who saw the tokens when the client tried to send them) can't use them.
There are other reasons too. It will notify you of any developer-mistakes that are sending credentials over HTTP (it's a one letter difference, and despite the best efforts sometimes these kinds of things slip into a codebase as typos or a dev just not thinking), and it can help you tell "scanning" traffic from "normal" traffic (since nothing in your app will ever talk to port 80, so everything on port 80 is "bad" and can give you some clues into what attackers are trying on your network).
And the best part is that it's easy! I could probably throw something together for our API servers that does this in a day or so start-to-finish. That's a REALLY good ratio between time spent and security benefit that you normally don't get!
Not all bearer tokens have this property.
A JWT token is composed of three parts: a header, payload, and signature.
The problem is that people can put sensitive info in the payload.
None of it is encrypted, it's only signed with HMAC.
Unless you're keeping track of the tokens, once a token is issued it's valid until it expires, due to it's stateless nature.
You can use a JWT as a Bearer token, but since it's only base64 encoded, you can pull out that payload data.
A truly opaque Bearer token will be meaningless to anything other than your server.
Play with the debugger here to see what I'm talking about: https://jwt.io/
However, I wouldn't throw other anti-CSRF measures away because if the attacker can use a stored XSS vuln, they can still make their way to a CSRF as well. Besides that, not all browsers support SameSite flag yet.
There's value to many in SaaS offerings, but any decently-sized programming ecosystem has a crap ton of auth offerings. e.g. Devise [0], Dotnet Identity [1], Django Auth [2]. Authorization is the fiddly/annoying part. For authentication, a reasonably motivated developer can expect to have workable, secure password authentication going in a couple hours, as long as they don't try to invent their own encryption scheme.
[0]: https://github.com/plataformatec/devise [1]: https://docs.microsoft.com/en-us/aspnet/core/security/authen... [2]: https://docs.djangoproject.com/en/2.1/topics/auth/
Simplicity is also Security
OpenID is a mechanism for one website to assert a user's identity to another website. OAuth is a way to let a user delegate access to some of their data on one site to another site. Neither have any particular affinity with the healthcare space, and they are not things you sprinkle on for extra security.
[0] https://www.hhs.gov/hipaa/for-professionals/security/index.h...
I highly recommend talking to someone who knows HIPAA well.
That's before the law gets involved as well.
It's definitely not enough alone, but at least gets you going on the security & compliance aspects.
GDPR is good in that regard as the standards are high and apply to more than just electronic storage/interchange.
Are these useful?
Here's the Code of Practice for NHS organisations and staff: https://www.gov.uk/government/publications/confidentiality-n...
Here's the other code of practice for everyone working with NHS data: https://digital.nhs.uk/data-and-information/looking-after-in...
And here's the guidance about when to share if it's needed: https://digital.nhs.uk/data-and-information/looking-after-in...
Alternatively you can use the auth code flow baked into lambda; if you have premium support make a case and someone can walk you through it :)
What I wish is Apple and co would give the consumer choices. I am a low threat target; I don't need to enter a pw to unlock the SIP. So presenting a fingerprint + a hardware key would be a huge security improvement and a reasonable defense against 99.9999999% of the threats I face. Unfortunately, Apple assumes we're all being targeting by physical attacks from the NSA, decreasing my convenience level for a non-existant threat.
I think this is a rather sweeping, and wrong, generalization.
Though the chattering masses on HN may not be HIPAA devs, that doesn't mean there aren't HIPAA devs here. I'm one of them.
Every time someone brings up an obscure topic on HN, there always seems to be a group of people who specialize in that topic that come out of the woodwork and have fascinating insights.
The largest number of commenters on HN seem to be Googlers, Facebookers, and one man bands. But there are plenty of, for example, Apple devs on HN. They just choose to keep the S/N ratio high.
There is approximately never a good reason for a team to roll their own authentication solution from the base primitives unless that's both their core competency and their product differentiation. It offers virtually no upside for virtually certain downside.
- Your authentication problems are not unique to you;
- The effort of implementing standards (whether it's front end like OAuth, OIDC, or SAML or back end like hashing) is a pain in the butt and easy to make bad choices;
- If your project is successful or as your requirements change over time, now you have to figure out how to add MFA, password resets, internationalization, address security audits, etc, etc.
Doing it yourself means you have 100% responsibility for everything when that is probably not your main skillset or really what you want to spend your time doing anyway.
Disclosure: I work for one of the companies mentioned in this thread.
Good stuff.
Also, I have a question for you, is there a good place to reach you?
Authentication asserts identities. Authorization asserts capabilities. This shifts and compartmentalizes the problem somewhat. Almost all interactive applications need to support robust authentication, but most applications do not require the sophisticated authorization restrictions HIPAA demands.
Whatever it is you choose, you should:
1) Use a mature, reputable library;
2) Use a library which provides the simplest possible interfaces for solving your needs in the most turnkey manner;
3) Engage with a reputable consulting firm specializing in HIPAA compliance and application security.
I would also recommend reading through as much information about Aptible's architecture and design ethos as possible. They have done an excellent job of navigating this problem space.
The problem is that you can't know whether that's the case at start, at some point in the future, or never. You'll only find out that your guess was wrong when you're breached which is never a good time for any service, particularly one covered by HIPAA. Besides, why intentionally implement a known-to-be-insecure second factor method? This is brand new code; there's no need to incur technical debt from day one. Which leads to:
> It's a good place to start until you are at a scale where you would have dedicated security engineers to work on the problem.
Except that day never comes for a variety of reasons. "Users already expect it so we can't remove that." "There are several dozen other security audits/features/fixes we need to make, let's prioritize those first." "What? SMS is insecure? Weird, never knew that."
Also, if we don't start making the decision now, before the second factor is ever implemented, to move away from using SMS as that second factor for the reasons it is known to be broken, when do we start?
The library I've linked brings up a good point to make sure that you know the difference between decoding and verifying the token, but after that it's fairly plain sailing.
[1]: https://jwt.io [2]: https://github.com/auth0/node-jsonwebtoken [3]: https://auth0.com [4]: https://jwt.io/introduction/
After that we no longer store these details.
We've been using amazon cognito with lambda authorizers.
It can easily be connected to any API without much "glue". And most common open source services already support it as auth backend.
It's also easier to audit than any custom service you might concoct on your own because auditors already have experience with it through Active Directory.
Most advice in the comments is pretty bad though. Stuff like "API Clients need bearer tokens" is completely backwards and pushed by marketing people from companies (Auth0, Okta, ...) that misuse open protocols (OAuth2, OIDC) as a way to legitimize the closed source saas approach they took. Along the lines "if it looks complex it looks secure because most people have no idea". It's actually very easy to use cookies (httpOnly, secure) with API clients and you're saving yourself so much complexity with refreshing tokens and all that stuff.
Yet another possibility for super rapid prototyping is: https://github.com/bitly/oauth2_proxy
edit:// I forgot KeyCloak, but it's also for advanced enterprise use cases (SAML, OIDC, Realms, ...) and (from what I've heard) with a steep learning curve and heavy.
Can you elaborate on how they "misuse" them? I don't have any familiarity with those two companies, generally curious. Thanks.
For authorization you are going to have to implement your own solution once you have an authenticated session. What someone can do always depends on your app and the functions you provide and so there is no nice third party solution to this. In my case I store the map of users to roles and what a role can do in a PostgreSQL app and cache there the answers to "which users are in a role" and "what can a role do"... user permission and roles changes are infrequent but flush the cache and so take immediate effect.
As a user performs activities, this may involve a scenario requiring escalation or revocation of authorization roles and corresponding permissions. Invalidate cache at this moment. Lazy cache updated authorization info upon next request.
(I authored Yosai)
From there, it's a bearer token encoded in JWT format for ease of debugging. From another NuGet.
We also support username and public key authentication for our SFTP server.
We do support username and password if necessary.
Hire an expert.
If you can't answer these questions yourself (which is fine - it's specialized knowledge separate from the skillset needed for building a useful application), you are lacking critical competence for coding anything handling health information.
The security minefield is much much bigger than the login page.
Then I read the last paragraph of the question.
Please follow this guy’s advice. As someone whose medical data you might one day be handling: please get someone who does this well.
Imagine you (or a family member) ever end up sick; your medical data ends up on Pastebin, and the arstechnica article about it surfaces a forum post from the engineer responsible: “hey guys howto auth?”. Honestly: how would you feel?
I agree with your conclusion (especially in a comment down the thread about nurses), and just wanted to add to something you said, because I often come across this sentiment that learning by doing is how professionals become what they are, and wanted to play with that idea. In tech, this sentiment is often reinforced by stories like Elon Musk learning how to build cars and rockets by reading books (which he did, but the truth is more that he surrounded himself with trained professionals who could design and execute). In my mind, to be a trained professional requires:
* conscious practice over a long period of time (in order to see all the variations)
* correct feedback from work, peers or masters (community)
* access to the right tooling and body of knowledge. (guilds, journals, trade secrets)
In many areas of programming, these are achievable by a competent individual working alone, but sometimes these factors aren't there but appear to be, which can lead to false and misleading knowledge. In my own area of numerical mathematics, sometimes newbies try to roll their own linear solver (a seemingly easy exercise), not realizing the full body of research and knowledge there is behind handling corner cases. Also, there are myriad tricks-of-the-trade (guild secrets) that are really hard to learn from just reading code -- but that one can learn from osmosis/word of mouth if one works in a lab or research group. This is why it takes years of doctoral and postdoctoral studies to churn out a good numerical analyst.
The CS analogy would be someone rolling their own database from scratch. In these endeavors, the baseline of knowledge to get started is very low, but the real-world knowledge required to make the product robust needs to be built-up over time and by many competent people (through collaborations/teams/community).
I just wonder if security/auth/crypto products fall into these complexity categories, and perhaps it might not be easy--or indeed possible--to become a professional as an individual (without the right conditions in place), and that it might make sense to "stand on the shoulders of giants" as it were, which was your original point.
the comparison is between "how does anaesthesia work?" (A) and "how does auth work?" (X), relative to "about to perform surgery at home" (B) and "about to implement a service containing medical information" (Y).
The point is: he's about to do something big, and is asking a basic question. The real problem is not the basic question (auth) but the context he's doing it in.
If a nurse in training, in a classroom setting, asked about anaesthesia, it'd be fine. If they're a doctor, about to operate on a live patient, it's different.
There isn't enough information on the question to tell wether the OP is a complete novice with no idea of the minefield he is getting it, or if he is somebody competent that wants a list of current practices to start further research.