5 ms·
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
by barrystaes 9y ago
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.
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 ?
- intellent 9y agoIf you use it for authorization only, it doesn’t.
- kbutler 9y agoYes, it does. If you want to be completely stateless, you need to send the authorization info on each request, probably as basic auth headers. This is actually simpler than implementing the Bearer token, for both client and server, but requires that the client retain the non-expiring username and password, rather than retaining the expiring, session-specific Bearer token.
- matwood 9y ago> but requires that the client retain the non-expiring username and password IMO, this makes this simpler solution a non-starter. It becomes way too easy to leak credentials.
- azernik 9y agoThe auth framework I use avoids this problem but remains stateless by encrypting/signing the tuple (user ID, session expiration time, maybe other stuff) in a cookie. Essentially it's using the browser as an encrypted one-row database to store the info that would normally be in a sessions table.
- matwood 9y agoThis can work, but you want to keep what you send with every request very small. It's also hard to do a mass expiration or revoke a single session. If you have the tokens on the server you can run a query and easily do both. Checking signatures and decrypting on every request can also be a performance issue.
- 9y ago
- matwood 9y agoI have found the above (sans JWT) to be the simplest, secure method. Do everything over HTTPS, use basic auth or post for the user/pass and return an expiring token, use that token as a Bearer token for all subsequent requests.
- oozzee 9y agoI’m mostley a FE person at the moment so forgive me for my ignorance but how does the server use the token passed to the client to do auth? Does it keep a copy somewhere and check against it on every request?
- pc86 9y ago> Does it keep a copy somewhere and check against it on every request? Yes. The last time I did this we checked the X-Token header on every request, if it didn't exist or there were multiple we replied 401. If only one was there we checked a DB table of active tokens, if it wasn't there or had expired we replied 401. If it was there but wasn't associated with a role that had access to the requested resource, we replied 403. If it was not expired and had access we continued with the request. As soon as you get away from "check authentication on every request" your attack vectors increase. As a bad actor, I no longer need to bypass your authentication, I just need to bypass whatever system you have in place to decide whether or not to authenticate me. That's generally going to be easier.
- mring33621 9y agoI was planning to use custom headers over HTTPS for a similar thing, but then I read that some firewalls will strip custom headers, even over HTTPS. Can anyone with experience comment? Thanks.
- matwood 9y agoJust use a Bearer token in the Authorization header from the OAuth spec: https://tools.ietf.org/html/rfc6750#section-2.1 https://tools.ietf.org/html/rfc6750#section-2.1
- pivotal 9y agoWhat is your reasoning for not using query params for the login request? I know it's probably more RESTful to use POST, but otherwise if you're using HTTPS for everything, query params are just as encrypted as the POST body. Or is there another reason?
- sk5t 9y agoFor one, the query string is much more likely to be logged, compared to the entity body. Think: httpd access logs, browser history, misconfigured caches / correctly configured caches subject to inappropriate cache directives, etc.
- dmytrish 9y agoGET requests just do not make sense for actions: they are cacheable and replayable. An http client/a proxy/something on the backend can cache it and avoid going to the actual logic. Also, mixing credentials into URL does not feel like a good separation of concerns, e.g. URLs are often logged and analyzed in separate logging/monitoring/analytic tools, so there is a bigger risk to have credentials leaked over some side-channel.
- marpstar 9y agoQuery params in the URL are encrypted for transmission, but not elsewhere: http://blog.httpwatch.com/2009/02/20/how-secure-are-query-strings-over-https/ http://blog.httpwatch.com/2009/02/20/how-secure-are-query-st...
- crescentfresh 9y agoIs this "go code this yourself" advice, or just what to look for from pre-existing tools? In my world there are middlewares that accomplish exactly this, it never occurred to me to code this myself, lest I screw it up.
- matwood 9y agoSure, the auth middlewares out there like Passport for js or Spring security on the java side do most of the work. You generally still have to code the very last bits of checking if the user/pass is good, generating the token, and checking if the token is good. There may be ones out there that do everything, but they are typically not quite as flexible as I'd like (lets store the token in Redis instead of an RDMS for example).