Hidden arguments from Javascript to Django view - javascript

I am currently working on integrating Facebook Login into my website.
In javascript, I was able to fetch the user's information the moment (s)he logs to my website; via Facebook.
So, part of my javascript code is the following:
...
u_email = response.email; //gets user's email
u_fname = response.first_name; //gets user's first name
...and so on!
Now I would like to do one of the two following scenarios: 1) If this is the first time the user logs in into my website; I would like to save all this information (email, first name, ...) to my users' database; 2) If this is not the first time the user logs in, I would like to redirect the user to another page, and display some information about him/her that I will need to get from the database (according to his/her email)!
In either case, I will have to access the database through the user's information. So, what I would like to do, is to redirect the user to a Django view while passing the user's information. For example, I can have the following in my javascript file:
document.location.href = '../' + u_email +'/' + u_fname + '/login';
...and in my urls.py, I can have the following:
url(r'^(?P<u_email>\w+)/(?P<u_fname>\w+)/login/$', views.login, name='login')
Lastly, in my view file, I can have the following:
def login(request, u_email, u_fname):
template = loader.get_template('counters/login.html')
context = RequestContext(request, {
'u_email': u_email,
'u_fname': u_fname,
})
return HttpResponse(template.render(context))
Now; clearly, I have a problem, that is, the user's (supposedly secretive) information will be shown in the url! Is there a way to avoid it by hiding the arguments passed from the javascript to the Django view?

I think you should not have url patterns based on critical information a potential attacker should not be able to see. This type of information should be passed to the server side using a POST request method in an encrypted ssl or tls request.
But for your usecase a better approach to achieve that is to :
use the FB javascript api to login on client side and get a FB token
send a POST https request to your backend and have your backend code requesting the user information using the FB Graph Api. (the ssl and tls request is necessary to pass the access_token information in POST mode, this is here the sensitive data)
#the view code
#import your user model here
import requests
from django.shortcuts import render_to_response
#POST_required
def login(request, facebookId):
if token is not None:
#query graph api
r = requests.get('https://graph.facebook.com/{facebook_id}?fields=email,name&access_token={token}'.format({'facebook_id':facebook_id, 'token':token}))
facebook_email = r.json()['email']
facebook_name = r.json()['name']
#check if first login
try:
user = Users.object.get(email=facebook_email, name=facebook_name)
except Users.DoesNotExist:
user = Users.objects.create(email=facebook_email, name=facebook_name)
render_to_response('counter/login.html', dictionnary={'user':user}, context=RenderContext(request))
#url conf code
from django.conf.urls import patterns, url
import views
url_patterns = url('',
patterns(r'^(?Pw+)/login/$', views.login)

According you have an Model to save the User information and his email is unique.
def login(request, u_email, u_fname):
try:
# Try to get the User in your DB
user = YourUserModel.objects.get(email=u_email)
# Do your redirects.
except YourUserModel.DoesNotExist:
# Do your other stuffs, like add this new user in your DB
template = loader.get_template('counters/login.html')
context = RequestContext(request, {
'u_email': u_email,
'u_fname': u_fname,
})
return HttpResponse(template.render(context))

Related

Can client mock a cookie?

I'm using ASP.NET and create a cookie on server, like this:
public void LoginCookie(string id, string name, string loc)
{
HttpCookie cookie = new HttpCookie("login");
cookie["name"] = HttpContext.Current.Server.UrlEncode(name); // user name
cookie["avatar"] = loc; // user avatar location
cookie["accountId"] = id; // user id
cookie.Expires = DateTime.Now.AddDays(180); // default expiring
HttpContext.Current.Response.Cookies.Add(cookie);
}
And here is the code to check if user is login:
if (Request.Cookies["login"] != null)
{
// login successful
}
My trouble is: Any client can view the cookie values easily. So, what's happen if he mocks a new cookie with the same name login and same values name, avatar, accountId?
If he does that, he needn't be login (same meaning with login without a password).
Is there any way to do that?
The way to do this is to store a hash of the username and the username in the cookie. Since the client does not know how you generate the hash (and you should generate with a cryptographically strong method) and can't generate one you can verify the user was the one you authenticated by checking the hash. To be really safe you probably want to include a time stamp in the hash.
Or you could encrypt the username (or more often userid) after authentication and store that. This is the most common method.
You could also use SSL or TLS and the cookies will be encrypted. However, this does not stop the client just people spying on the client.

How to fix whenever I click on a page link within site, I get logged out?

I have an intranet site with multiple page links linking to other pages within the site on each page. The issue is that if I login to my profile for example I have no problem, but if I click on a link to say my index page or recent news page or whatever it takes me to the page but I get logged out and I have to login again. I've found out that linking between pages out works if the user's password is "something"
I have two versions of this site, the only difference is that they connect to different databases. On one domain everything works fine, on the other is when I get this issue.
This is at the top of every page for connections to the database and checking to see if the user has the right credentials and just some functions. I think the issue should be with the code checking the user credentials and or starting the session.
<?php
// Connect To Secure Login
$cfgProgDir = 'phpSecurePages/';
include($cfgProgDir . "secure.php");
//These are the includes needed to make the php page run
// this file connects to the database
include("includes/connect.inc.php");
// This file holds all the custom functions
include("includes/functions.inc.php");
This is the config file
$cfgIndexpage = '/index.php';
$cfgServerHost = '********************'; // MySQL hostname
$cfgServerPort = ''; // MySQL port - leave blank for default port
$cfgServerUser = '*********'; // MySQL user
$cfgServerPassword = '**********'; // MySQL password
$cfgDbDatabase = '******'; // MySQL database name containing phpSecurePages table
$cfgDbTableUsers = 'members'; // MySQL table name containing phpSecurePages user fields
$cfgDbLoginfield = 'firstName'; // MySQL field name containing login word
$cfgDbPasswordfield = 'password'; // MySQL field name containing password
$cfgDbUserLevelfield = 'permission'; // MySQL field name containing user level
// Choose a number which represents the category of this users authorization level.
// Leave empty if authorization levels are not used.
$cfgDbUserIDfield = 'id'; // MySQL field name containing user
/****** Data ******/
/* this data is necessary if no database is used */
$cfgLogin[1] = ''; // login word (username)
$cfgPassword[1] = ''; // password
$cfgUserLevel[1] = '0'; // user level
and the connect file ($connect) just connects the my DB
Any suggestions on what the issue could be? :)
It probably means your session is getting destroyed somewhere or cookies aren't being set.
I didn't dwelve much into the code (It's a bit messy) but... secure.php include checklogin.php on line 67. On checklogin.php file, Line 37, session_start() is called and it is called again on your config file.
It should raise a warning so, if you haven't seen it, you're either using an old version of PHP or you don't have error reporting enabled.
You should enable error reporting and check for any notice or warning.

Concern with Facebook's login decoding sign_request performance

I am completely new to the Facebook API. I would like to incorporate Facebook login into my application. I am using the Javascript SDK on the front-end to log the user in and retrieve the user_id and signed_request from Facebook. I then plan to send these two pieces of information via AJAX to my server (either php/hack (hhvm), node, java, or whichever language I can determine is quickest for decoding) every time my logged in user does an action on my application to validate if the user is indeed logged in and is the person they say they are. For me to accomplish this, I need to decode the signed_request, for example in php:
function parse_signed_request($signed_request) {
list($encoded_sig, $payload) = explode('.', $signed_request, 2);
$secret = "appsecret"; // Use your app secret here
// decode the data
$sig = base64_url_decode($encoded_sig);
$data = json_decode(base64_url_decode($payload), true);
// confirm the signature
$expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
if ($sig !== $expected_sig) {
error_log('Bad Signed JSON signature!');
return null;
}
return $data;
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_', '+/'));
}
which then I will be able to extract the following JSON object:
{
"oauth_token": "{user-access-token}",
"algorithm": "HMAC-SHA256",
"expires": 1291840400,
"issued_at": 1291836800,
"user_id": "218471"
}
to be able to compare if the user_id the user sent over matches the one in the JSON object. Then if it matches I can complete my business logic (DB manipulation).
My big concern here is a user will be sending many requests to my server, so every time I will need to decode this signed_request which can really kill my server performance. I was thinking I maybe could call Facebook from my server, pass the user_id, and receive the signed_request string, which I can then match with the signed_request string the user sent over from the client_side and see if they match. This would be more efficient, but it does not seem Facebook offers anything like this. Is there any other methods besides the heavy performing decoding to validate a user? I have gone through quite a bit of the Facebook SDK's information but could not find a solution. If I must decode, which language/library would be the best performing at this type of operation?
PS. I plan on using cordova later to create a mobile app so I must use only Javascript on the front end and can't use a server language such as php to create html for the client.
Decoding the signed request will not kill your server. It's way fast than making an external request.
If you're using php you should look into the Facebook SDK for PHP and use this helper: https://developers.facebook.com/docs/php/FacebookJavaScriptLoginHelper/4.0.0

auto-saving the contents of a WTForm

I am making a (quite frankly) somewhat tenuous form. As such, I want it to save every time they input something into a data field. However, I don't want to save them as a user to the site until the form is complete and validated.
This is what I imagine the javascript side to contain
$('input').blur(function() {
$.post(endpoint, form);
});
however, what I currently have for the endpoint is something like this:
#auth.route('/register', methods=['GET', 'POST'])
def register():
""" register a new user using the form """
form = RegistrationForm()
if form.validate_on_submit():
new_user = User(
email=form.email.data.lower(),
first_name=form.first_name.data.title(),
last_name=form.last_name.data.title(),
username=form.username.data.lower(),
password=form.password.data
)
db.session.add(new_user)
flash('successfully registered!', 'success')
return redirect(url_for('auth.login'))
return render_template('user/register.html', form=form)
this works well to register a user, but how do I simply save their form data for later use if they revisit without making them a user?
I think you have to store each session into database, you have to load the partial filled form data when the session and cookie communicates.
IMHO, when the new user comes to the application new session will be created, you have to store that session into database, if the user starts filling the form you have to update the data along with session variable, then when the same user tries to access next time, the same session need to be loaded from the database. The session has to be identified from the cookie input like
identify the session using sid
sid = request.cookies.get(app.session_cookie_name)
followed by, you have to load the partial filled form data along with that particular session.
loading the session back
response.set_cookie(app.session_cookie_name, session.sid,
expires=self.get_expiration_time(app, session),
httponly=True, domain=domain)
The example code is already done by some GOD for you :)
I assume you are already aware of storing and retrieving the form data.

Can I detect valid JSONP return?

I want to send/receive data to a web service on a different server that does not have CORS enabled. I have to use JSONP to do it. The service requires authentication and most of the time the user is in an SSO environment and the SSO mechnaism easily passes them to the service without issue.
When not inside the SSO environment, the user is redirected (301) to a login page, which of course returns invalid javascript because the file would start with <!Doctype...
Is there a way to see if the returned data is operable? I know exactly what the first 15 chars should be anytime the user can successfully access the service. I would like to check the return and then do something like:
if(dataIsValid){ //continue normally, build page with returned data }
else{ //redirect to non-SSO login page }
Or anything that resembles that kind of a workflow.
I assume you're using jQuery since you've added a relevant tag.
var dataIsValid = true;
var data = {};
try {
data= $.parseJSON(data);
} catch (exc){
dataIsValid = false;
}
//...

Categories

Resources