How to make a stateless architecture design so that if a user(A) is loggedIn and the Json web token is generated by Server(X1) and returned to user-A. And again user-A sends the request to server and the purpose is served by Server(X2) without making the user re-authenticate.
So that the architecture is highly scalable horizontally.
Normally you would have a service that would do all the work related to authentication. Basically that means that X1 and X2 will call that service to authenticate user or verify existing authentication. The only thing that should be performed on X1 and X2 is validation of the token. Token could be valid, valid and expired or not valid. In case of it is valid, you just perform necessary work, regardless of particular server. If it is not valid, you reject request and if it is expired, you redirect user to reauthentication.
But if you are asking about particular environment-specific details and your problem is that X2 does not have some specific cryptography keys that X1 has or something like this, then you forgot to mention what frameworks you are using to obtain JWT.
There are few requirements to make it work:
As mentioned above, X1 and X2 would use internal service A for credential verification.
there will be salts in user/api client records bound to the A's datasource.
X1 and X2 encryption keys should be shared, and they should use same structure of JWT's sub object. iss object should also be checked (normally bound to the api client to which user requesting authentication is bound). The logic of verefication should be shared between X1 and X2.
The token have data forged into it - and if it provided by same service A, and then hashed, and structured and then checked by X1 and X2 in same way.
Related
I am starting to work on an authentication system for an angular 2 Single Page Application using django-rest framework as back-end. I'd also like to have some kind of "remember me" functionality that is going to keep users logged in for a certain amount of time.
From what I have read so far, it seems that the best authentication method for this kind of Angular 2 SPA/REST API is using jwt (json web token). For jwt authentication, I looked at the django-rest-framework-jwt (https://github.com/GetBlimp/django-rest-framework-jwt).
The problem that I see is that the token needs to have a short life span (few minutes to a few hours...) in order to minimize security issues if the token get stolen. The token now needs to be refreshed frequently to avoid the user from being disconnected while using the application. In this case, a "remember me" functionality is posing problem since the token have a short life span.
I thought about a solution involving a second token that would serve as a refresh token. It would be opaque, have a longer life span and would contain information specific to the user (ip address or something like that) so that if it get stolen, the information specific to the user being different would render this refresh token invalid.
So here are my questions:
1- I would like to know if they are existing solutions addressing this problem. As any security/authentication issues, I prefer to rely on well tested solutions to avoid getting my API compromised.
2- Would the refresh token based on specific user infos be a good idea?
3- Any other ideas how I could implement what I want?
For your situation, you really need a way to store issued tokens.
I always use an OAuth2.0 server setup that manages the auth and returns tokens the OAuth setup uses a database to manage everything so it's easy to manage and revoke tokens.
The database schema would be like this http://imgur.com/a/oRbP2 the problem with using just JWT without any management over the issued tokens with long expiration you have that security issue of not being able to revoke easily.
I would advise against including any such thing as a password in the JWT and requiring them to change it what if they use that password everywhere, then they would have to change that everywhere.
Updated from comments
Sessions Authentication use session_id which most the time is stored in a cookie and this is attached to every outgoing request. It is stateful. It is nothing more than a unique identifier that associates a user account that the server has in memory/database. For example, this can course problems when running multiple servers/instances when scaling your infrastructure.
Token Authentication no session is persisted on the server so this means it is stateless. It normally uses the header Authorization: Bearer REPLACE-WITH-TOKEN . This means that this token can be passed to multiple different servers/instances because the authentication is not limited to the server that you initiated the authentication on. This helps with scaling your infrastructure. Tokens can also be passed to other clients.
RESTful API's are stateless so there must not be a session state stored on the server. Instead, it must the handled entirely by the client so that's why token authentication is used.
I had the exact problem when trying to use JWT with an application that needed a lot more than JWT was designed for. OAuth2.0 has a lot more options that I believe are necessary to meet your requirement in the safest manner possible and even features that you may find very useful in the future as your Application may grow and need more features with regards authentication.
Actors
Front-end (fat client-side Javascript application) which has Facebook access token.
Back-end which 100% relies on OAuth2 authentication. All requests need to be authenticated via Facebook.
To mutate user data on the back-end, I require user to be logged in via Facebook. Ideally, with every request, I would know the Facebook's user ID (the one that graph.facebook.com/me provides).
Question 1
Is there a way to get whatever graph.facebook.com/me returns to be signed, so I don't have to call Facebook to verify it with every request, nor store state in my backend?
Situation 2
If the answer to Question 1 is "no", it means I have to invent my own. I am thinking of the following:
The user sends the access token to the backend.
Backend calls token debug API, signs the result with my key, and sends back to the client.
Every time client does a request, it includes the previously-included blob.
Upon every incoming request to the backend, it verifies the signature, which, if matches, means that the request wasn't tampered with and I can trust it is coming from the previously-verified token.
Question 2
If I employ this scheme (sign the answer from Facebook and send it upon every request), how can I safely implement this? Are there resources I could read up which would tell me:
Things to be cautious about with this scheme.
Which signature algorithm to use, how to safely verify the signatures.
How to avoid common types of attacks and stupid mistakes.
Thanks!
It's not really clear what exactly you want to do, but I think you should have a look at the docs at
https://developers.facebook.com/docs/graph-api/securing-requests
Quote:
Graph API calls can be made from clients or from your server on behalf of clients. Calls from a server can be better secured by adding a parameter called appsecret_proof.
Access tokens are portable. It's possible to take an access token generated on a client by Facebook's SDK, send it to a server and then make calls from that server on behalf of the person. An access token can also be stolen by malicious software on a person's computer or a man in the middle attack. Then that access token can be used from an entirely different system that's not the client and not your server, generating spam or stealing data.
You can prevent this by adding the appsecret_proof parameter to every API call from a server and enabling the setting to require proof on all calls. This prevents bad guys from making API calls with your access tokens from their servers. If you're using the official PHP SDK, the appsecret_proof parameter is automatically added.
I have created a web service API and it's architecture is such that the server requires a client to sign the request along with a secret key assigned to it (signature is always different between multiple requests).
Server matches the client's signature with its own computed signature. If they are a match then the server returns the response.
I am wondering if a client should check the response coming back from the server to see if it's from the same application to which the request was made.
Is any kind of attack possible between HTTP request and HTTP response?
Do we need a security signature for the web service response?
It depends. There are a few types of web service APIs out there. Some need strict security other might not. You could have a few types of APIs:
(1) completely opened API. Say you have a blog where you post about writing RESTful services and clients. You host a complete working REST service based on one of your posts so that people give it a spin. You don't care who calls your service, the service returns some dummy data etc. It's just a demo, a toy, no security here, no request signing, nada. It's just plain HTTP calls.
(2) service with an API key. Say you have a web service and you want to know who calls it. This kind of service needs a pre-registration and each client who wants to call your service needs to register and obtain a key first. Do note that the registration is not about authentication or authorization, you just want to know who's using your API (e.g. what business sector they operate in, how many clients they have, why are they using your API for etc) so that you later make some analysis of your own and take some (marketing maybe) decisions of some sort later on based on the data you get back.
There is nothing secret about this API key. It's just an UUID of some sort, the most basic way of differentiating between calls. This again involves only plain HTTP calls with the key as an additional request parameter.
(3) service with an API key and a secret key. This is similar to number (2) but you need to absolutely make sure that the calls are coming from the client that presents some API key. You need this because you probably want to bill the client for how much they have used your service. You want to make sure the calls actually come from that client and not someone ill intentioned that maybe wants to overcharge the client's bill.
So the client uses it's key for identification and a signature of the request with the secret key to actually vouch for it's identity. This again can be plain HTTP calls with the key and signature as additional request parameters.
(4) data "tampered-safe" web services. For numbers (1), (2) and (3) above I haven't considered any message security issues because most APIs don't need it. What's exchanged isn't confidential and not all that important to protect. But sometimes although the data isn't confidential you need to make sure it wasn't tampered with during transit.
Say you are the owner of a shop that builds some product and you want to advertise your product on some partner web sites. You expose a service with the product details and your partners just use this data to display your product details on their sites. Everybody knows what products you are building so you don't need to hide that, but you are paranoid about your competition trying to ruin you so you want to avoid them intercepting the
request and multiplying by 10 all your prices in the responses of your result just to scare potential buyers away.
Number (3) above, although uses the signing part as a way to prove the identity of the caller, also assures the request was not tampered with (server will reject the request if the signature does not match). So if you need to assure an original response you can also sign the response.
For this, the service can provide the client with an API key and two secret keys. One secret key is used by the client to sign their requests while the second secret key is used by the client to verify the signature of the response (using an unique secret key for the server isn't all that safe so the server emits a server secret key specific to each client).
But this has a weak point: you would need to trust your partners that they will indeed validate the response signature before displaying the information on the site and not just bluntly display it. Paranoid as you are you want to protect against this and for this you need HTTPS.
As #SilverlightFox mentioned this proves the validity of the response. The data was not tempered with because it's encrypted. The client does not need to have an extra step to verify the response signature because that verification is already done at a lower (transport) level.
(5) secure services. And now we reach the last type of service where the data is actually confidential. HTTPS is a must for these services. HTTPS ensures the data remains confidential, that it isn't tempered in transit, identifies the server and can also identity the client if client side certificates are used.
So, in conclusion, it depends on what type of service you have.
Make the request over HTTPS to ensure the validity of the response.
This will ensure your data is not vulnerable to a MITM attack. Rolling your own untested encryption/hashing methods is a sure way to open up your application to attack, so you should use TLS/SSL which means that you should connect to your web service API over HTTPS. TLS is the proven and secure way to ensure the response is coming from the application that the request was made to.
I am trying to get my head around secure authentication. Here is the safest method I can think of.
Send an encrypted username + SHA-256ed password to the server and wait for a yes / no response. But the problem with this is a hacker could hack the response to be a yes when it should be a no, giving them unauthorized access to that account.
I am thinking you could work around it by encrypting the response and then, instead of storing it in a Boolean, calling a function that changes state of the application. But because the hacker can make the server say no and yes from his control he can find out the encryption key and still change the result.
That seems kind of insecure, right? What's stopping the hacker from isolating the function that logs you in or the Boolean?
Or am I just being naive and everything really is that insecure? I suppose the only real safe way to do it is to store if the user passed authentication on the authorization server and do a quick Boolean check to see if the user is logged in before every server action.
As Banthar said in his comment, the authorization check should always be performed on the server.
The standard way of implementing this kind of thing is by using a token: the client sends a username and password to the server. If the credentials given by the client succeed authentication, then the server generates a security token, stores it somewhere for later chacks and also sends the token back to the client. For every following request to the server, the client should send the token along with the request parameters, allowing the server to check if the token is valid. The server executes the request only if it can verify that the token is legitimate and authorized, any doubt should result in the server revoking the token.
This method is quite similar to the one you describe in the last part of your post.
The token generated by the server should be a value which cannot be forged: it cannot be a simple integer value incremented for each generated token, since a hacker could easily predict a valid value. It cannot be built using only information available to the client, for the same reason (although it would require more work for a hacker, he could ultimately forge a valid token). Also, on the server, the token should be attached with information allowing the server to easily and uniquely verify the token: a small variation in the connection information should result in the token being revoked. Token values should never be reused (with a token of finite length, there will still be a chance that a token value is reused, so figure out a length which is a good compromise between security and practicability). Finally, the token for a valid session should be regularly updated during the session, to prevent a malicious user steeling the session.
There are many ways to implement this, but the details depend on the security level you are trying to achieve. Using some sort of secret key to generate the token on the server is generally a bad idea, since there is always a chance that the key is leaked. The time when the token is generated may also be predictable. Pseudo-random number generators available to any programming languages have to be properly seeded so that the sequence of numbers cannot be predicted.
Finally, note that no authentication logic ever is completely safe: building more safety in your logic only makes the job harder to a hacker. Think about the incentive for a hacker to break into your system, and devise your logic so that the amount of work for breaking into the system is not worth the resource cost (time, money, specialty hardware...). And do never forget that obscurity does not mean security: let people review your process and comment on it, they may well think about some flaw that you had not seen.
I want to develop a REST API. REST guidelines specify that the state mustn't be stored on the server side.
But the REST methods I want to implement imply user connection management. In order to respect the statelessness, do I need to give the user credentials in each REST method request ? I find that quite inefficient... Isn't there an other more effective way ??
Statelessness is one of the main constrains of a REST architecture, as can be read in the original publication:
5.1.3 Stateless
We next add a constraint to the client-server interaction: communication must be stateless in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3), such that 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. Session state is therefore kept entirely on the client.
So for the credentials you mentioned, you should provide them in each call separately (i.e. Basic Auth + SSL). Of course, this is were "the real world" comes in, and applications start to differ. You might also use OAuth, fixed tokens, etc. but remember that you're then weakening the "RESTfulness" of your API.
Authenticating on every request does not necessarily require passing the username and password on every request. Some systems will take the user name and password, verify it and then create some kind of security token that can be passed on every request instead.
The idea is that the token should be quicker to authenticate than doing a full username password check. Obviously depending on how sophisticated the token generation and verification is you may be opening other security holes but you have to decide how critical that is.