Python - Inheritance - Facebook application - python

I have a question about how the code run in inheritance in Python. It might look like a dummy question somehow, but I a new to Python.
This a code snippet from some Facebook application I am working on:
class BaseHandler(webapp.RequestHandler):
facebook = None
user = None
def initialize(self, request, response):
"""General initialization for every request"""
super(BaseHandler, self).initialize(request, response)
try:
self.init_facebook()
except Exception, ex:
self.log_exception(ex)
raise
def init_facebook(self):
"""Sets up the request specific Facebook and user instance"""
facebook = Facebook()
user = None
# Initially Facebook request comes in as a POST with a signed_request
if u'signed_request' in self.request.POST:
facebook.load_signed_request(self.request.get('signed_request'))
# We reset the method to GET because a request from Facebook with a
# signed_request uses POST for security reasons, despite it
# actually being a GET. In a web application this causes loss of request.POST data.
self.request.method = u'GET'
self.set_cookie(
'u', facebook.user_cookie, datetime.timedelta(minutes=1440))
elif 'u' in self.request.cookies:
facebook.load_signed_request(self.request.cookies.get('u'))
# Try to load or create a user object
if facebook.user_id:
user = User.get_by_key_name(facebook.user_id)
if user:
# Update stored access_token
if facebook.access_token and \
facebook.access_token != user.access_token:
user.access_token = facebook.access_token
user.put()
# Refresh data if we failed in doing so after a realtime ping.
if user.dirty:
user.refresh_data()
# Restore stored access_token if necessary
if not facebook.access_token:
facebook.access_token = user.access_token
if not user and facebook.access_token:
me = facebook.api(u'/me', {u'fields': _USER_FIELDS})
try:
friends = [user[u'id'] for user in me[u'friends'][u'data']]
user = User(key_name=facebook.user_id,
user_id=facebook.user_id, friends=friends,
access_token=facebook.access_token, name=me[u'name'],
email=me.get(u'email'), picture=me[u'picture'])
user.put()
except KeyError, ex:
pass # Ignore if can't get the minimum fields.
self.facebook = facebook
self.user = user
This is another class that inherits from BaseHandler
class RecentRunsHandler(BaseHandler):
"""Show recent runs for the user and friends"""
def get(self):
if self.user:
friends = {}
for friend in select_random(
User.get_by_key_name(self.user.friends), 30):
friends[friend.user_id] = friend
self.render(u'runs',
friends=friends,
user_recent_runs=Run.find_by_user_ids(
[self.user.user_id], limit=5),
friends_runs=Run.find_by_user_ids(friends.keys()),
)
else:
self.render(u'welcome')
Does the initialize function in the BaseHandler get called when the RecentRunsHandler is called?
I am asking this because if after the user "allow" the application (and the user data is saved in the database) ... The application still redirects him to the welcoming page where the Facebook-login button exists.
To make it more clear, the application can't know that the user has authorized him before.

Probably not. Perhaps you should def initialize to def __init__? Python objects get instantiated through the __init__ method, not through any initialize() method. Since you don't seem to have any explicit calls to initialize(), it will probably not be called.

Related

how does flask-login identify different users that have logged in by a single session?

I have know that we created a session object with unique sessionID to response to client when a user first logged, and then when user request others' they will request with a cookie with that ID, so server can find the session object by that ID, which will denote the user have logged!
But this is one user situation, I find most blogs doesn't say if there are many users to manage, if we need to create many sessions in memory to every user. I think so!
But when I lookup flask-login source code, I can't find a session collections to maintain session for every user?
def login_user(user, remember=False, force=False, fresh=True):
'''
Logs a user in. You should pass the actual user object to this. If the
user's `is_active` property is ``False``, they will not be logged in
unless `force` is ``True``.
This will return ``True`` if the log in attempt succeeds, and ``False`` if
it fails (i.e. because the user is inactive).
:param user: The user object to log in.
:type user: object
:param remember: Whether to remember the user after their session expires.
Defaults to ``False``.
:type remember: bool
:param force: If the user is inactive, setting this to ``True`` will log
them in regardless. Defaults to ``False``.
:type force: bool
:param fresh: setting this to ``False`` will log in the user with a session
marked as not "fresh". Defaults to ``True``.
:type fresh: bool
'''
if not force and not user.is_active:
return False
user_id = getattr(user, current_app.login_manager.id_attribute)()
session['user_id'] = user_id
session['_fresh'] = fresh
session['_id'] = _create_identifier()
if remember:
session['remember'] = 'set'
_request_ctx_stack.top.user = user
user_logged_in.send(current_app._get_current_object(), user=_get_user())
return True
There is one session to keep the user, but what if another user come?
# -*- coding: utf-8 -*-
"""
flask.globals
~~~~~~~~~~~~~
Defines all the global objects that are proxies to the current
active context.
:copyright: (c) 2011 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
from functools import partial
from werkzeug.local import LocalStack, LocalProxy
def _lookup_req_object(name):
top = _request_ctx_stack.top
if top is None:
raise RuntimeError('working outside of request context')
return getattr(top, name)
def _lookup_app_object(name):
top = _app_ctx_stack.top
if top is None:
raise RuntimeError('working outside of application context')
return getattr(top, name)
def _find_app():
top = _app_ctx_stack.top
if top is None:
raise RuntimeError('working outside of application context')
return top.app
# context locals
_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()
current_app = LocalProxy(_find_app)
request = LocalProxy(partial(_lookup_req_object, 'request'))
session = LocalProxy(partial(_lookup_req_object, 'session'))
g = LocalProxy(partial(_lookup_app_object, 'g'))
I find session is an global variable, and is an localstack(), but I still don't konw how does it works?
class Local(object):
__slots__ = ('__storage__', '__ident_func__')
def __init__(self):
object.__setattr__(self, '__storage__', {})
object.__setattr__(self, '__ident_func__', get_ident)
def __iter__(self):
return iter(self.__storage__.items())
def __call__(self, proxy):
"""Create a proxy for a name."""
return LocalProxy(self, proxy)
def __release_local__(self):
self.__storage__.pop(self.__ident_func__(), None)
def __getattr__(self, name):
try:
return self.__storage__[self.__ident_func__()][name]
except KeyError:
raise AttributeError(name)
def __setattr__(self, name, value):
ident = self.__ident_func__()
storage = self.__storage__
try:
storage[ident][name] = value
except KeyError:
storage[ident] = {name: value}
def __delattr__(self, name):
try:
del self.__storage__[self.__ident_func__()][name]
except KeyError:
raise AttributeError(name)
Many people say it will use another thread id to identify, storage[ident][name] = value , but i disable threading, it works well for multi-users?
I just find it use current_user variable to identify current user, but current_user is so magic! It doesn't maintain user session collection but just one current_user to solve the problem! I don't know how it works?
def login_required(func):
'''
If you decorate a view with this, it will ensure that the current user is
logged in and authenticated before calling the actual view. (If they are
not, it calls the :attr:`LoginManager.unauthorized` callback.) For
example::
#app.route('/post')
#login_required
def post():
pass
If there are only certain times you need to require that your user is
logged in, you can do so with::
if not current_user.is_authenticated:
return current_app.login_manager.unauthorized()
...which is essentially the code that this function adds to your views.
It can be convenient to globally turn off authentication when unit testing.
To enable this, if the application configuration variable `LOGIN_DISABLED`
is set to `True`, this decorator will be ignored.
.. Note ::
Per `W3 guidelines for CORS preflight requests
<http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0>`_,
HTTP ``OPTIONS`` requests are exempt from login checks.
:param func: The view function to decorate.
:type func: function
'''
#wraps(func)
def decorated_view(*args, **kwargs):
if request.method in EXEMPT_METHODS:
return func(*args, **kwargs)
elif current_app.login_manager._login_disabled:
return func(*args, **kwargs)
elif not current_user.is_authenticated:
return current_app.login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
So where is process of comparing current user sessionID from cookie with session collection mantained by server? Anybody can help me?
I take a look at flask-login/flask_login/login_manager.py:_load_user()
I guess you are talking about SESSION_PROTECTION. In this case the way user will be reloaded depends on basic or strong auth modes. If you have no session protection, flask try to load the user from request, header or cookies if you have handlers for this.
class LoginManager(object):
...
def _load_user(self):
'''Loads user from session or remember_me cookie as applicable'''
user_accessed.send(current_app._get_current_object())
# first check SESSION_PROTECTION
config = current_app.config
if config.get('SESSION_PROTECTION', self.session_protection):
deleted = self._session_protection()
if deleted:
return self.reload_user()
# If a remember cookie is set, and the session is not, move the
# cookie user ID to the session.
#
# However, the session may have been set if the user has been
# logged out on this request, 'remember' would be set to clear,
# so we should check for that and not restore the session.
is_missing_user_id = 'user_id' not in session
if is_missing_user_id:
cookie_name = config.get('REMEMBER_COOKIE_NAME', COOKIE_NAME)
header_name = config.get('AUTH_HEADER_NAME', AUTH_HEADER_NAME)
has_cookie = (cookie_name in request.cookies and
session.get('remember') != 'clear')
if has_cookie:
return self._load_from_cookie(request.cookies[cookie_name])
elif self.request_callback:
return self._load_from_request(request)
elif header_name in request.headers:
return self._load_from_header(request.headers[header_name])
return self.reload_user()
def _load_from_request(self, request):
user = None
if self.request_callback:
user = self.request_callback(request)
if user is not None:
self.reload_user(user=user)
app = current_app._get_current_object()
user_loaded_from_request.send(app, user=_get_user())
else:
self.reload_user()
Flask passes request to your callback if it presented. Flask-login has good example(Custom Login using Request Loader) how you can load user from request.
#login_manager.request_loader
def load_user_from_request(request):
# first, try to login using the api_key url arg
api_key = request.args.get('api_key')
if api_key:
user = User.query.filter_by(api_key=api_key).first()
if user:
return user
# next, try to login using Basic Auth
api_key = request.headers.get('Authorization')
if api_key:
api_key = api_key.replace('Basic ', '', 1)
try:
api_key = base64.b64decode(api_key)
except TypeError:
pass
user = User.query.filter_by(api_key=api_key).first()
if user:
return user
# finally, return None if both methods did not login the user
return None
The api_key can be assigned when a client will be authorized through the backend for different logins from one physical machine.

How to disconnect update_last_login?

I implemented my own User class from scratch in Django. But when I log in I have this error:
The following fields do not exist in this model or are m2m fields: last_login
I really don't want the field last_login.
I do some reasearch and the problem is here: contrib.aut.models.py
def update_last_login(sender, user, **kwargs):
"""
A signal receiver which updates the last_login date for
the user logging in.
"""
user.last_login = timezone.now()
user.save(update_fields=['last_login'])
user_logged_in.connect(update_last_login)
I found a workaround but it's not an ellegant solution. I added user_logged_in.disconnect(update_last_login) in my models.py file, where my User class is defined.
Is there any better solution for this?
Not sure if this is related to a newer version of django or what, but in my case
user_logged_in.disconnect(update_last_login)
didn't work. This is what works for me (django 2.1):
user_logged_in.disconnect(update_last_login, dispatch_uid='update_last_login')
Currently in Django 1.7...
I think the workaround you defined is the only valid solution (besides from a monkey patch) currently when using the Django auth login() method. I'm just going to assume you are using the standard login() method which is raising this exception.
If we take a look at the source for the login method, we find at the end of the method, a call to execute user_logged_in.send(sender=user.__class__, request=request, user=user). We can't prevent this signal from executing besides from disconnecting it as you have pointed out.
Alternatively, we could monkey patch the login() method to remove that signal call.
from django.contrib.auth import login
def monkey_patch_login(request, user):
"""
Persist a user id and a backend in the request. This way a user doesn't
have to reauthenticate on every request. Note that data set during
the anonymous session is retained when the user logs in.
"""
session_auth_hash = ''
if user is None:
user = request.user
if hasattr(user, 'get_session_auth_hash'):
session_auth_hash = user.get_session_auth_hash()
if SESSION_KEY in request.session:
if _get_user_session_key(request) != user.pk or (
session_auth_hash and
request.session.get(HASH_SESSION_KEY) != session_auth_hash):
# To avoid reusing another user's session, create a new, empty
# session if the existing session corresponds to a different
# authenticated user.
request.session.flush()
else:
request.session.cycle_key()
request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)
request.session[BACKEND_SESSION_KEY] = user.backend
request.session[HASH_SESSION_KEY] = session_auth_hash
if hasattr(request, 'user'):
request.user = user
rotate_token(request)
login = monkey_patch_login
We would put the monkey patch code at the top of the file that needs to call the login() method.

How to read email of facebook user using Facebook graph api for python-tornado?

I have included 'email' in extended parameters scope. How do I read the email in a tornado object?
My LoginHandler looks like this:
class LoginHandler(tornado.web.RequestHandler, tornado.auth.FacebookGraphMixin):
#tornado.web.asynchronous
def get(self):
userID = self.get_secure_cookie('user_id')
if self.get_argument('code', None):
self.get_authenticated_user(
redirect_uri='http://localhost:8000/auth/login',
client_id=self.settings['facebook_api_key'],
client_secret=self.settings['facebook_secret'],
code=self.get_argument('code'),
callback=self.async_callback(self._on_facebook_login))
return
elif self.get_secure_cookie('access_token'):
self.redirect('/')
return
self.authorize_redirect(
redirect_uri='http://localhost:8000/auth/login',
client_id=self.settings['facebook_api_key'],
extra_params={'scope': 'email'}
)
def _on_facebook_login(self, user):
if not user:
self.clear_all_cookies()
raise tornado.web.HTTPError(500, 'Facebook authentication failed')
self.set_secure_cookie('user_id', str(user['id']))
self.set_secure_cookie('user_name', str(user['name']))
self.set_secure_cookie('access_token', str(user['access_token']))
self.redirect('/')
I need to collect the email in an object and insert it into the database.
I literally had the same problem just a few days ago. Facebook documentation doesn't really help you to use the API. You have to dig around.
Anw, the solution is to make a facebook_request() and get the user profile. In that user profile you can find the email of the user. Put the request in the login callback.
The request would look like this:
self.facebook_request("/me", access_token=user["access_token"], callback=self._save_user_profile)
You access the user token from the "user" object returned in your _on_facebook_login() callback. Now define another callback called _save_user_profile().
def _save_user_profile(self, user):
if not user:
raise tornado.web.HTTPError(500, "Facebook authentication failed.")
try:
User.objects(email=user['email']).get()
except DoesNotExist, e:
new_u = User()
new_u.first_name = user['first_name']
new_u.last_name = user['last_name']
new_u.email = user['email'] #THIS IS WHAT YOU NEED
new_u.username = user['username']
new_u.gender = user['gender']
new_u.locale = user['locale']
new_u.fb_id = user['id']
new_u.save()
else:
#User exists
pass

How to implement user_loader callback in Flask-Login

I'm attempting to use Flask and the Flask-Login extension to implement user authentication in a Flask app. The goal is to pull user account information from a database and then log in a user, but I'm getting stuck; however, I've narrowed it down to a particular part of Flask-Login behavior.
According to the Flask-Login documentation, I need to create a user_loader "callback" function. The actual purpose and implementation of this function has had me confused for a few days now:
You will need to provide a user_loader callback. This callback is used
to reload the user object from the user ID stored in the session. It
should take the Unicode ID of a user, and return the corresponding
user object. For example:
#login_manager.user_loader
def load_user(userid):
return User.get(userid)
Now, say I want the user to enter a name and password into a form, check against a database, and log in the user. The database stuff works fine and is no problem for me.
This 'callback' function wants to be passed a user ID #, and return the User object (the contents of which I'm loading from a database). But I don't really get what it's supposed to be checking/doing, since the user IDs are all pulled from the same place anyway. I can 'sort-of' get the callback to work, but it seems messy/hackish and it hits the database with every single resource that the browser requests. I really don't want to check my database in order to download favicon.ico with every page refresh, but flask-login seems like it's forcing this.
If I don't check the database again, then I have no way to return a User object from this function. The User object/class gets created in the flask route for logging in, and is thus out of scope of the callback.
What I can't figure out is how to pass a User object into this callback function, without having to hit the database every single time. Or, otherwise figure out how to go about doing this in a more effective way. I must be missing something fundamental, but I've been staring at it for a few days now, throwing all kinds of functions and methods at it, and nothing is working out.
Here are relevant snippets from my test code. The User class:
class UserClass(UserMixin):
def __init__(self, name, id, active=True):
self.name = name
self.id = id
self.active = active
def is_active(self):
return self.active
The function I made to return the user object to Flask-Login's user_loader callback function:
def check_db(userid):
# query database (again), just so we can pass an object to the callback
db_check = users_collection.find_one({ 'userid' : userid })
UserObject = UserClass(db_check['username'], userid, active=True)
if userObject.id == userid:
return UserObject
else:
return None
The 'callback', which I don't totally understand (must return the User object, which gets created after pulling from database):
#login_manager.user_loader
def load_user(id):
return check_db(id)
The login route:
#app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST" and "username" in request.form:
username = request.form["username"]
# check MongoDB for the existence of the entered username
db_result = users_collection.find_one({ 'username' : username })
result_id = int(db_result['userid'])
# create User object/instance
User = UserClass(db_result['username'], result_id, active=True)
# if username entered matches database, log user in
if username == db_result['username']:
# log user in,
login_user(User)
return url_for("index"))
else:
flash("Invalid username.")
else:
flash(u"Invalid login.")
return render_template("login.html")
My code 'kinda' works, I can log in and out, but as I said, it must hit the database for absolutely everything, because I have to provide a User object to the callback function in a different namespace/scope from where the rest of the login action takes place. I'm pretty sure I'm doing it all wrong, but I can't figure out how.
The example code provided by flask-login does it this way, but this only works because it's pulling the User objects from a global hard-coded dictionary, not as in a real-world scenario like a database, where the DB must be checked and User objects created after the user enters their login credentials. And I can't seem to find any other example code that illustrates using a database with flask-login.
What am missing here?
You will need to load the user object from the DB upon every request. The strongest reason for that requirement is that Flask-Login will check the authentication token every time to ensure its continuing validity. The calculation of this token may require parameters stored on the user object.
For example, suppose a user has two concurrent sessions. In one of them, the user changes their password. In subsequent requests, the user must be logged out of the second session and forced to login anew for your application to be secure. Think of the case where the second session is stolen because your user forgot to log out of a computer - you want a password change to immediately fix the situation. You might also want to give your admins the ability to kick a user out.
For such forced logout to happen, the authentication token stored in a cookie must 1) be based in part on the password or something else that changes each time a new password is set; 2) be checked before running any view, against the latest known attributes of the user object - which are stored in the DB.
I do share your concerns Edmond: hitting database each time when one needs to know user's role or name is insane. Best way would be to store your User object in session or even application-wide cache which gets updated from the DB each couple of minutes. I personally use Redis for that (that way website can be run by multiple threads/processes while using single cache entry point). I just make sure Redis is configured with password and non-default port, and any confidential data (like user hashes etc) are stored there in an encrypted form. Cache can be populated by a separate script running on specified interval, or separate thread can be spawned in Flask. Note: Flask-Session can be also configured to use (the same) redis instance to store session data, in that case instance with 'bytes' datatype will be needed, for a regular cache you might often go with instance type which automatically translates bytes into strings (decode_responses=True).
Here is my code, another User as data mapping object provide query_pwd_md5 method.
User login:
#app.route('/users/login', methods=['POST'])
def login():
# check post.
uname = request.form.get('user_name')
request_pwd = request.form.get('password_md5')
user = User()
user.id = uname
try:
user.check_pwd(request_pwd, BacktestUser.query_pwd_md5(
uname, DBSessionMaker.get_session()
))
if user.is_authenticated:
login_user(user)
LOGGER.info('User login, username: {}'.format(user.id))
return utils.serialize({'userName': uname}, msg='login success.')
LOGGER.info('User login failed, username: {}'.format(user.id))
return abort(401)
except (MultipleResultsFound, TypeError):
return abort(401)
User class:
class User(UserMixin):
"""Flask-login user class.
"""
def __init__(self):
self.id = None
self._is_authenticated = False
self._is_active = True
self._is_anoymous = False
#property
def is_authenticated(self):
return self._is_authenticated
#is_authenticated.setter
def is_authenticated(self, val):
self._is_authenticated = val
#property
def is_active(self):
return self._is_active
#is_active.setter
def is_active(self, val):
self._is_active = val
#property
def is_anoymous(self):
return self._is_anoymous
#is_anoymous.setter
def is_anoymous(self, val):
self._is_anoymous = val
def check_pwd(self, request_pwd, pwd):
"""Check user request pwd and update authenticate status.
Args:
request_pwd: (str)
pwd: (unicode)
"""
if request_pwd:
self.is_authenticated = request_pwd == str(pwd)
else:
self.is_authenticated = False

Get first name from Facebook with django-socialregistration

With django-socialregistration what should I do to get the first name from Facebook at the moment of the Facebook Connect?
I tried to put these lines in django-socialregistration/views.py:
graph = request.facebook.graph
fb_profile = graph.get_object("me")
user.first_name = fb_profile['first_name']
user.save()
in the method post(self, request) after user = profile.authenticate() but I get this error when I try to connect:
int() argument must be a string or a number, not 'AnonymousUser'
Why? The error occurs at the first line graph = request.facebook.graph
The code of the django-socialregistration view:
class Setup(SocialRegistration, View):
"""
Setup view to create new Django users from third party APIs.
"""
template_name = 'socialregistration/setup.html'
def get_form(self):
"""
Return the form to be used. The return form is controlled
with ``SOCIALREGISTRATION_SETUP_FORM``.
"""
return self.import_attribute(FORM_CLASS)
def get_username_function(self):
"""
Return a function that can generate a username. The function
is controlled with ``SOCIALREGISTRATION_GENERATE_USERNAME_FUNCTION``.
"""
return self.import_attribute(USERNAME_FUNCTION)
def get_initial_data(self, request, user, profile, client):
"""
Return initial data for the setup form. The function can be
controlled with ``SOCIALREGISTRATION_INITIAL_DATA_FUNCTION``.
:param request: The current request object
:param user: The unsaved user object
:param profile: The unsaved profile object
:param client: The API client
"""
if INITAL_DATA_FUNCTION:
func = self.import_attribute(INITAL_DATA_FUNCTION)
return func(request, user, profile, client)
return {}
def generate_username_and_redirect(self, request, user, profile, client):
"""
Generate a username and then redirect the user to the correct place.
This method is called when ``SOCIALREGISTRATION_GENERATE_USERNAME``
is set.
:param request: The current request object
:param user: The unsaved user object
:param profile: The unsaved profile object
:param client: The API client
"""
func = self.get_username_function()
user.username = func(user, profile, client)
user.save()
profile.user = user
profile.save()
user = profile.authenticate()
self.send_connect_signal(request, user, profile, client)
self.login(request, user)
self.send_login_signal(request, user, profile, client)
self.delete_session_data(request)
return HttpResponseRedirect(self.get_next(request))
def get(self, request):
"""
When signing a new user up - either display a setup form, or
generate the username automatically.
"""
# I want some validation here, hacked up in the generic callback
try:
urlfrom = request.session['urlfrom']
match = resolve(urlfrom)
username, code = match.args
checkcode, referrer, ticket = utils.register_validate(username, code)
except:
return http.HttpResponseServerError()
# validation end
try:
user, profile, client = self.get_session_data(request)
except KeyError:
return self.render_to_response(dict(
error=_("Social profile is missing from your session.")))
if GENERATE_USERNAME:
return self.generate_username_and_redirect(request, user, profile, client)
form = self.get_form()(initial=self.get_initial_data(request, user, profile, client))
return self.render_to_response(dict(form=form))
def post(self, request):
"""
Save the user and profile, login and send the right signals.
"""
try:
user, profile, client = self.get_session_data(request)
except KeyError:
return self.render_to_response(dict(
error=_("A social profile is missing from your session.")))
form = self.get_form()(request.POST, request.FILES,
initial=self.get_initial_data(request, user, profile, client))
if not form.is_valid():
return self.render_to_response(dict(form=form))
user, profile = form.save(request, user, profile, client)
# validation count up referrals, tickets, etc.
try:
urlfrom = request.session['urlfrom']
match = resolve(urlfrom)
username, code = match.args
checkcode, referrer, ticket = utils.register_validate(username, code)
except:
return http.HttpResponseServerError()
utils.register_accounting(checkcode, referrer, ticket, user)
user = profile.authenticate()
self.send_connect_signal(request, user, profile, client)
self.login(request, user)
self.send_login_signal(request, user, profile, client)
self.delete_session_data(request)
# added by me
graph = request.facebook.graph
fb_profile = graph.get_object("me")
user.first_name = fb_profile['first_name']
user.save()
#
return HttpResponseRedirect(self.get_next(request))
let me take a stab at it. From where your code is it appears right above it you're killing the session self.delete_session_data(request). This might take away the session key or auth token. Try your code above that line.
It seems like you may have an AnonymousUser object in request.user when you access request.facebook.graph. Check to see if your user is_authenticated (more docs on AnonymousUser):
request.user.is_authenticated()
Another thing to play with is pdb from inside the dev server (manage.py runserver). The easiest way to use it is by using this line of code to put in a break point just before your code is bombing out:
import pdb; pdb.set_trace()
That will give you a prompt where you can look around at variables in context.

Categories