Fix token introspection "aud" and "client_id" response
Based on the OAuth 2.0 Token Introspection spec the "aud" field should be based on the token. Previously "aud" was populated with the id of the client making the introspection request which seems wrong. This changes the endpoint to return the value from the token. The "client_id" field is then changed to return the client id for the client that originally requested the token rather than returning the "aud" value from the token. From the spec https://tools.ietf.org/html/rfc7662: client_id OPTIONAL. Client identifier for the OAuth 2.0 client that requested this token. aud OPTIONAL. Service-specific string identifier or list of string identifiers representing the intended audience for this token, as defined in JWT [RFC7519].
This commit is contained in:
parent
50733f8135
commit
b1e994aa7e
2 changed files with 11 additions and 10 deletions
|
@ -18,6 +18,7 @@ class TokenIntrospectionEndpoint(object):
|
|||
def __init__(self, request):
|
||||
self.request = request
|
||||
self.params = {}
|
||||
self.token = None
|
||||
self.id_token = None
|
||||
self.client = None
|
||||
self._extract_params()
|
||||
|
@ -37,19 +38,19 @@ class TokenIntrospectionEndpoint(object):
|
|||
logger.debug('[Introspection] No token provided')
|
||||
raise TokenIntrospectionError()
|
||||
try:
|
||||
token = Token.objects.get(access_token=self.params['token'])
|
||||
self.token = Token.objects.get(access_token=self.params['token'])
|
||||
except Token.DoesNotExist:
|
||||
logger.debug('[Introspection] Token does not exist: %s', self.params['token'])
|
||||
raise TokenIntrospectionError()
|
||||
if token.has_expired():
|
||||
if self.token.has_expired():
|
||||
logger.debug('[Introspection] Token is not valid: %s', self.params['token'])
|
||||
raise TokenIntrospectionError()
|
||||
if not token.id_token:
|
||||
if not self.token.id_token:
|
||||
logger.debug('[Introspection] Token not an authentication token: %s',
|
||||
self.params['token'])
|
||||
raise TokenIntrospectionError()
|
||||
|
||||
self.id_token = token.id_token
|
||||
self.id_token = self.token.id_token
|
||||
audience = self.id_token.get('aud')
|
||||
if not audience:
|
||||
logger.debug('[Introspection] No audience found for token: %s', self.params['token'])
|
||||
|
@ -74,10 +75,9 @@ class TokenIntrospectionEndpoint(object):
|
|||
raise TokenIntrospectionError()
|
||||
|
||||
def create_response_dic(self):
|
||||
response_dic = dict((k, self.id_token[k]) for k in ('sub', 'exp', 'iat', 'iss'))
|
||||
response_dic = dict((k, self.id_token[k]) for k in ('aud', 'sub', 'exp', 'iat', 'iss'))
|
||||
response_dic['active'] = True
|
||||
response_dic['client_id'] = self.id_token.get('aud')
|
||||
response_dic['aud'] = self.client.client_id
|
||||
response_dic['client_id'] = self.token.client.client_id
|
||||
|
||||
response_dic = run_processing_hook(response_dic,
|
||||
'OIDC_INTROSPECTION_PROCESSING_HOOK',
|
||||
|
|
|
@ -30,16 +30,17 @@ class IntrospectionTestCase(TestCase):
|
|||
call_command('creatersakey')
|
||||
self.factory = RequestFactory()
|
||||
self.user = create_fake_user()
|
||||
self.aud = 'testaudience'
|
||||
self.client = create_fake_client(response_type='id_token token')
|
||||
self.resource = create_fake_client(response_type='id_token token')
|
||||
self.resource.scope = ['token_introspection', self.client.client_id]
|
||||
self.resource.scope = ['token_introspection', self.aud]
|
||||
self.resource.save()
|
||||
self.token = create_fake_token(self.user, self.client.scope, self.client)
|
||||
self.token.access_token = str(random.randint(1, 999999)).zfill(6)
|
||||
self.now = time.time()
|
||||
with patch('oidc_provider.lib.utils.token.time.time') as time_func:
|
||||
time_func.return_value = self.now
|
||||
self.token.id_token = create_id_token(self.token, self.user, self.client.client_id)
|
||||
self.token.id_token = create_id_token(self.token, self.user, self.aud)
|
||||
self.token.save()
|
||||
|
||||
def _assert_inactive(self, response):
|
||||
|
@ -50,7 +51,7 @@ class IntrospectionTestCase(TestCase):
|
|||
self.assertEqual(response.status_code, 200)
|
||||
expected_content = {
|
||||
'active': True,
|
||||
'aud': self.resource.client_id,
|
||||
'aud': self.aud,
|
||||
'client_id': self.client.client_id,
|
||||
'sub': str(self.user.pk),
|
||||
'iat': int(self.now),
|
||||
|
|
Loading…
Reference in a new issue