|
@ -6,6 +6,7 @@ import os |
|
|
import base64 |
|
|
import base64 |
|
|
|
|
|
|
|
|
from odoo import http |
|
|
from odoo import http |
|
|
|
|
|
from odoo.http import request |
|
|
import werkzeug |
|
|
import werkzeug |
|
|
|
|
|
|
|
|
from .. api import resource |
|
|
from .. api import resource |
|
@ -104,7 +105,7 @@ class Main(http.Controller): |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
@http.route('/.well-known/openid-configuration', auth='public', type='http') |
|
|
@http.route('/.well-known/openid-configuration', auth='public', type='http') |
|
|
def metadata(self, req, **query): |
|
|
|
|
|
|
|
|
def metadata(self, **query): |
|
|
base_url = http.request.httprequest.host_url |
|
|
base_url = http.request.httprequest.host_url |
|
|
data = { |
|
|
data = { |
|
|
'issuer': base_url, |
|
|
'issuer': base_url, |
|
@ -122,14 +123,14 @@ class Main(http.Controller): |
|
|
return json.dumps(data) |
|
|
return json.dumps(data) |
|
|
|
|
|
|
|
|
@http.route('/oauth/jwks', auth='public', type='http') |
|
|
@http.route('/oauth/jwks', auth='public', type='http') |
|
|
def jwks(self, req, **query): |
|
|
|
|
|
|
|
|
def jwks(self, **query): |
|
|
keyset = jwk.JWKSet() |
|
|
keyset = jwk.JWKSet() |
|
|
keyset.add(self.__get_id_token_jwk(req)) |
|
|
|
|
|
|
|
|
keyset.add(self.__get_id_token_jwk(request)) |
|
|
return keyset.export(private_keys=False) |
|
|
return keyset.export(private_keys=False) |
|
|
|
|
|
|
|
|
@resource('/oauth/userinfo', method='GET') |
|
|
@resource('/oauth/userinfo', method='GET') |
|
|
def userinfo(self, req, **query): |
|
|
|
|
|
user = req.env.user |
|
|
|
|
|
|
|
|
def userinfo(self, **query): |
|
|
|
|
|
user = request.env.user |
|
|
values = { |
|
|
values = { |
|
|
'sub': str(user.id), |
|
|
'sub': str(user.id), |
|
|
# Needed in case the client is another Odoo instance |
|
|
# Needed in case the client is another Odoo instance |
|
@ -141,22 +142,22 @@ class Main(http.Controller): |
|
|
return values |
|
|
return values |
|
|
|
|
|
|
|
|
@resource('/oauth/clientinfo', method='GET', auth='client') |
|
|
@resource('/oauth/clientinfo', method='GET', auth='client') |
|
|
def clientinfo(self, req, **query): |
|
|
|
|
|
client = req.env['galicea_openid_connect.client'].browse(req.context['client_id']) |
|
|
|
|
|
|
|
|
def clientinfo(self, **query): |
|
|
|
|
|
client = request.env['galicea_openid_connect.client'].browse(request.context['client_id']) |
|
|
return { |
|
|
return { |
|
|
'name': client.name |
|
|
'name': client.name |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@http.route('/oauth/authorize', auth='public', type='http', csrf=False) |
|
|
@http.route('/oauth/authorize', auth='public', type='http', csrf=False) |
|
|
def authorize(self, req, **query): |
|
|
|
|
|
|
|
|
def authorize(self, **query): |
|
|
# First, validate client_id and redirect_uri params. |
|
|
# First, validate client_id and redirect_uri params. |
|
|
try: |
|
|
try: |
|
|
client = self.__validate_client(req, **query) |
|
|
|
|
|
redirect_uri = self.__validate_redirect_uri(client, req, **query) |
|
|
|
|
|
|
|
|
client = self.__validate_client(request, **query) |
|
|
|
|
|
redirect_uri = self.__validate_redirect_uri(client, request, **query) |
|
|
except OAuthException as e: |
|
|
except OAuthException as e: |
|
|
# If those are not valid, we must not redirect back to the client |
|
|
# If those are not valid, we must not redirect back to the client |
|
|
# - instead, we display a message to the user |
|
|
# - instead, we display a message to the user |
|
|
return req.render('galicea_openid_connect.error', {'exception': e}) |
|
|
|
|
|
|
|
|
return request.render('galicea_openid_connect.error', {'exception': e}) |
|
|
|
|
|
|
|
|
scopes = query['scope'].split(' ') if query.get('scope') else [] |
|
|
scopes = query['scope'].split(' ') if query.get('scope') else [] |
|
|
is_openid_request = 'openid' in scopes |
|
|
is_openid_request = 'openid' in scopes |
|
@ -194,7 +195,7 @@ class Main(http.Controller): |
|
|
if not response_mode: |
|
|
if not response_mode: |
|
|
response_mode = 'query' if response_type == 'code' else 'fragment' |
|
|
response_mode = 'query' if response_type == 'code' else 'fragment' |
|
|
|
|
|
|
|
|
user = req.env.user |
|
|
|
|
|
|
|
|
user = request.env.user |
|
|
# In case user is not logged in, we redirect to the login page and come back |
|
|
# In case user is not logged in, we redirect to the login page and come back |
|
|
needs_login = user.login == 'public' |
|
|
needs_login = user.login == 'public' |
|
|
# Also if they didn't authenticate recently enough |
|
|
# Also if they didn't authenticate recently enough |
|
@ -227,10 +228,10 @@ class Main(http.Controller): |
|
|
'exp': int(time.time()) + 60 |
|
|
'exp': int(time.time()) + 60 |
|
|
} |
|
|
} |
|
|
payload.update(extra_claims) |
|
|
payload.update(extra_claims) |
|
|
key = self.__get_authorization_code_jwk(req) |
|
|
|
|
|
|
|
|
key = self.__get_authorization_code_jwk(request) |
|
|
response_params['code'] = jwt_encode(payload, key) |
|
|
response_params['code'] = jwt_encode(payload, key) |
|
|
if 'token' in response_types: |
|
|
if 'token' in response_types: |
|
|
access_token = req.env['galicea_openid_connect.access_token'].sudo().retrieve_or_create( |
|
|
|
|
|
|
|
|
access_token = request.env['galicea_openid_connect.access_token'].sudo().retrieve_or_create( |
|
|
user.id, |
|
|
user.id, |
|
|
client.id |
|
|
client.id |
|
|
).token |
|
|
).token |
|
@ -243,7 +244,7 @@ class Main(http.Controller): |
|
|
#extra_claims['at_hash'] = base64.urlsafe_b64encode(at_hash[:16]).strip('=') |
|
|
#extra_claims['at_hash'] = base64.urlsafe_b64encode(at_hash[:16]).strip('=') |
|
|
extra_claims['at_hash'] = base64.urlsafe_b64encode(at_hash[:16]) |
|
|
extra_claims['at_hash'] = base64.urlsafe_b64encode(at_hash[:16]) |
|
|
if 'id_token' in response_types: |
|
|
if 'id_token' in response_types: |
|
|
response_params['id_token'] = self.__create_id_token(req, user.id, client, extra_claims) |
|
|
|
|
|
|
|
|
response_params['id_token'] = self.__create_id_token(request, user.id, client, extra_claims) |
|
|
|
|
|
|
|
|
return self.__redirect(redirect_uri, response_params, response_mode) |
|
|
return self.__redirect(redirect_uri, response_params, response_mode) |
|
|
|
|
|
|
|
|