spray security: how to protect routes? - scala

I'm trying to implement a full development with REST Spray. There is an argument that I have not yet figured out and I have not found documented: how to protect the routes for authentication / authorization? I would just use a token - based authentication through a header of the request.

At the moment Spray implements only basic security mechanisms. It comes with HTTP basic authentication implemented and some cookie support.
It makes sense not to include more specific security implementations because every project implements it differently. Although Oauth implementation would be useful in many cases. There might be projects that provide that for Spray.
Token based authentication sounds like a good general choice.

Related

How to implement token based authentication for my API?

I have a Django backend which will be served as my API endpoints. Users are identified by username and password and have some extra information and should be able to consume my same API, so I want to grant tokens for them.
How to create API keys for them to use? (Would a uuid serve a good purpose here?)
How to generate tokens for them? (I could imagine that some way like sha256(api_key + password + some_salt), where salt is some timestamp object would do the trick and also help in expiration)
How to generate a refresh token to be used for refreshing an expired token? (I have no idea here)
I took a look at Oauth 2.0 but TBH I could not figure it out completely and it is overly complicated as my API server will also be my authentication server.
I would not recommend to build your own authentication scheme, nor deploy your own cryptographic functions. Nowadays the industry standard for API authentication and authorization is OAuth 2.0, it provides all the requirements you've described in a robust but rather simple to implement solution.
If the mentioned application does not require any of the OAuth 2.0 authorization concepts, using OpenID Connect is certainly a great approach. OpenID Connect is a protocol built on top of OAuth 2.0:
It allows Clients to verify the identity of the End-User based on the
authentication performed by an Authorization Server, as well as to
obtain basic profile information about the End-User in an
interoperable and REST-like manner.
API authentication technologies are widely available in different forms, even SAML 2.0 can be implemented for such scenarios (more infrastructure is required), anyhow for what you have described, OpenID Connect certainly cover all requirements.
The easiest way to solve this is a classical Session-Cookie, Django directly offers this functionality.
If you do not want to hold state on the server side you may look into JSON Web Tokens.

OAuth2 for REST API with tightly coupled SPA as only client

I'm developing a REST API with a tightly coupled SPA as the only client of the mentioned REST API.
Let's say the SPA is available at myservice.com and api is under myservice.com/api. They're basically one service, just split at code level, and deployed at different root paths.
What I'm using for security right now is OAuth2 with ROPC (username/password) grant type.
Here comes the problem. I keep reading everywhere that ROPC is not secure and should not be used. What should I use then?
My REST API acts as an authorization server but it doesn't have any web interface itself. So any flow involving redirect doesn't really make sense. The SPA and API are so tightly coupled that for an end user they're basically one application. There's no 3rd party.
I could add simple login form to the API available at let's say myservice.com/login. But I'm struggling to see the difference that would make.
Security in this application is very important.
Here are my questions:
Is using ROPC really dangerous in this scenario?
What would be the perfect way for authentication and authorization?
Or maybe OAuth2 is completely redundant without a third party?
Technologies used:
Server: Spring Boot
Is using ROPC really dangerous in this scenario?
No, not really providing:
a) You don't store a user's password - maybe only use it to get the initial access and refresh token - although that could be tricky with an SPA.
b) Your SPA client and the resource API are owned by you, so you don't need the user to consent to specific scoped access for the SPA.
What would be the perfect way for authentication and authorization?
It depends on lots of things. Not enough info to try to answer that. OAuth2.0 (with a probably implemented Authorisation server) is a pretty good way for the example you have here.
Or maybe OAuth2 is completely redundant without a third party?
If other applications will use your API in time then OAuth2.0 is probably a good call. Otherwise you could probably use a more simple solution e.g. session cookies as all sits on same domain.
Answer to this can be taken out from OAuth 2.0 specification (RFC6749) itself. It define when ROPC grant is suitable for,
4.3. Resource Owner Password Credentials Grant
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged
application. The authorization server should take special care when
enabling this grant type and only allow it when other flows are not
viabl.
According to your explanation, you have tight coupling with SPA and backend. Also you have both authorization server and resource server built as one. This is completely acceptable implementation.
The authorization server
may be the same server as the resource server or a separate entity.
So what matter now is to clear out why you use OAuth 2.0 in your scenario.
If you are using OAuth 2.0 to obtain tokens, maintain them as defined through OAuth 2.0 specification, then this is completely oaky. But if you are doing this to follow a trend, think twice.
OAuth 2.0 implementation comes with it's own complexity. You have to maintain user identities, maintain tokens and renew them. You are building a complete authorization server by yourself. But this also have some advantages as well.
For example, same authorization server can be used to issue token for future integrations/secondary app. IMO, usage of OAuth 2.0 make integrations easy as it define a protocol for issuing tokens, renew and revoke them.! But in such integration scenario, may be you will require to use a different grant. Still, your API being authorized on token, you only need to worry about how new integration/application obtain tokens. This is better than using authenticated sessions
Going back to your questions,
Q : Is using ROPC really dangerous in this scenario?
As explained, if there is a correct trust relationship between client and authorization server, then it is fine. But be mindful about complexity comes with having a authorization server.
Q : What would be the perfect way for authentication and authorization?
OAuth 2.0 is for authorization. You obtain access token and use them to authorize against your protected APIs. From APIs you do a token validation to detect correct access levels/permissions.
If you want authenticaiton, then you must use OpenID Connect. It is a protocol extended from OAuth 2.0. And allows your application to authenticate the end user based on ID Token. You can use ROPC grant to obtain an ID token.!
Q : Or maybe OAuth2 is completely redundant without a third party?
Not necessarily. It allows you to design your APIs in a modern, standard way. Who know what future hold (again the integration scenario). Following a protocol allows that easy.
Only advice, follow specifications closely. Do not invent your own protocol/adaptation. It makes things harder to maintain.

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

Does CSRF exist in pure rest api without UI?

I don't know much about CSRF, but after reading the doc, it seems it only happens in browser. So now I have a library with rest api, but no ui. Do I need to take care of CSRF in this rest api ? Thanks
First of all, it's important to note that CSRF is an attack that can be exploited in browers.
According to Guidelines for Implementation of REST, a document issued by NSA, REST APIs are vulnerable to CSRF attacks:
F. Cross Site Request Forgery:
Cross site request forgery (CSRF) attacks attempt to force an authenticated user to
execute functionality without their knowledge. [...]
It is important to note that CSRF attacks execute functionality, but are unable to
interact with the response from the targeted server. [...]
REST is stateless at its core and thus inherently vulnerable to CSRF attacks. [...]
Two approaches are suggested to ensure protection. Summarizing them below:
Custom HTTP header
The first method involves checking the presence of a custom header (agreed-upon between the server and a client – e.g. X-CSRF or X-Requested-By) in all state-changing requests coming from the client. The value of the header does not really matter. It works, because the browser would not send custom headers unless the web page makes a request using XMLHttpRequest, which only allows requests to the same site.
This method is currently used by Jersey, the JAX-RS reference implementation for REST web services in Java.
And it's also mentioned in Robust Defenses for Cross-Site Request Forgery from Stanford University.
CSRF tokens
The second method involves protecting REST endpoints against CSRF attacks by establishing session state. This approach violates REST principles and involves the use of a CSRF token that is generated for each action, then associated with the user session and submitted with each important website action.
This essentially forces a sequential ordering of actions on the application.

What is the best way to perform OAuth2 authentication using akka-http?

Akka HTTP and Spray provide an authenticateOAuth2 directive, but their documentation states that
This directive does not implement the complete OAuth2 protocol, but instead enables implementing it, by extracting the needed token from the HTTP headers.
I also cannot find any libraries that implement OAuth2 for Akka HTTP or Spray. Is there something I'm missing, or is this simply the state of these libraries right now?
I think the biggest problem is that OAuth2 itself doesn't really tell you how the implementation details look like.
To quote the RFC:
The token may denote an identifier used to retrieve the authorization
information or may self-contain the authorization information in a
verifiable manner (i.e., a token string consisting of some data and a
signature). Additional authentication credentials, which are beyond
the scope of this specification, may be required in order for the
client to use a token.
Access tokens can have different formats, structures, and methods of
utilization (e.g., cryptographic properties) based on the resource
server security requirements. Access token attributes and the
methods used to access protected resources are beyond the scope of
this specification and are defined by companion specifications such
as [RFC6750].
For example you could use JWT to validate a request or you could use the token only as an identifier and ask a service whether the token is allowed for that resource.
Depending on your OAuth2 provider the implementation can vary, so my guess is the framework can only provide you the common thing (extract the token for you) or it would have to implement all possible OAuth2 implementations, which seems not feasible at this point.
I personally have used pauldijou/jwt-scala in the past, which you might want to take a look at.