Hello,
I am trying multiple login methods- Twitter or Facebook.
I want to know the best practice to support multiple login methods
(multiple OAuth).
Currently, I got a problem.
I can redirect to login form of facebook or twitter.
But after I successfully logged in the OAuth providers, I can't log in my
service.
Here is my code.
In db.py, I defined two classes TwitterAccount and FacebookAccount
from gluon.contrib.login_methods.oauth20_account import OAuthAccount
class FaceBookAccount(OAuthAccount):
"""OAuth impl for Facebook"""
AUTH_URL="https://graph.facebook.com/oauth/authorize"
TOKEN_URL="https://graph.facebook.com/oauth/access_token"
user = None
graph = None
def __init__(self, g=globals()):
OAuthAccount.__init__(self, g,
FACEBOOK_CLIENT_ID,
FACEBOOK_CLIENT_SECRET,
self.AUTH_URL,
self.TOKEN_URL)
self.graph = None
def get_user(self):
if not self.accessToken():
return None
if not self.graph:
self.graph = GraphAPI((self.accessToken()))
if not self.user:
try:
self.user = self.graph.get_object("me")
except GraphAPIError:
return None
return self.user
import oauth2 as oauth
from gluon.contrib.login_methods.oauth10a_account import OAuthAccount as
OAuthAccount10a
class TwitterAccount(OAuthAccount10a):
AUTH_URL = "http://twitter.com/oauth/authorize"
TOKEN_URL = "https://twitter.com/oauth/request_token"
ACCESS_TOKEN_URL = "http://twitter.com/oauth/access_token"
def __init__(self, g=globals()):
OAuthAccount10a.__init__(self, g,
consumer_key,
consumer_secret,
self.AUTH_URL,
self.TOKEN_URL,
self.ACCESS_TOKEN_URL)
def get_user(self):
if self.accessToken() is not None:
client = oauth.Client(self.consumer, self.accessToken())
resp, content =
client.request('http://api.twitter.com/1/account/verify_credentials.json')
if resp['status'] != '200':
# cannot get user info. should check status
return None
u = json.loads(content)
return dict(username=u['screen_name'], name=u['name'],
registration_id=str(u['id']))
and then, make two instances
# TWITTER
twitter_login = TwitterAccount(globals())
# FACEBOOK
facebook_login = FaceBookAccount(globals())
# set
crud.settings.auth = None # =auth to enforce
authorization on crud
auth.settings.actions_disabled=['register','change_password','request_reset_password','profile']
auth.define_tables()
In controller,
def user():
if len(request.args) > 1:
if request.args[0] == 'login' and request.args[1] == 'facebook':
auth.settings.login_form=facebook_login
elif request.args[0] == 'login' and request.args[1] == 'twitter':
auth.settings.login_form=twitter_login
return dict(form=auth())
But it seems that I need to set 'auth_settings.login_form' in db.py before
calling auth.define_tables()
If I set
auth.settings.login_form=twitter_login
auth.define_tables()
or
auth.settings.login_form=facebook_login
auth.define_tables()
in db.py, each works well.
Is there any way to set auth.settings.login_form dynamically in controller?
I think it may impossible, because auth creates tables before knowing
proper fileds (like username).
Then, how can I set multiple login form?
Or right way to support multiple login? (except janrain)
Thank you very much.
--