[IMP] generic oauth providers
bzr revid: al@openerp.com-20120815180913-2y889mtgg15v5lqb
This commit is contained in:
parent
eb50d91461
commit
334bc0ff66
|
@ -1,3 +1,3 @@
|
||||||
import controllers
|
import controllers
|
||||||
|
import auth_oauth
|
||||||
import res_users
|
import res_users
|
||||||
import oauth_providers
|
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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()
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
@ -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>
|
||||||
|
|
Loading…
Reference in New Issue