I'm developing an hybrid mobile app using HTML/CSS/JS, I'm going over security with login information, the system I have set up creates an hash after a user logs in, this hash has a time limit and is set via localStorage
Essentially, I would have something like this is localstorage:
hash
5f4a09cfec2a6d8f306eecb3844e33e9
hash_expiration
1373012945
password
*encryted user password*
This hash is sent to my server for validation in the header of all my AJAX requests (accompanied by the user id for database matching)
I'm mostly opening this topic to discuss best practices on how to deal with recreating hash keys, I need to figure out a way to refresh a users hash key.
Considering my experience with AJAX and JS is still rather limited, I thought about using the AJAX setup to check for a new hash, like so:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
var time = new Date().getTime(); //unix time
var hash_time = localStorage.getItem("hash_expiration");
if(time>hash_time){
//ajax request to fetch new hash, async: false to make sure this completes before continuing with other AJAX calls
}
}
});
I would send the user id and his encrypted password to verify him and return a new hash.
Should I be sending AJAX requests in the ajaxSetup's beforeSend? How would this conflict with other beforeSends across my application?
Basicallly on the clients side you shouldnt have anything except hash. On the server side this hash must be associated with user it belongs to, expire time and anything else you need.
Send this hash with each request, and on server side validate it. When it expires you have to send (server) appropriate headers like 401 - Unauthorized. Client have to understand that response and try to exchange hash to new one. And finally when client gets new valid hash it can resume sending requests.
... and you shouldnt check expire time at client, this job for server.
thanks.
Related
I am a web-dev noob but I'll try my best to be clear about the problem, explain my approach, and what I've tried. I also include imports in-case those are causing the problem but I'm pretty sure I've isolated it to what I describe.
I am trying to use Flask-session to keep information private but some values are "lost". This code is trimmed down significantly for simplicity. The user lands on /send and we render the loading template. loading.js does fetch() on /deploy while it runs an animation, then() we go to /results when the deploy function is done.
loading.js
function navigate() {
window.location.href = 'results'; // redirect to results page when done!
}
// deploy the contract while the loading screen goes then navigate to results page
const data = fetch('deploy').then(navigate);
loopThroughMessages(messages);
main.py
from flask_session import Session
app = Flask(__name__,
static_folder='static',
template_folder='templates')
# for the session, i.e passing values
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
app.config.from_object(__name__)
Session(app)
#app.route('/send')
def main():
# take url parameters and do stuff with them
return render_template('loading.html')
#app.route("/deploy")
def deploy_contract():
session['contract_address'] = some_fnc()
# fetch() requires that this function return a json
return {}
#app.route("/results")
def serve_results_page():
# pull saved values from the session
data = {'contract_key' : session['contract_address']
} # calling session here causes the error, the contract_address key doesn't exist
return render_template('results.html', data=data)
So contract_address is saved to the session but when we get to /results, the server has no way to associate that session with the client.
We want to keep our contract_address private so sending it to loading.js is not an option. I'm guessing that since http is stateless, I need to pass a cookie to and from my js and python files but I'm a bit lost on how to implement it. Are cookies unnecessary (because the server doesn't actually need to receive any data from my js files)? Should I be using redirects or something besides fetch()?
Hacky fixes, different approaches, and resources are all welcome. I feel like I'm close, like there's a simple way to use cookies that I'm overlooking.
I will be continuing to research and detail the approaches I'm considering
Edit1: Looking at Flask's should_set_cookie method
Try fetch with credentials:'include' to cause browsers to send a request with credentials included on the server side calls:
fetch('deploy', {
method: 'GET',
credentials: 'include'
}).then(navigate);
Using this, you will access session['contract_address'] in the results route.
The flask-session sets a cookie with a key session in your browser, fetch with credentials:'include' includes this cookie value in the network call.
Session in flask is implemented as a client session, saving all session content as client cookies. The flask-session extension provides some other server storage for session. E.g. app.config["SESSION_TYPE"] = "filesystem" save session content in a file on the server.
But both of the approaches still depends on Cookie. The server-side session storage need to get a session_id from client Cookie.
You need to enable cookie sending on Fetch API.
fetch, sending cookies
I have a node.js REST API and I want to restrict POST/PUT/DELETE calls to a predefined list of "sources" (web applications which I do not own the code).
The only way I see to achieve this is to put a token on the client-side (something like Google Analytics in JS files) but I have no idea how to secure this since the token will be accessible in the static files.
What strategy should I use ? JWT and OAuth2 seem not indicated since it requires first user authentication, but what I want to authenticate is not user but webapps.
Your question is slightly unclear. You could mean either (a) that you want to strongly encourage the user to use the app and prevent other code from maliciously making your user perform an action, or (b) that you want to absolutely prevent your user from using other code to access your server.
The first option is possible, and indeed a very good idea. The second is impossible, based on the way the Internet works.
First, the impossibility. Essentially, client-side code is there to make life easier for your client. The real work will always be done on the server side -- even if this only means validating data and storing it in the database. Your client will always be able to see all the HTTP requests that they send: that's the way HTTP works. You can't hide the information from them. Even if you generate tokens dynamically (see below), you can't prevent them from using them elsewhere. They can always build a custom HTTP request, which means ultimately that they can, if they really, really want, abandon your app altogether. Think of your client-side code as merely making it easier for them to perform HTTP requests and abandon any idea of preventing them "doing it wrong"!
The much better option is CSRF protection, which gives the best possible protection to both your server and the client. This means sending a generated token to your client when they first log on and verifying it (either by looking it up or decrypting it) when they send it on every request. This is the basis of JWT, which is a beautiful implementation of a fairly old system of verification.
In the end your API is public, since any random website visitor will have to be able to interact with the API. Even if you use tokens to restrict access somewhat, those tokens by definition will have to be public as well. Even regularly expiring and renewing the tokens (e.g. through a backend API, or by including a nonce algorithm) won't help, since those new tokens will again be publicly visible on the 3rd party's website where anyone can fetch one.
CSRF protection can help a little to avoid cross-site abuse within browsers, but is ultimately pointless for the purpose of preventing someone to write an API scraper or such.
The best you can do is use the tokens to identify individual site owners you granted access to, vigilantly monitor your API use, invalidate tokens when you think you're seeing them abused and contact the site owners about securing their tokens better somehow (which they'll have the same problem doing, but at least you have someone to blame cough cough).
You can use hmac to secure this :
Each client has a unique couple of key public/private (for example "public" and "private").
When client send request, he has to send a nonce + his user public key + the hmac of nonce+public key with his private key.
When server handle request, the server retrieve the client according to his public key, get the secret key of the user, then verify the signature.
Client, sample call on /api
var nonce = "randomstring";
var pk = "aaa";
var sk = "bbb";
var string = "pk="+pk+"&nonce="+nonce;
var crypto = require('crypto');
var hmac = crypto.createHmac('sha512', sk).update(string).digest('hex');
// send this payload in your request in get, put, post, ....
var payload = string+"&hmac="+hmac;
request.post({uri:"website.com/api?"+payload}, ....
And
Server side, security check
var nonce = req.query.nonce;
var pk = req.query.pk;
var hmac = req.query.hmac;
// retrieve user and his sk according to pk
var sk = getUser(pk).sk
// rebuild payload string
var string = "pk="+pk+"&nonce="+nonce;
var crypto = require('crypto');
var hmac_check = crypto.createHmac('sha512', sk).update(string).digest('hex');
if(hmac_check === hmac) { // request valid }else{ // invalid request }
I am using Thinktecture AuthorizationServer (AS) and it is working great.
I would like to write a native javascript single page app which can call a WebAPI directly, however implicit flow does not provide a refresh token.
If an AJAX call is made, if the token has expired the API will send a redirect to the login page, since the data is using dynamic popups it will this will interrupt the user.
How does Facebook or Stackoverflow do this and still allow the javascript running on the page to call the APIs?
Proposed Solution
Does the below scenario sound sensible (assuming this can be done with iframes):
My SPA directs me to the AS and I obtain a token by Implicit Flow. Within AS I click allow Read data scope, and click Remember decision, then Allow button.
Since I have clicked Remember decision button, whenever I hit AS for a token, a new token is passed back automatically without me needing to sign in ( I can see FedAuth cookie which is remembering my decision and believe this is enabling this to just work).
With my SPA (untrusted app), I don't have a refresh-token only an access token. So instead I:
Ensure user has logged in and clicked remember decision (otherwise iframe wont work)
Call WebAPI, if 401 response try and get a new token by the below steps...
Have a hidden iframe on the page, which I will set the URL to get a new access-token from the Authorisation Server.
Get the new token from the iframe's hash-fragment, then store this in the SPA and use for all future WebAPI requests.
I guess I would still be in trouble if the FedAuth cookie is stolen.
Any standard or recommended way for the above scenario?
I understand that your problem is that the user will experience an interruption when the access token has expired, by a redirection to the login page of the authorization server. But I don't think you can and should get around this, at least, when using the implicit grant.
As I'm sure you already know, the implicit grant should be used by consumers that can NOT keep their credentials secret. Because of this, the access token that is issued by an authorization server should have a limited ttl. For instance google invalidates their access token in 3600 sec. Of course you can increase the ttl, but it should never become a long lived token.
Also something to note is that in my opinion the user interruption is very minimal, i.e if implemented correctly, the user will only have to authenticate once with the authorization server. After doing that (for example the first time when also authorizing the application access to whatever resources the user controls) a session will be established (either cookie- or token based) and when the access token of the consumer (web app using implicit grant) expires, the user will be notified that the token has expired and re authentication with the authorization server is required. But because a session already has been established, the user will be immediately redirected back to the web app.
If however this is not what you want, you should, in my opinion, consider using the authorization code grant, instead of doing complicated stuff with iframes.
In that case you need a server side web application because then you can keep your credentials secret and use refresh tokens.
Sounds like you need to queue requests in the event that an access token expires. This is more or less how Facebook and Google do it. A simple way using Angular would be to add a HTTP Interceptor and check for HTTP401 responses. If one is returned, you re-authenticate and queue any requests that come in after until the authentication request has completed (i.e. a promise). Once that's done, you can then process the outstanding queue with the newly returned access token from your authentication request using your refresh token.
Happy Coding.
Not sure if I understand your question but,
I would like to write a native javascript single page app which can call a WebAPI directly, however implicit flow does not provide a refresh token.
Summarize facts,
refresh token is sometimes used to be a part of A: Authorization Grant
https://www.rfc-editor.org/rfc/rfc6749#section-1.5
and as you said in implicit flow you dont get back refresh token, but only in Authorization Grant part
https://www.rfc-editor.org/rfc/rfc6749#section-4.2.2
so you can get back refresh token when issuing access token (refresh tokens are always optional)
https://www.rfc-editor.org/rfc/rfc6749#section-5.1
With my SPA (untrusted app), I don't have a refresh-token only an
access token. So instead I:
Ensure user has logged in and clicked remember decision (otherwise
iframe wont work)
Call WebAPI, if 401 response try and get a new
token by the below steps...
Have a hidden iframe on the page, which
I will set the URL to get a new access-token from the Authorisation
Server.
Get the new token from the iframe's hash-fragment, then
store this in the SPA and use for all future WebAPI requests.
SPA(you) have no idea if user selected remember decision. Its in AS direction and should be complete blackbox. Skip this step.
You can try to use access token and wait for result, always.
If access token has expired and you dont have refresh token, you still can create hidden iframe and and try to get new access token.
Lets assume your AS provide option to remember decision and wont change it in future, then: your iframe will get new access token without user interaction, then you will get result back in some unknown time limit.
Result can be checked by setInterval for read specific cookie or iframe postmessage.
If you dont get back data in time limit, then one from following scenarios occured:
lag, AS is slow, connection is slow or time limit is too tight
user didnt select remember decision
In this case:
show iframe with login
I consider scenario above as good practise if AS doesnt provide refresh tokens, but I also guess every AS like that wont provide remember option as well.
StackOverflow <---> Google scenario (I can only guess)
User login, authorization request occured
User logs in, SO gets access token
SO tries to use access token
SO gets back result + refresh token
SO saves refresh token
SO has permanent access to users Google account
In Google o-Auth , the access token will only be valid for 1 hour, so you need to programmatically update your access token in each one hour, simple you can create web api to do so,you need to have a refresh token, and also that refresh token will not be expired , using c# code, I have done this.
if (dateTimeDiff > 55)
{
var request = (HttpWebRequest)WebRequest.Create("https://www.googleapis.com/oauth2/v3/token");
var postData = "refresh_token=your refresh token";
postData += "&client_id=your client id";
postData += "&client_secret=your client secrent";
postData += "&grant_type=refresh_token";
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
request.UseDefaultCredentials = true;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
you need to save the last updated date time of the access token somewhere(say in database), so that , whenever you have to make a request , so you can subtract that with current date time , if it is more than 60 minutes , you need to call the webapi to get new token .
I have built a browser game and now I'm working on making it a bit more secure. Since all server requests are initiated from javascript even kids could tamper data on the server. I've been reading through questions on stackoverflow and implemented sending/receiving a token in my requests however I am regenerating this token on every request to the server and send the new one back to the client for the next call. Requests are made through https and are of type POST.
Here's the token flow on client side:
var token = 'abcd1234';
$.ajax({
url: "index.php",
type: "post",
data: {
method: "score",
value: 50
}
});
$(document).ajaxSend(function(e, xhr, o){
o.data += '&token=' + token;
});
$(document).ajaxComplete(function(e, xhr, o){
var data = JSON.parse(xhr.responseText);
token = data.token;
});
And on server side:
if (!isset($_POST['token']) || ($_POST['token'] != $_SESSION['token']))
{
die();
}
else
{
// generate new token and send it back along with the response
}
So my question would be if this token increases the security of my server requests or not and what can be done to further increase the security?
EDIT This is a facebook game, all code is javascript and the server side simply handles updating the database.
I dont really think tokens do alot when using Ajax.
You should just validate all your forms and data server sided with the users session because the login itself is the most realiable way to identify a user.
A token an merely help to make session stealing/riding harder but if you code your session handle to logout the user on changed IP adress this should be fair secure enough.
I have an online game aswell and I dont do more but validate all forms and values against injection, valid data and check the login/session every time correctly and never had any bad experience with that.
One more thing I do is security issue is that you should flag your admin accounts with a special attribute that it requires a special IP range to login, then I fetch the ip range with a whois lookup on ripe.net and enter it into the database and look if the users actual IP is inside the min and max ip, this way maybe 1 of 1000 attackers would have the correct IP adress to login with the admin account even if they achive the login data.
Remember that the generated token will be received and send with every normal ajax request and someone who want to harm you and your page will analyse your form and request data and then simply copy that process.
It will make it harder for script kiddies, but not for professional intruders.
Its all just a matter about how paranoid you are about security issues and how skilled your possible attackers are.
As Steini already stated the ONLY reliable login system is done with session. The client side solution has got infinity security issues.
You can for example make the system using session and than use Javascript to ask php if the user is logged, and which privilege it has.
This said you can use PDO to increment the security, you can also fetch all the data from all the form and all variables that are passed through browser alone to exclude some issues.
Without a secure login system your game will be a security bomb and will create you trouble soon or later.
We are creating a prototype application as follows:
We have a html web site using knockoutjs
Using qQuery/Ajax it communicates with Web Api services
We only want the services to be accessed by authorised users. So we have written in security that can validate the user based on username/password
So next I guess we need to pass back some type of token to the client which it uses in further communications with the API services.
What I would like to know is how this is stored on the client so it can be passed back to the server again for the next call?
I assume the client makes an initial call passing in the user name and password over HTTPS and gets back a token. You question is to how to store the token? I assume your application is an SPA. If so, why not just store it in a JavaScript variable? If you do not use a cookie, you avoid XSRF. Of course, you must ensure the user name and password are never stored in the client side and that the life time token of your token is finite and preferably as small as possible.
EDIT:
If you can regenerate the token with every page (since it is not SPA), it is even better and you make the life time of token very small. You can use code like this. I use Authorization header and bearer scheme but you can use your own scheme as well, if no standardization is needed.
var accessToken = ''; // Write out the token into this variable in the server side (view)
$.ajax({
type: 'GET',
url: 'http://whatever',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
headers: { 'Authorization=': ='Bearer ' + accessToken },
success: function (data) {
}
});
So we have written in security that can validate the user based on username/password
This sentence basically means that you need to store the username and password in your javascript file in order to be able to call the service, unless of course you want to ask the user to enter his credentials on every single action he performs. I hope this is not something you are wiling to do at the moment. If it is then you can stop reading my answer and store the username and password in your javascript file.
At this stage it is more than clear that your security should be handled differently. Your Web API should not be protected by a username and password but by a token. Here's how this could work in practice. You will have an action that will take the username and password, validate them and if successful it will return a token. This token could contain the encrypted username. So your javascript will ask the user for his username and password, call the Login method and it could store the token. Then it will use this token on subsequent calls. The API will in turn decrypt it in order to extract the username.
What I would like to know is how this is stored on the client so it can be passed back to the server again for the next call?
Cookies. You will send token as a cookie, and it will be sent automatically when user requests your page.
create a server side session, for the once authorised md5(username) md5(password).
generate an uuid per request, and return it in the response.
basic model is called token exchange and it is reliable (no m.i.t.m) even w/o SSL.