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
Related
I'm looking for some clarity regarding security concerns with just JWT in our current project.
basically it is working right now like this:
User authenticates with username + password at an authentication Service
frontend gets JWT
frontend can use this JWT in the communication with the backend.
but that seems unsecure for many reasons, so we discussed this so far and had a few ideas to make it more secure:
additionally encrypt the JWT, basically make an nested JWT (JWE) and work with a blacklist on logout... but here the question remains why work with an JWT and not a stateful authentication like Shared Sessions and a Redis service
Implementing an Api-Gateway so that the frontend or User gets a Session cookie and the gateway works with JWT for backend and auth. unfortunatly i've found no implementation like this whatsoever
We just want to be kinda secure in Login/Logout AND be scaleable in the the future so that there might be X other backends.
apologies for any errors, english is not my first language and i'm happy to answer any questions regarding this.
take care.
You are right that keeping tokens on the front end has some security issues. The current best practice is to try to keep tokens out of the browser altogether. At Curity we have described one possible solution as the Token Handler pattern. It adds a bit more complexity to your system but enables you to use secure sessions on the front instead of any tokens. We have provided a few implementations of the components needed by the Token Handler, you can have a look at how to run our complete example here: https://curity.io/resources/learn/token-handler-spa-example/
As to your first idea, if you want to implement blacklisting tokens, then you're in fact implementing sessions, and you're better off with cookies and plain old HTTP sessions. JWEs protect the contents of your token but an attacker can still steal such a token and use it to call your APIs.
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.
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.
We are in the process of planning an iOS application in which users will need to be authenticated and authorized before they can interact with data provided by a Symfony2 web service.
Authorization will be implemented with ACLs, it's the authentication I'm not sure about.
From what I found in my research, there are a few ways to achieve the authentication part, but since there won't be any third parties accessing the data it sounds like basic HTTP authentication paired with a SSL certificate is the way to go. Is this correct?
Additionally, is a simple username and password secure enough, or is it better to add some sort of API key for identification?
If a key is needed and considering our users will be part of a group, should a key be bound to every user individually or to the group as a whole?
Finally, and slightly off topic, Symfony2 has FOSRestBundle, is there a defacto REST library for iOS?
For securing REST applications in symfony the FOSOAuthServerBundle is very useful. With it you can implement easy OAuth authentication for your app. OAuth is de facto standard for securing REST web services.
As https/ssl is pretty secure you can go for basic http authentication and/or the api key solution.
Wether to use a key and/or username/password is your personal choice.
If somehow requests can be catched in cleartext either one is compromised.
Keys in addition to username/password auth can have the advantage of seperating i.e. user contingents.
Basic http authentication is mostly used, therefore the chance of your client having already available methods to integrate it from his side are high.
You should always give out unique keys or username/passwords to every user in order to be able to log who did exactly what.
I'm not that much into iOS, sorry.
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.