This question comes up all the time on HN. I'm one of a bunch of people on HN that do this kind of work professionally. Here's a recent comment on a recent story about it:<p><a href="https://news.ycombinator.com/item?id=16006394" rel="nofollow">https://news.ycombinator.com/item?id=16006394</a><p>The short answer is: don't overthink it. Do the simplest thing that will work: use 16+ byte random keys read from /dev/urandom and stored in a database. The cool-kid name for this is "bearer tokens".<p>You do not need Amazon-style "access keys" to go with your secrets. You do not need OAuth (OAuth is for <i>delegated authentication</i>, to allow 3rd parties to take actions on behalf of users), you do not need special UUID formats, you do not need to mess around with localStorage, you do not need TLS client certificates, you do not need cryptographic signatures, or any kind of public key crypto, or really any cryptography at all. You almost certain do not and will not need "stateless" authentication; to get it, you will sacrifice security and some usability, and in a typical application that depends on a database to get anything done anyways, you'll make those sacrifices for nothing.<p>Do <i>not</i> use JWTs, which are an increasingly (and somewhat inexplicably) popular cryptographic token that every working cryptography engineer I've spoken to hates passionately. JWTs are easy for developers to use, because libraries are a thing, but impossible for security engineers to reason about. There's a race to replace JWTs with something better (PAST is an example) and while I don't think the underlying idea behind JWTs is any good either, even if you disagree, you should still wait for one of the better formats to gain acceptance.
Do everything via HTTPS, disable HTTP.
The login request (POST, dont use url query params) contains username + password. The API replies with a session token (a random string). You can store any metadata relating to this session token in your DB.<p>The API client should this token in every request that requires authentication, often in the header as `Authorization : Bearer 123TheToken456`.<p>JWT:
If DB performance becomes a problem (or you want to expose signed session metadata) consider using JWT to provide session validation with the request itself. The downsides of JWT are that its often used to hold secret values (dont do this), or is a few kilobytes big which makes all requests slow, or stupid mistakes in signing and session validation that make it very insecure like allowing any request to just specify false permissions.
I highly recommend reading "The Do's and Don'ts of Client Authentication on the Web" [1] from MIT. It's rather old and not very well-known, but it's excellent. The concepts provide very useful background info that will serve you well no matter what technology you use to implement your HTTP services, including issues like session hijacking, etc. One of it's best recommendations: avoid roll-your-own solutions. Secondly, I recommend checking out the "auth" example from the expressjs repository on github [2]. It will provide a practical implementation example. Lastly, if you're considering using Express or any similar framework, I recommend checking out "route parameter preconditions". These seem to remain a little-known feature of Express, but they can be particularly useful for applying middleware to entire sets of routes, for example enforcing authentication on anything under a certain path. You can still find screen-casts for route-specific middleware and route parameter preconditions on the Express 2.x documentation site by TJ, the original author [3]. Some of the specific details may have changed in the newer versions of Express, but TJ's explanation of the concepts is simple and clear.<p>[1] <a href="https://pdos.csail.mit.edu/papers/webauth:sec10.pdf" rel="nofollow">https://pdos.csail.mit.edu/papers/webauth:sec10.pdf</a>
[2] <a href="https://github.com/expressjs/express/blob/master/examples/auth/index.js" rel="nofollow">https://github.com/expressjs/express/blob/master/examples/au...</a>
[3] <a href="https://expressjs.com/2x/screencasts.html" rel="nofollow">https://expressjs.com/2x/screencasts.html</a>
Why not use either simple API key or HTTP basic auth? Both are simple to implement and supported by all the tools and libraries.<p>I would consider more complicated solutions only if you first come to conclusion that these simple things are not fit for the purpose.<p>True that some fancy token based solution may reduce database load, but if the API is doing something useful then that one primary key lookup and potentially the password hashing won't be a show stopper. Drawback with tokens and skipping the DB check is that you can't simply kill a client behaving badly. With API key you can just change the key and requests stop immediately (with MVP product this might be an issue, since maybe you have decided to add rate limits etc later).
It depends on the use-case.<p>* Public data API (no notion of user account, e.g. weathers API, newspapers API, GitHub public events, Reddit /r/popular, etc): use an API key. The developers must create an account on your website to create their API key; each API call is accompanied by the API key in the query string (?key=...)<p>* Self-used API for AJAX (notion of user account, e.g. all the AJAX calls behind the scenes when you use Gmail): use the same user cookie as for the rest of the website. The API is like any other resource on the website except it returns JSON/XML/whatever instead of HTML.<p>* Internal API for micro-services: API key shared by both ends of the service. There can be a notion of user accounts, but it's a business notion and the user is an argument like any other. If possible, your micro-services shouldn't actually be accessible on the public Internet.<p>* API with the notion of user accounts intended for third-parties (e.g. Reddit mobile app where the users can authorize the app to use their Reddit account on their behalf): OAuth2
Hi,
can someone explain me why SSL client authentication is not widely used? You can use the same protocol you use to authenticate hosts to authenticate users, yet no one seem to do that nowadays.
I'm not professional web developer so maybe answer to this question is obvious (but I just don't know it).
PAST looks good.<p><a href="https://github.com/paragonie/past" rel="nofollow">https://github.com/paragonie/past</a><p>Basically JWT but without the pitfalls as far as I can see.
I’d say it depends a lot.<p>If your API just serves public non-user-specific data, a simple API key might be okay. The obvious downside of this method is that a user leaking their client API key is a big problem, especially if your users are likely to distribute code that makes requests (e.g. a mobile app that makes requests to your API).<p>The state of the art is probably still OAuth, where clients regularly request session keys. This means a leaked key probably won’t cause problems for very long. The obvious downside of this is complexity, but that can be mitigated by releasing client libraries that smooth over the process.
AWS has their own v4 signature method that I always thought was neat.<p>Key benefits:<p>* Secret not included in request<p>* Verifies integrity of the message (since its contents are signed)<p>* Protection against replay attacks<p>It's probably overkill in a lot of situations, but I've always liked how even if TLS were compromised, all the attacker would gain is the ability to see the requests--not modify them or forge new ones.<p>I haven't used JWT before, but reading one of the links below, it looks like it covers a lot of the same stuff (although you'd have to implement your own replay protection if you want that).
One generic solution is to have identity on the server (users table) and generate one or more tokens for each user. When a user wants to make an authenticated API call, they have to add the approprite header to their request:<p><pre><code> curl -X GET https://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b'
</code></pre>
Note: HTTPS is required for all of this to be secure.<p>This is what comes out of the box with Django Rest Framework.
It makes me sad that in 2018 that it is entirely reasonable for such a simple and common question to elicit so many answers. Of course no one solution fits all use cases, but skimming the comments there seems to be a very diverse range of suggestions. Wouldn't it be lovely if there was one stand-out solution that was so good it was a no-brainer?<p>FWIW I have ended up using OAuth2 for this situation a few times, and it always feels more complicated than I'd like.
Auth0 and Okta have tons of docs on this. Even if you don't use their services, they have much to read.<p>Also, here is a good recent video for ASP Net Core 2, that includes extra things like HSTS, etc. Even if your not in ASP, the concepts will be relevant <a href="https://www.youtube.com/watch?v=z2iCddrJRY8" rel="nofollow">https://www.youtube.com/watch?v=z2iCddrJRY8</a>
OpenId its an extension of OAuth. OpenID provides "Authentication" while OAuth or JWT provides "Authorization." But the real question is what language are you using? If you are using ASP.NET I'd recommend reading this: <a href="https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/individual-accounts-in-web-api" rel="nofollow">https://docs.microsoft.com/en-us/aspnet/web-api/overview/sec...</a>
If there is nothing special about it, I'd recommend JWT, for the simple reason that you have less load on your DB (and more on your CPU but that is usually not the bottleneck)
There is no single good answer to this question without taking into account the security consideration of the API in question and the consumers. On a high level all solutions work just fine as long as we understand the tradeoff's involved (cpu, IO, revocation, complexity,..).
The different solutions that could be tried with ease are:
1. Network filtering - If the API consumers can be limited by identifying their IP addresses
2. Bearer tokens - Simple random string that can be passed in the header (depending on number of consumers, ability to revoke/change tokens it can become little complex)
3. JWT's - Similar to bearer tokens without the ability of revocation and extra cost of key management and CPU (the signature verifications are quite costly).
4. OAuth - Better call it 2-legged OAuth since its between servers only. Its the ideal one with both revocation possibility and signature verification.<p>The first three could be implemented easily inhouse and are suited when number of consumers are small. Its better to use some third party SAAS service or OAuth server for the fourth one. I work professionally on these things and these implementations can be time consuming. More than often people dont take into account their requirements when choosing a solution.
If you are looking for something along the lines of OAuth2 - you should BTW! Highly recommended if your API is going to be consumed by first-party client apps on different platforms or third-party clients - one of the best setups I've come across is Laravel Passport[1].<p>If you don't mind running a PHP application, or it being built in Laravel, (I don't, but some do) it's actually a really good implementation of a solid OAuth package[2] (Disclaimer: I am a maintainer on oauth2-server).<p>You can set this up in a couple of days, and it'll be ready to roll for the majority of use-cases. With a few simple tweaks and additions, you can have it doing extra stuff pretty easily.<p>In one build I'm working on, this acts as just the authentication layer. The actual API that relies on the tokens this generates sits elsewhere and could be written in any other language (it's not in this case).<p>[1]: <a href="https://github.com/laravel/passport" rel="nofollow">https://github.com/laravel/passport</a>
[2]: <a href="https://github.com/thephpleague/oauth2-server" rel="nofollow">https://github.com/thephpleague/oauth2-server</a>
Anyone know amy good resources for the following scenario:<p>WEB API that a device needs to authenticate to.
Can't store password on device (it's a device we don't control).
No user, so authentication has to be all autommated.<p>i.e. we need to run software on a clients machine, and it has to authenticate to our web api to send us data.<p>We obviously don't want to hard code the credentials in the software as that can be trivially extracted.
Just wanted to throw Azure API Management out there <a href="https://azure.microsoft.com/en-us/services/api-management" rel="nofollow">https://azure.microsoft.com/en-us/services/api-management</a><p>If you happen to be using Azure. I found it very useful for everything you'd want to do with your API, one of them being able to tie down security as much or as little as you need. It even builds a front end for anyone who has access to use for reference. But that's just one of the cool features.
From the cheap seats (as I am a liberal arts major) and currently an entrepreneur trying to launch some microservices for my resume editing and other professional services business using R-project and the plumbing api creator package. What about a fairly lengthy random password provided to clients (human beings) they input into the intake form using Typeform, then the underlying code checks for it in the "authorized" file and removes it after 1 time use? The form feeds the api inputs directly.<p>TIA.
Depending on your usecase, a quick setup would be to use <a href="https://auth0.com/" rel="nofollow">https://auth0.com/</a> They have a lot of documentation and samples to get started.<p>We have implemented it for authentication with a Asp.Net Core webservice, with a REST based API. Authorization is also possible, either by working with the JWT token scopes, or using the Auth0 app_metadata.
Depends on what you want. You can just use an API key if it's for easy access, through a header.<p>If you want more, then use username + pass. Encrypt both or generate something from both of them. Eg. encrypt(username):encrypt(pass)<p>If you want more, use private & public keys, which receive a session token the first time ( when authenticating).<p>...<p>I think the end result would be a self hosted oauth server with permission management.
Authentication is such a mess, I don't even know where to begin. Most APIs rely on some sort of token-based auth, communicated via the header format: "Authorization: Bearer abc123", as opposed to placing it in the Cookie, as most web sites will do. Many solutions exist, like OAuth2, JWT, etc. but that's ultimately what it all boils down to.
If you choose to use JWTs I suggest still keeping a database of tokens and validate against that. This way you have an option to revoke the token and force client to get a new one. This is useful for when token data becomes stale, e.g. email changed, roles added etc. Simply keeping it all in token is not enough.
I think that Auth Tokens are easy to understand, use, and implement. They can generally be invalidated if the developer feels that they have been compromised.<p>Some APIs also use self-invalidating auth tokens based on an expiry date. For more secure data, I'd prefer that.
Auth Tokens are easy to work with for customers and the API developers. Generate a token, and then authenticate. I prefer them.<p><a href="http://page.rest" rel="nofollow">http://page.rest</a> does a good job.
JWT is pretty easy to understand.<p>Create a token, put your userId in it, set an expiry date.<p>If a request comes with a token check if token is valid, check the userId & expiry date otherwise throw error.
I suggest JSON Web Tokens. Check this out <a href="https://jwt.io/introduction/" rel="nofollow">https://jwt.io/introduction/</a>
I have an internal REST API (Tomcat server) on a Windows network that uses the WAFFLE library.<p>I am interested to know whether HN thinks this is considered secure?