[IMP] generic oauth providers

bzr revid: al@openerp.com-20120815180913-2y889mtgg15v5lqb
This commit is contained in:
Antony Lesuisse 2012-08-15 20:09:13 +02:00
parent eb50d91461
commit 334bc0ff66
9 changed files with 83 additions and 85 deletions

View File

@ -1,3 +1,3 @@
import controllers import controllers
import auth_oauth
import res_users import res_users
import oauth_providers

View File

@ -30,10 +30,10 @@
'website': 'http://www.openerp.com', 'website': 'http://www.openerp.com',
'depends': ['base', 'web'], 'depends': ['base', 'web'],
'data': [ 'data': [
'oauth_providers_data.xml' 'auth_oauth_data.xml'
], ],
'update_xml': [ 'update_xml': [
'oauth_providers.xml' 'auth_oauth_view.xml'
], ],
'js': [ 'js': [
'static/src/js/auth_oauth.js', 'static/src/js/auth_oauth.js',

View File

@ -1,10 +1,9 @@
from openerp.osv import osv, fields from openerp.osv import osv, fields
class oauth_providers(osv.osv): class auth_oauth_providers(osv.osv):
"""Class defining the configuration values of an OAuth2 provider""" """Class defining the configuration values of an OAuth2 provider"""
_name = 'oauth.providers' _name = 'auth.oauth.provider'
_description = 'OAuth2 provider' _description = 'OAuth2 provider'
_order = 'name' _order = 'name'
@ -15,14 +14,8 @@ class oauth_providers(osv.osv):
'scope' : fields.char('Scope'), # OAUth user data desired to access 'scope' : fields.char('Scope'), # OAUth user data desired to access
'validation_endpoint' : fields.char('Validation URL'), # OAuth provider URL to validate tokens 'validation_endpoint' : fields.char('Validation URL'), # OAuth provider URL to validate tokens
'data_endpoint' : fields.char('Data URL'), 'data_endpoint' : fields.char('Data URL'),
'redirect_uris' : fields.char('Redirect URIs'),
'icon_url' : fields.char('Icon'), # URL of the icon's provider 'icon_url' : fields.char('Icon'), # URL of the icon's provider
'active' : fields.boolean('Active'), 'active' : fields.boolean('Active'),
'sequence' : fields.integer(), 'sequence' : fields.integer(),
} }
_sql_constraints = [
('name', 'unique(name)', 'The name of the OAuth provider must be unique')
]
oauth_providers()

View File

@ -1,25 +1,23 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<openerp> <openerp>
<data noupdate="1"> <data noupdate="1">
<record id="1" model="oauth.providers"> <record id="provider_google" model="auth.oauth.provider">
<field name="name">Google OAuth2</field> <field name="name">Google OAuth2</field>
<field name="client_id">108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com</field> <field name="client_id">108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.googleusercontent.com</field>
<field name="auth_endpoint">https://accounts.google.com/o/oauth2/auth</field> <field name="auth_endpoint">https://accounts.google.com/o/oauth2/auth</field>
<field name="scope">https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile</field> <field name="scope">https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile</field>
<field name="validation_endpoint">https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=</field> <field name="validation_endpoint">https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=</field>
<field name="data_endpoint">https://www.googleapis.com/oauth2/v1/userinfo?access_token=</field> <field name="data_endpoint">https://www.googleapis.com/oauth2/v1/userinfo?access_token=</field>
<field name="redirect_uris">https://localhost/</field>
<field name="active">True</field> <field name="active">True</field>
</record> </record>
<record id="2" model="oauth.providers"> <record id="provider_twitter" model="auth.oauth.provider">
<field name="name">Twitter OAuth2</field> <field name="name">Twitter OAuth2</field>
<field name="client_id">108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.twitterusercontent.com</field> <field name="client_id">108010644258-duuhmp6pu7li4tsmnqg7j9rvdeklg0ki.apps.twitterusercontent.com</field>
<field name="auth_endpoint">https://api.twitter.com/oauth/request_token</field> <field name="auth_endpoint">https://api.twitter.com/oauth/request_token</field>
<field name="scope"></field> <field name="scope"></field>
<field name="validation_endpoint">https://api.twitter.com/oauth/authorize?oauth_token=</field> <field name="validation_endpoint">https://api.twitter.com/oauth/authorize?oauth_token=</field>
<field name="data_endpoint"></field> <field name="data_endpoint"></field>
<field name="redirect_uris">https://localhost/</field>
<field name="active">True</field> <field name="active">True</field>
</record> </record>
</data> </data>
</openerp> </openerp>

View File

@ -1,36 +1,31 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<openerp> <openerp>
<data> <data>
<menuitem id="menu_oauth_provider" parent="base.menu_administration" name="OAuth2 Settings" action="" sequence="100" />
<record model="ir.ui.view" id="view_oauth_provider_form"> <record model="ir.ui.view" id="view_oauth_provider_form">
<field name="name">oauth.provider.form</field> <field name="name">auth.oauth.provider.form</field>
<field name="model">oauth.providers</field> <field name="model">auth.oauth.provider</field>
<field name="type">form</field> <field name="type">form</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="arch" version="7.0"> <form string="arch" version="7.0">
<header>
</header>
<sheet> <sheet>
<group name="info1" string="" col=""> <group>
<field name="name" /> <field name="name" />
<field name="client_id" /> <field name="client_id" />
<field name="active" /> <field name="active" />
</group> </group>
<group name="info2" string="" col=""> <group>
<field name="auth_endpoint" /> <field name="auth_endpoint" />
<field name="scope" /> <field name="scope" />
<field name="validation_endpoint" /> <field name="validation_endpoint" />
<field name="data_endpoint" /> <field name="data_endpoint" />
<field name="redirect_uris" />
</group> </group>
</sheet> </sheet>
</form> </form>
</field> </field>
</record> </record>
<record model="ir.ui.view" id="view_oauth_provider_list"> <record model="ir.ui.view" id="view_oauth_provider_list">
<field name="name">oauth.provider.list</field> <field name="name">auth.oauth.provider.list</field>
<field name="model">oauth.providers</field> <field name="model">auth.oauth.provider</field>
<field name="type">tree</field> <field name="type">tree</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="arch" version="7.0"> <tree string="arch" version="7.0">
@ -42,10 +37,10 @@
</record> </record>
<record model="ir.actions.act_window" id="action_oauth_provider"> <record model="ir.actions.act_window" id="action_oauth_provider">
<field name="name">Providers</field> <field name="name">Providers</field>
<field name="res_model">oauth.providers</field> <field name="res_model">auth.oauth.provider</field>
<field name="view_type">form</field> <field name="view_type">form</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<menuitem id="menu_oauth_providers" parent="menu_oauth_provider" name="OAuth2 Providers" action="action_oauth_provider" sequence="0" /> <menuitem id="menu_oauth_providers" parent="base.menu_users" name="OAuth Providers" action="action_oauth_provider" sequence="30"/>
</data> </data>
</openerp> </openerp>

View File

@ -12,12 +12,13 @@ _logger = logging.getLogger(__name__)
class OAuthController(openerpweb.Controller): class OAuthController(openerpweb.Controller):
_cp_path = '/auth_oauth' _cp_path = '/auth_oauth'
@openerpweb.jsonrequest
def list_providers(self, req, dbname): def list_providers(self, req, dbname):
#dbname = kw.get("state") registry = openerp.modules.registry.RegistryManager.get(dbname)
#registry = openerp.modules.registry.RegistryManager.get(dbname) with registry.cursor() as cr:
#with registry.cursor() as cr: providers = registry.get('auth.oauth.provider')
# dsfasdf l = providers.read(cr, 1, providers.search(cr, 1, []))
pass return l
@openerpweb.httprequest @openerpweb.httprequest
def signin(self, req, **kw): def signin(self, req, **kw):
@ -26,18 +27,18 @@ class OAuthController(openerpweb.Controller):
with registry.cursor() as cr: with registry.cursor() as cr:
try: try:
u = registry.get('res.users') u = registry.get('res.users')
credentials = u.auth_oauth(cr, 1, kw) credentials = u.auth_oauth(cr, 1, {}, kw)
cr.commit() cr.commit()
return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials) return openerp.addons.web.controllers.main.login_and_redirect(req, *credentials)
except AttributeError: except AttributeError:
# auth_signup is not installed # auth_signup is not installed
_logger.exception("attribute error") _logger.error("auth_signup not installed on database %s: oauth sign up cancelled."%dbname)
url = "/#action=auth_signup&error=1" url = "/#action=login&oauth_error=1"
except Exception,e: except Exception,e:
# signup error # signup error
_logger.exception('oops') _logger.exception('oops')
url = "/#action=auth_signup&error=2" url = "/#action=login&oauth_error=2"
return openerp.addons.web.controllers.main.set_cookie_and_redirect(req, "/") return openerp.addons.web.controllers.main.set_cookie_and_redirect(req, url)
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -1,5 +1,6 @@
import logging import logging
import urllib
import urllib2 import urllib2
import simplejson import simplejson
@ -10,40 +11,36 @@ from openerp.osv import osv, fields
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class res_users(osv.Model): class res_users(osv.Model):
_inherit = 'res.users' _inherit = 'res.users'
_columns = { _columns = {
'oauth_provider': fields.char('OAuth Provider', size=1024), 'oauth_provider': fields.many2one('auth.oauth.provider','OAuth Provider'),
'oauth_uid': fields.char('OAuth User ID', size=256, 'oauth_uid': fields.char('OAuth User ID', help="Oauth Provider user_id"),
help="Used for disambiguation in case of a shared OpenID URL"), 'oauth_access_token': fields.char('OAuth Token', readonly=True),
'oauth_access_token': fields.char('OAuth Token',
readonly=True),
} }
def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None): def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None):
url = endpoint + access_token params = urllib.urlencode({'access_token':access_token})
url = endpoint + '?' + params
f = urllib2.urlopen(url) f = urllib2.urlopen(url)
response = f.read() response = f.read()
return simplejson.loads(response) return simplejson.loads(response)
def auth_oauth_fetch_user_validation(self, cr, uid, access_token, context=None): def auth_oauth_fetch_user_validation(self, cr, uid, access_token, context=None):
endpoint = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=' endpoint = 'https://www.googleapis.com/oauth2/v1/tokeninfo'
return self.auth_oauth_rpc(cr, uid, endpoint, access_token) return self.auth_oauth_rpc(cr, uid, endpoint, access_token)
def auth_oauth_fetch_user_data(self, cr, uid, access_token, context=None): def auth_oauth_fetch_user_data(self, cr, uid, access_token, context=None):
endpoint = 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' endpoint = 'https://www.googleapis.com/oauth2/v1/userinfo'
return self.auth_oauth_rpc(cr, uid, endpoint, access_token) return self.auth_oauth_rpc(cr, uid, endpoint, access_token)
def auth_oauth(self, cr, uid, params, context=None): def auth_oauth(self, cr, uid, config, params, context=None):
# Advice by Google (to avoid Confused Deputy Problem) # Advice by Google (to avoid Confused Deputy Problem)
# if validation.audience != OUR_CLIENT_ID: # if validation.audience != OUR_CLIENT_ID:
# abort() # abort()
# else: # else:
# continue with the process # continue with the process
access_token = params.get('access_token') access_token = params.get('access_token')
validation = self.auth_oauth_fetch_user_validation(cr, uid, access_token, context=context) validation = self.auth_oauth_fetch_user_validation(cr, uid, access_token, context=context)
if validation.get("error"): if validation.get("error"):
raise openerp.exceptions.AccessDenied raise openerp.exceptions.AccessDenied
@ -51,8 +48,7 @@ class res_users(osv.Model):
login = validation['email'] login = validation['email']
oauth_uid = validation['user_id'] oauth_uid = validation['user_id']
name = self.auth_oauth_fetch_user_data(cr, uid, access_token)['name'] name = self.auth_oauth_fetch_user_data(cr, uid, access_token)['name']
credentials = (cr.dbname, login, access_token)
r = (cr.dbname, login, oauth_uid)
res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)]) res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)])
if res: if res:
@ -69,8 +65,7 @@ class res_users(osv.Model):
'active': True, 'active': True,
} }
self.auth_signup_create(cr, uid, new_user) self.auth_signup_create(cr, uid, new_user)
return r return credentials
def check(self, db, uid, passwd): def check(self, db, uid, passwd):
try: try:
@ -93,5 +88,4 @@ class res_users(osv.Model):
finally: finally:
cr.close() cr.close()
res_users()
# #

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve"> <templates id="template" xml:space="preserve">
<t t-name="auth_oauth.Login.button">
<t t-extend="Login"> <t t-foreach="widget.oauth_providers" t-as="p">
<t t-jquery=".oe_login_pane form ul" t-operation="after"> <a href="#" class="oe_oauth_sign_in" t-att-data-index="p_index">
<ul class="oe_login_oauth"> Login with <t t-esc="p.name"/> icon <t t-esc="p.icon_url"/>
<li>OR</li> </a>
<li><a href="#">Login with Google</a></li> <br/>
</ul>
</t>
</t> </t>
</t>
</templates> </templates>