Maintaing credentials in a stateless RESTful web service between calls - rest

I'm writing a rest web service which authenticates and authorizes against an LDAP server. The problem is that calls to the LDAP server are somewhat expensive due to the way everything is configured. Consequently I am trying to minimize the number of calls I have to make to it.
In a normal stateless design, each call to the rest backend just be authenticated and authorized. I'm trying to figure if/how I can accomplish this without having to contact the LDAP server each time.
I've been toying with the idea of using a custom token upon initial login and require the client to return the token at each request, but short of encrypting the token or signing it, I can't think of a secure mechanism that would allow me to do this. But to encrypt a new token at each response, and decrypt at each request will put extra overhead that I would gladly avoid as well.
Caching the LDAP response is a concept as well, but then that opens to a whole bunch of other concerns as well (cache life, clustering, etc).
Is there a mechanism that I can use to accomplish this?

Related

MIcroservice: Best practise for Authentication

I am looking into using microservice for my application. However the application involves authentication. E.g. there is a service for user to upload their images if they are authenticated. There is also a service for them to write reviews if they are authenticated.
How should i design the microservice to ensure that the user just need to authenticate once to access different services. Should i have a API gateway layer that does the authentication and make this API gateway talk to the different services?
You can do authentication at the gateway layer, if authentication is all you need. If you are interested in authorization, you may have to pass the tokens forward for application to consider it. Also you can do that, if you have trust on other services behind the gateways. That is service 1 is free to call service 2 without authentication.
Also you loose bit of information about the principal, you can however write it back on the request in the gateway while forwarding.
Also another point to consider is JWT, they are lightweight and more importantly could be validated without calling auth server explicitly and it saves you some time specially in microservices. So even if you have to do auth at every service layer you are doing it at minimal cost, some nanoseconds. You can explore that as well.
However final call is based on how strong your security needs are compared to rest. based on that you can take a call. Auth stripping at api gateway saves you code duplication but is less secure as other services can do as they wish.
Same goes for token, you can authenticate without explicit call to auth server but then tokens are valid for some min time and bearer is free to do as they wish once they got the tokens, you cannon invalidate it.
While Anunay's answer is one the most famous solutions, there is another solution I would like to point out. You could use some distributed session management systems to persist sessions on RAM or DISK. As an example, we have authentication module that creates a token and persists it in Redis. While Redis itself can be distributed and it can persist less used data on disk, then it will be a good choice for all microservices to check client tokens with redis.
With this method, there is nothing to do with API gateway. The gateway just passes tokens to microservices. So even in case you are thinking about different authenitcation methods on different services, it will be a good solution. (Although I cant think of a reason for that need right now but I have heard of it)
Inside a session, you can store user Roles and Permissions. That's how you can strict users access to some API's. And for your private API's, you could generate a token with role ADMIN. Then each microservice can call other one with that token so your API's will be safe.
Also you could rapidly invalidate any sessions and store anything you want in those sessions. In our system, spring framework generates a X-AUTH-TOKEN that can be set in headers. The token is pointing to a session key in redis. This works with Cookies too. (and if I'm not wrong, you could even use this method with oAuth and JWT)
In a clean architecture you can create a security module that uses this validation method over API's and add it to every microservice that you want to protect.
There are other options when it comes to session persisting too. Database, LDAP, Redis, Hazelcast ... the choice depends on your need.

Security Issues with RESTful Authentication & Session Management

I'm trying to implement authentication and session management for a microservice. In order to do the process RESTfully, I understand that I'll need to use some kind of token-based authentication to avoid tracking client session data on the server. The following quote from this answer on the Information Security Stack Exchange nicely sums up my understanding of the implementation:
In Token-based Authentication no session is persisted server-side (stateless). The initial steps are the same. Credentials are exchanged against a token which is then attached to every subsequent request (It can also be stored in a cookie). However for the purpose of decreasing memory usage, easy scale-ability and total flexibility a string with all the necessary information is issued (the token) which is checked after each request made by the client to the server.
From this, I understand how stateless session maintenance is advantageous for scalability, and flexibility as explained. But it seems to me that this leaves the application exposed to some serious problems:
If a hacker somehow intercepts the credential exchange HTTP REST call, they could execute replay attacks on the server get all the information they want.
In fact, since the session token is stored on the client side, couldn't a hacker just retrieve the requisite information from LocalStorage/SessionStorage by debugging the app? Or by monitoring the incoming and outgoing HTTP calls using dev tools? If they get the required token information (even encrypted token information), they could simply start faking REST calls to the server from another window and get all the data they want!
Finally, even if you do give the client a session token, wouldn't the server still have to authenticate that token? In effect, the server would have to maintain session tokens to user mappings...but doesn't that defeat the purpose of a stateless REST-based architecture?
Maybe I am seeing these problems because there is a gap in my understanding. If that's the case, I'd like some clarity of the basic concepts. If not, I'd like to know if there are any techniques to address these specific problems.

Symfony - Most secure way to authenticate using REST?

I'm trying to build a proof of concept using Angular 5 and Symfony 4. I need the backend to be decoupled from the frontend so that I can focus on using JS entirely for the frontend and to be able to escalate to apps and other types of clients.
For this reason I'm building a RESTful API on Symfony. I've managed to send credentials from the front to the back... and that's pretty much what I've managed to do because I don't know how to proceed next.
Symfony should take the login data, somehow call a service to validate, and respond properly to the frontend. What is the most secure way of doing this? I've read a lot about JWT and how it's unfitting for this use case, and apparently OAuth2 is good only for authorization and not authentication unless you use OpenId Connect. I've read that the simplest approach is to create a session ID + a CSRF token and store it in a cookie (I don't care if this breaks statelessness, being certain that the system is secure is more important). I think the latter can be done with a bundle transparently but I don't know how to do the former.
In fact I'm entirely lost. I don't know where to begin, I've been stuck for days and the task seems just too overwhelming. I was even suggested to use Laravel instead, but I don't even know where to get started and this is legit the first time I try to implement a REST API, so it's quite daunting.
What am I supposed to do here?
EDIT: Here are some of the reasons why I'm schewing JWT for authentication.
Wanting to use JWT instead of OpenID Connect is like wanting to use a SAML assertion without the SAML protocol.1
(This one could lead me to use OpenID Connect as my solution)
Stateless JWT tokens cannot be invalidated or updated, and will introduce either size issues or security issues depending on where you store them. Stateful JWT tokens are functionally the same as session cookies, but without the battle-tested and well-reviewed implementations or client support.2
Unfortunately, an attacker can abuse this. If a server is expecting a token signed with RSA, but actually receives a token signed with HMAC, it will think the public key is actually an HMAC secret key.3
This isn't just an implementation bug, this is the result of a failed standard that shouldn't be relied on for security. If you adhere to the standard, you must process and "understand" the header. You are explicitly forbidden, by the standard, to just disregard the header that an attacker provides.4
The linked websites have more information as of why JWT is not secure.
Now I am implementing a similar task, only on the frontend Vue.js. On the backend I use Symphony 4 + API Platform. At the moment, I implement secure access to the API through JWT Authentication, this method is recommended.
Links for your topic:
https://github.com/lexik/LexikJWTAuthenticationBundle
https://gist.github.com/lologhi/7b6e475a2c03df48bcdd
https://github.com/knpuniversity/oauth2-client-bundle
If you want fast setup, then use FOSUserBundle Integration, but API Platform not recomendated his method.
Or use this method at Symfony4: -
https://symfony.com/doc/current/security/api_key_authentication.html
https://symfony.com/doc/current/security/guard_authentication.html

Authentication with Akka-Http

We're developing an iOS app, where the user needs to authenticate using email+password (or mobile number). Our backend is made of a couple of microservices using Akka-Http. It needs to be fast, scalable, concurrent, and the authentication+authorization should work across our multiple services.
I'm trying to figure out which authentication method to use.
Akka-HTTP currently offers Basic Auth and a partial implementation of OAuth2.
So at first we were considering Basic authentication (too simple and not enough functionality), Oauth1 (too complex), so we moved towards OAuth-2.0 because it is sort of a standard.
Then we considered AWS Cognito because it combines Oauth-2.0 and OpenID Connect which gives the authentication mechanism that OAuth2 lacks.
http://www.thread-safe.com/2012/01/problem-with-oauth-for-authentication.html
Then we realised that OAuth2 is just for authentication using a third party - when in fact we don't need a third party authentication provider - maybe we need to do it ourselves, and using Cognito is an overkill that would create extra api calls outside our microservices...
So I read a little bit about creating our own custom auth provider, using WSSE specs:
http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html
And I also found this example using Spray, but I'm sure it's not that different from Akka-Http:
http://danielasfregola.com/2015/06/29/how-to-create-a-spray-custom-authenticator/
It looks too simplified and doesn't have token expiration...
So my question is, am I missing something? What method should I chose and where can I find examples for it?
I feel like I'm going in circles, we're gonna have to write our own custom authentication provider from scratch, which kinda doesn't make sense. After all almost everybody needs authentication and it should be a standard.
I've recently been using SoftwareMill's akka-http-session library and found it simple and easy to integrate. It has support for case class based sessions, JWTs, refresh tokens with pluggable storage, using headers and CSRF tokens as well as some nice simple directives for use in routes.
My solution for user registration has been to use Keycloak, an open source server which can handle user registration and do OIDC, OAuth2 style login. It reduces the amount of code I have to write, and the code is more secure than if it rolled it myself.
I then write my application as Scala backend that's purely a JSON API and a React/Javascript rich frontend in front of that API. In this configuration the authentication is handled completely on the front-end (and can be done in your iOS client). The front-end app redirects the user to Keycloak and when the user comes back they have a signed "JWT" token you can keep in a cookie.
That JWT token is attached to all API calls made the JSON backend as an Authorization Bearer token HTTP header. The token itself contains the users email address and is cryptographically signed by the Keycloak server.
The backend gets the JWT token in the HTTP header, extracts the email address and verifies the token is cryptographically signed by the keycloak server.
It's performing a certificate check on the keycloak server and can cache it's certificate. So it doesn't need to have roundtrips like OAuth, or any upstream calls to make.
This gives us simple, low-chance-of-failure, high speed authorisation in our JSON backend API and means we aren't putting secrets in the iOS client, or rolling too much of our own code.

How do I implement authentication the restful way?

I'm building a picture diary on web application google app engine using python. Users can sign up and post pictures to their diary.
Also, I'm trying to conform as much as I can to the REST architecture of doing things.
The authentication scheme is based like this for the web application:
1. Post username/password from the frontend
2. Backend sets up a cookie if authentication is successful
3. The rest of the AJAX calls made are authenticated using this cookie.
Is there any way to conform to REST without using cookies ?
Now, I'm also building an android application where users can sign in and post/view their picture diary. I need to expose the data from web application's datastore so I'll be building a webservice to fetch data from the datastore.
The authentication scheme for the android client:
OPTION a
1. Post username/password over https to the web service
2. Web service returns a unique authorization token (store the token in the username/pwd table on the datastore)
3. Request subsequent services by adding this token to the Request Header of the request
4. Server maps the token to the username/pwd table and returns data if token is found
5. Authorization token expires after a certain period of time
OPTION b
1. Set up a secret key on the client and server side
2. Use "username:hash of password and secret key" in the authorization header of every request
3. server generates the password by extracting the password from the hash value using the same hash algorithm ; if successful returns data
btw, I didn't wanna use basic authorization because of its security vulnerabilities.
Which is better ?
Are there other significantly better ways to accomplish what I'm trying to do ? Security is quite a concern for me btw.
I'd appreciate if anyone has any insight into this issue. thanks.
I've been doing some research myself as to what would be the best solution. I think the 2-legged oauth might work in my case as Leonm suggested.
In this case the server has to provide the client with a consumer key/secret which in my case is hardcoded in the app.
The steps now would be:
1. Generate a signature using the oauth_parameters(consumer_key, signature_method, timestamp), request url, request parameters, and the SECRET.
2. Include the signature, oauth parameters when making a request.
3. Server verifies the request by generating the signature again except in this case it uses the SECRET that corresponds to the key
I think this way I am pretty much confirming to the REST principles. The server is statless as I far I understand now.
What are the pros/cons on doing things this way?
If "security is a concern" then I would say that you'd be a lot better off using open standards and a library to achieve what you want. The main reason for this is that if you do it yourself, you're very likely to forget something; these standards have had a lot of eyes looking at them, looking for holes.
Your options include (in increasing level of complexity)
Basic authentication and HTTPS
Everything is encrypted, which makes it impossible to compress or look into, it increases the overhead somewhat, using more horsepower on the server, and more perhaps battery power on the client. Simple to implement, since it's well supported by libraries.
Digest authentication
Unencrypted messages pass the wire, but the authentication is securely managed in the Authorization headers. See the wikipedia entry for more information.
OAuth
See how Google is providing OAuth for installed applications. I believe it isn't what you're looking for, since you're not asking to share data between applications, just authenticating users.
Roll your own
If you want to roll your own, I suggest looking at e.g. how Google's (now deprecated ?) ClientLogin used to work.
Clients would GET a protected resource, and get a 401 with instructions to perform a GoogleLogin authentication, including a URI for where to perform the login itself
Clients (knowing how to do this) POST a request in a specific manner to that URI
The server responds with a specific response including a (long) token
The client can now perform GET requests to the protected resource with that token.
Statelessness
You cite REST, which dictates that requests should not specifically depend on prior interaction: "... each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server." (fielding) This means that a server shouldn't store conversational context (like an authentication token) in a table.
One way of fixing this is by using any of the token based approaches (where the server tells the client about a token it should use for future requests) where the token is not a random number, but a message to the server itself. To protect yourself from client tampering, it can be signed, and if you're afraid of clients looking at it, you can encrypt it.
Edit: Although I'm not certain, it seems unlikely that Google has a table of all authentication tokens ever issued; The length of their tokens suggests that the token is some encrypted message proving that whoever holds this token actually provided real credentials in some realm at some time.
OAuth does exactly what you want to do in a standard way.
You could use a combination of HTTPS and HTTP Basic Auth. Both are existing standards and should be secure enough when used together.