8 ms·
Ask HN: What's the recommended method of adding authentication to a REST API?
- sidhuko 9y agoFor users or applications within your own network?
- somtum 9y agoWhat would you recommend for both?
- mcjiggerlog 9y agoWithin your own network a simple key/secret combination is enough, as the secret can just be stored as an environment variable, for example. For users you'd need some way for the users to "fetch the secret", which is effectively what logging in is. At that point you should just use JWT or oAuth.
- sidhuko 9y agoFor applications using a HMAC token with some sort of timestamp which can be checked for replay attacks. AWS has a good guide: https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html https://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthenti.... For users, I'd add a OAuth layer to the application layer and still have this application using a HMAC like above. You want to try keep things 'stateless' when it comes to your API's.
- tristan_ph 9y agoI suggest JSON Web Tokens. Check this out https://jwt.io/introduction/ https://jwt.io/introduction/
- mcny 9y agoI would suggest everyone to stay away from jwt unless they're willing to spend the time to learn how it works. I believe the meta is that jwt is solid itself but allows doing things "wrong". Guardrails so to speak are insufficient if not outright lacking. I'd say just go with plain text token for a web app. I don't like the idea of trusting the client because I don't understand how jwt works.
- Raed667 9y agoTrusting in what sense? If my token only has the userId as data, what kind of trust is needed?
- mfontani 9y agoSome libraries don't make it easy (or possible) to check that the algorithm used by the JWT sent by the client is in fact the algorithm you're using and want the client to come back with, see i.e. https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/ https://auth0.com/blog/critical-vulnerabilities-in-json-web-...
- Raed667 9y agoI see, but sticking to HS256 should solve this without much headache.
- catchmeifyoucan 9y agoAuth Tokens are easy to work with for customers and the API developers. Generate a token, and then authenticate. I prefer them. http://page.rest http://page.rest does a good job.
- spdionis 9y agoOauth2 tokens or jwt.
- MaxBarraclough 9y agoSeems to me the answer is indeed that simple: use OAuth2 and be done.
- sidhuko 9y agoSo you need to get an access token by validating against a third-party (keycloak, auth0) to access your own API? That's a pain.
- MaxBarraclough 9y agoThird-party? Token-issuance is just another endpoint, no?
- spdionis 9y agoJust use a regular oauth server library in your language/framework of choice.
- davewritescode 9y agoOAuth 2.0 is so bloated that it scares people off. Something like the client credentials flow is relatively easy to implement on your own and is basically lets clients exchange a client_id (username) and secret (password) for an API key. Bonus: If you stay close enough to the standard you can plugin a real OAuth 2.0 provider if/when you decide you need it.
- MaxBarraclough 9y ago> OAuth 2.0 is so bloated that it scares people off I think we're thinking the same thought, maybe my terminology is sloppy. Suppose we just say "Use this token-generation endpoint (with your credentials) to generate a session token, and attach that token by means of OAuth 2.0 Bearer Token in subsequent requests to other endpoints". Doing that, we can easily scythe off any bloat, no? We don't care about people signing-in with their Google accounts, or anything like that. Or is that what 'client credentials flow' means?
- Raed667 9y agoJWT is pretty easy to understand. Create a token, put your userId in it, set an expiry date. If a request comes with a token check if token is valid, check the userId & expiry date otherwise throw error.
- sidchilling 9y agoI 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. Some APIs also use self-invalidating auth tokens based on an expiry date. For more secure data, I'd prefer that.
- baddox 9y agoI’d say it depends a lot. 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). 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.
- fyfy18 9y agoOne thing to be aware of with OAuth 2.0 is Refresh Tokens. If the spec is followed, the Refresh Tokens are long-lived and never expire (the spec makes a suggestion that you revoke used tokens, but it's not required), so if they are leaked you are in for a bad time. There's an RFC that goes into some of the security considerations of OAuth 2.0, that should be required reading if you implement it (even from a pre-built library): https://tools.ietf.org/html/rfc6819 https://tools.ietf.org/html/rfc6819
- Fradow 9y agoIf the Refresh Tokens are leaked, you revoke them and the user has to re-authenticate. It's crucial that clients are able to respond to their refresh tokens being revoked. The good thing is that it is a standard workflow, contrary to API key being revoked, which is generally not handled (most people hard-code API key in their client).
- imtringued 9y agoWhat's the appeal of tokens that never expire? You cannot delete the revokations after the token has expired.
- mattmanser 9y agoCan you explain why only "public non-user-specific data" is suitable for basic auth over HTTPS? For most SasS products, basic auth or an API key is going to be fine. In fact, a ton of SasS vendors do exactly that. It's also totally fine for, say, an enterprise API used by a partner or clients. Oauth is a cluster-fuck of terribleness, a nightmare for you to work with and a nightmare for your consumers to use. If you do it, you will need to have excellent support docs and examples or have to hand-hold external devs to get it working. The only time I might start considering OAuth is if you want other apps to be granted permissions to use the API on behalf of the user, where you want some granularity of which parts they can access. I'm not saying OAuth doesn't have a use, but it's awful, overcomplicated implementation means it's a huge time-sink compared to basic auth over HTTPS and I certainly wouldn't recommend it without a very good reason.
- nautical 9y agoOAuth(Robust, Many Libraries), JWT(Easy to understand and implement), API Keys/Tokens(Simple and fast)
- stillbourne 9y agoOpenId 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: https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/individual-accounts-in-web-api https://docs.microsoft.com/en-us/aspnet/web-api/overview/sec...
- LandR 9y agoAnyone know amy good resources for the following scenario: 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. i.e. we need to run software on a clients machine, and it has to authenticate to our web api to send us data. We obviously don't want to hard code the credentials in the software as that can be trivially extracted.
- perlgeek 9y agoIdeally you use some kind of time-limited API tokens, and find a way to automatically distributed new API tokens, before the old ones expire. That way, the breach of a single device doesn't immediately give the attacker unlimited access to the API. You should also monitor for unusual activity, and blacklist API keys and devices with such activity.
- dmichulke 9y ago1. As secret, use encrypted(some internal device id, pregenerated-key) 2. Generate pregenerated-key upon first login (maybe based on email or tel no?). Just like, e.g., Signal does it 3. On your servers, check if pregenerated-key and/or email is used more than once at the same time, if so invalidate it and direct user to 2.
- LandR 9y agoWe already do number 3 :) We monitor for the same login being used twice at the same time and disconnect both and delete the account.
- Fredej 9y agoCould it be a possibility to generate a keypair on the machine and then attempt to register itself to your webserver supplying client-name, IP and public-key. Then you would be able to see and OK any attempts to connect. Once you've OK'ed it, it would be able to authenticate and communicate normally as an authenticated device.
- icebraining 9y ago
- scandox 9y agoPAST looks good. https://github.com/paragonie/past https://github.com/paragonie/past Basically JWT but without the pitfalls as far as I can see.
- Spone 9y agoDownside is that this is very new and there is only a PHP library.
- j_s 9y agoDefinitely depends on timeline; PAST is a reasonable recommendation gaining momentum as best practice. The recent Show HN annoucement discussed many caveats of authentication tokens: Show HN: PAST, a secure alternative to JWT | https://news.ycombinator.com/item?id=16070394 https://news.ycombinator.com/item?id=16070394 (2018Jan:361 points,137 comments)
- jongpieter 9y agoDepending on your usecase, a quick setup would be to use https://auth0.com/ https://auth0.com/ They have a lot of documentation and samples to get started. 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.
- dmichulke 9y agoIf 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)
- Chriky 9y agoI have an internal REST API (Tomcat server) on a Windows network that uses the WAFFLE library. I am interested to know whether HN thinks this is considered secure?
- belyakov 9y agoIf 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.
- niwde 9y agoUse Access-control-allow-origin and set it to only allow calls from a specific address.
- ssudaraka 9y agoCan someone fake the origin?
- fimdomeio 9y agoThis is controlled on browser level and most (all?) browsers implement this. Origin can be faked by just using anything that can make a http request, like curl. It exists to protect users not the server.
- askthrowaway 9y agofrom browser ? No. from non-browser clients like curl ? Yes. And your server will never be able to tell if it is fake or not
- jpalomaki 9y agoWhy not use either simple API key or HTTP basic auth? Both are simple to implement and supported by all the tools and libraries. I would consider more complicated solutions only if you first come to conclusion that these simple things are not fit for the purpose. 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).
- comradesmith 9y agoHTTP Basic authentication should never be used, it is very vulnerable to traffic analysis attacks. HTTP Digest authentication however, would be a perfectly fine solution.
- dozzie 9y agoHow so? Over SSL? (Note that you should never call anything requiring authentication/authorization over plain HTTP.)
- comradesmith 9y agoA quick Google suggests you're right, as in either case you must run SSL/TLS. Appypolylogies.
- deleted 9y ago[deleted]
- alex_duf 9y agoI would agree, always start simple - unless you manipulate sensitive data - a shared secret is a good place to start (api-key or basic/digest auth) You can always introduce other forms of authentication later. I have a slight preference for basic/digest auth as the secret isn't part of the URL, and therefore not cached/logged by any network equipment.
- barrystaes 9y agoDo 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. The API client should this token in every request that requires authentication, often in the header as `Authorization : Bearer 123TheToken456`. 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.
- fimdomeio 9y agoI basically do this with jwt. In my case jwt just contains the basic data that the front needs to find out who the user is and what it can do (user uuid and role). While obviously checking if action is allowed to user is done server side it's normally useful for the front end to also be aware.
- jcadam 9y agoYea, I happen to be using JWT in the simplest way. Authentication only. I don't even store role information in them, since authorization checks are performed on the server anyway. If the client needs to know what a user is allowed to do with a resource (so it knows not to display certain buttons, etc.) I have the client do an OPTIONS call (with the token) to see what methods are allowed. Lately, I've been thinking about replacing the whole JWT scheme with simple bearer tokens stored in the database, mostly because it would make revocation simple and I can't think of anything I would lose by giving up JWTs (a little storage space in the database?), and I don't think switching the type of bearer token I'm working with will actually be very painful implementation-wise. You know what, I'm adding a task to my backlog...
- sethgecko 9y agoDoesn't a session token violate the stateless principle ?
- ivan_ah 9y agoOne 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: curl -X GET https://127.0.0.1:8000/api/example/ -H 'Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' Note: HTTPS is required for all of this to be secure. This is what comes out of the box with Django Rest Framework.
- moduspwnens14 9y agoAWS has their own v4 signature method that I always thought was neat. Key benefits: * Secret not included in request * Verifies integrity of the message (since its contents are signed) * Protection against replay attacks 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. 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).
- NicoJuicy 9y agoDepends on what you want. You can just use an API key if it's for easy access, through a header. If you want more, then use username + pass. Encrypt both or generate something from both of them. Eg. encrypt(username):encrypt(pass) If you want more, use private & public keys, which receive a session token the first time ( when authenticating). ... I think the end result would be a self hosted oauth server with permission management.
- EngineerBetter 9y agoIt 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? FWIW I have ended up using OAuth2 for this situation a few times, and it always feels more complicated than I'd like.
- liquidise 9y agoThis is arguably self-serving but I am happy there isn’t one. The appeal to coding is that it hasn’t matured to being computerized LEGO’s, where I spend my time connecting prebuilt components unspecialized for my application. But we are not alone in this regard. Bridge building is centuries more mature than software engineering and their shapes, materials and construction methods still change regularly. I would expect to see this trend remain for a long time. Engineering is an inherently creative practice, often staffed by appropriately creative people. The continued evolution, including the trial and error approach, are likely to continue for decades.
- trevor-e 9y agoI do agree with your sentiment, but is creativity something we want to encourage with security? Security is hard, and most developers won't know when they've made a mistake implementing something. The laws of physics haven't changed for bridge builders. In the end, everyday consumers are the ones suffering from the recent hacks.
- 6ue7nNMEEbHcM 9y agoHi, 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).
- weitzj 9y agoProbably good missing browser support. I mean with support: getting the certs in there. Once they are in your keychain, clientcerts are really nice.
- homero 9y agoI also want to know. It's extremely secure. It's also how I'm blocking my origin ip to where only Cloudflare can access it in case it's leaked. Safer and easier than a whitelist.
- acdha 9y agoFor public services, getting users to have keys and install them in their browsers is quite hard. For APIs, it should be more manageable but many places stumble with key management and a lot of developers were resistant to learning enough about the tooling to do things like manage test instances.
- 6ue7nNMEEbHcM 9y agoI guess regarding the public services your statement may be correct. But I wonder if anyone (any significant content provider) actually tried. The technology is available for > 10 years at least (including browsers support). I think it's an issue for most people that they need to manage multiple passwords and it sometimes turns off people from actually using the service. With client certificates you install certificate once and (given enough support from web developers) forget about passwords "forever".
- jandrese 9y agoStartcom does client certificate authentication. The hassle is that you need to install the certificate on every device you want to access the page from.
- snomad 9y agoAuth0 and Okta have tons of docs on this. Even if you don't use their services, they have much to read. 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 https://www.youtube.com/watch?v=z2iCddrJRY8 https://www.youtube.com/watch?v=z2iCddrJRY8
- drderidder 9y agoI 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. [1] https://pdos.csail.mit.edu/papers/webauth:sec10.pdf https://pdos.csail.mit.edu/papers/webauth:sec10.pdf [2] https://github.com/expressjs/express/blob/master/examples/auth/index.js https://github.com/expressjs/express/blob/master/examples/au... [3] https://expressjs.com/2x/screencasts.html https://expressjs.com/2x/screencasts.html
- cagmz 9y agoReact router supports a similar pattern to Express, although they seem to be called "protected routes" [1]. [1] https://tylermcginnis.com/react-router-protected-routes-authentication/ https://tylermcginnis.com/react-router-protected-routes-auth...
- iopuy 9y agoIsn't using the "auth" snippet more an example of rolling your own crypto? Why not use established libraries like passportjs? Super curious.
- always_good 9y agoI think that if you use passportjs because you don't understand how to implement authn yourself, then you're no any better off from a security standpoint. To me, passportjs might be useful if you need to plug into 3rd party auth APIs, but I don't really see the point. Authentication is a core part of your application and you should always know exactly how it works. If you can't store an authn secret with confidence, how can you do anything with confidence?
- Pigo 9y agoJust wanted to throw Azure API Management out there https://azure.microsoft.com/en-us/services/api-management https://azure.microsoft.com/en-us/services/api-management 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.
- tboyd47 9y agoAuthentication 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.
- jmulho 9y agoIs there any reason to favor bearer tokens over cookies?
- tboyd47 9y agoIf you use a cookie for an API, it will look like you don't know what you are doing. Also, there are extra rules around Cookies (expiration, length, etc.) that may bite you if you use them outside a browser context.
- jmulho 9y agoAh, so there are other contexts (e.g. native mobile apps) that may be sharing the API, not just browser (web) apps. I think I get it. Thanks.
- darkhorn 9y agoClient side SSL certifikate or digest authentication or basic acces authentication.
- intrasight 9y agoIn addition to token/key, for some APIs in the past I've added IP address filters.
- newscracker 9y agoUsing IP address filters would require knowing the client environment and keeping some kind of planning and communication mechanisms of changes in what. Big enterprises would have teams and a lead time of a few months to sort this out, adding more overhead and costs to the service provider (which would have to somehow be recovered or absorbed).
- Daycrawler 9y agoIt depends on the use-case. * 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=...) * 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. * 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. * 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
- simonhamp 9y agoIf 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]. 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). 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. 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). [1]: https://github.com/laravel/passport https://github.com/laravel/passport [2]: https://github.com/thephpleague/oauth2-server https://github.com/thephpleague/oauth2-server
- tptacek 9y agoThis 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: https://news.ycombinator.com/item?id=16006394 https://news.ycombinator.com/item?id=16006394 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". You do not need Amazon-style "access keys" to go with your secrets. You do not need OAuth (OAuth is for delegated authentication, 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. Do not 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.
- MattBearman 9y agoGreat answer. One thing I'd like to add is if you're using bearer tokens, make sure your API has an easy way to invalidate and regenerate them, as anyone with the bearer token has full access.
- naikrovek 9y agoHeck, I've been overthinking this. Thank you!
- hundt 9y agoDo you recommend signing requests?
- balls187 9y agoUse Auth0 eta: I don't work for them, but really no need to roll your own.
- san_at_weblegit 9y agoThere 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. 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.
- vfulco 9y agoFrom 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. TIA.
- deleted 9y ago[deleted]