Skip to content

Commit

Permalink
Add OpenID Connect Token authenticator
Browse files Browse the repository at this point in the history
Signed-off-by: Patrick Uiterwijk <puiterwijk@redhat.com>
  • Loading branch information
puiterwijk committed Apr 16, 2017
1 parent d717c05 commit 9c2f03d
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 0 deletions.
61 changes: 61 additions & 0 deletions custodia/httpd/authenticators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from cryptography.hazmat.primitives import constant_time

import requests

from custodia import log
from custodia.plugin import HTTPAuthenticator, PluginOption

Expand Down Expand Up @@ -131,3 +133,62 @@ def handle(self, request):
self.audit_svc_access(log.AUDIT_SVC_AUTH_FAIL,
request['client_id'], dn)
return False


class OpenIDCTokenAuth(HTTPAuthenticator):
token_info_url = PluginOption(str, None,
'URL for getting token information')
client_id = PluginOption(str, None,
'Client ID for verifying tokens')
client_secret = PluginOption(str, None,
'Client Secret for verifying tokens')
scope = PluginOption(str, 'custodia', 'OAuth2 scope to require')

def _get_token_info(self, token):
return requests.post(self.token_info_url,
data={'client_id': self.client_id,
'client_secret': self.client_secret,
'token': token,
'token_type_hint': 'Bearer'}).json()

def handle(self, request):
token = None
if 'Authorization' in request['headers']:
hdr = request['headers']['Authorization']
if hdr.startswith('Bearer '):
self.logger.debug('Bearer token provided in header')
token = hdr[len('Bearer '):]
else:
self.logger.debug('Unrecognized Authorization header')
return False
elif request.get('access_token'):
self.logger.debug('Token provided in form')
token = request.get('access_token')
else:
self.logger.debug('Missing any credentials in request')
return False

if not token:
self.logger.debug('No token')
return False

try:
tokeninfo = self._get_token_info(token)
except:
self.logger.debug('Error getting token information',
exc_info=True)
return False

aud = tokeninfo['aud']
if isinstance(aud, list) and self.client_id not in aud:
self.logger.debug('My client ID not in audience list')
return False
elif self.client_id != aud:
self.logger.debug('Client ID is not audience')
return False

if self.scope not in tokeninfo['scope'].split(' '):
self.logger.debug('Required scope not found')
return False

return True
5 changes: 5 additions & 0 deletions docs/source/plugins/authenticators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ Authenticators
:undoc-members:
:show-inheritance:

.. autoclass:: custodia.httpd.authenticators.OpenIDCTokenAuth
:members:
:undoc-members:
:show-inheritance:

1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def run(self):
'SimpleAuthKeys = custodia.httpd.authenticators:SimpleAuthKeys',
('SimpleClientCertAuth = '
'custodia.httpd.authenticators:SimpleClientCertAuth'),
'OIDCTokenAuth = custodia.httpd.authenticators:OpenIDCTokenAuth',
]

custodia_authorizers = [
Expand Down

0 comments on commit 9c2f03d

Please sign in to comment.