Skip to content

Commit

Permalink
Add ORCID id_token validation
Browse files Browse the repository at this point in the history
  • Loading branch information
matkaczmarek committed Sep 25, 2024
1 parent bffb97e commit 9e4da39
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
33 changes: 33 additions & 0 deletions physionet-django/user/validators.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import re
import requests
import jwt
import json

from django.conf import settings
from django.contrib.auth.validators import UnicodeUsernameValidator
Expand Down Expand Up @@ -216,6 +219,36 @@ def validate_orcid_token(value):
if not re.fullmatch(r'^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$', value):
raise ValidationError('ORCID token is not in expected format.')

def validate_orcid_id_token(token):
"""
When openid scope is enabled then ORCID returns
access_token and signed id_token, this function validates id_token signature
"""

jwks_url = "https://sandbox.orcid.org/oauth/jwks" # ORCID Sandbox JWKS URL
jwks = requests.get(jwks_url).json()
headers = jwt.get_unverified_header(token)

public_keys = {}
for jwk in jwks['keys']:
kid = jwk['kid']
public_keys[kid] = jwt.algorithms.RSAAlgorithm.from_jwk(json.dumps(jwk))

rsa_key = public_keys[headers['kid']]
if rsa_key is None:
raise ValidationError('ORCID id_token is invalid.')

try:
jwt.decode(
token,
rsa_key,
algorithms=['RS256'],
audience=settings.ORCID_CLIENT_ID,
issuer=settings.ORCID_DOMAIN
)
except jwt.InvalidTokenError as e:
raise ValidationError('ORCID id_token is invalid.')

def validate_orcid_id(value):
"""
Validation to verify the ID returned during
Expand Down
3 changes: 2 additions & 1 deletion physionet-django/user/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ def auth_orcid_login(request):

auth_login(request, user, backend='user.backends.OrcidAuthBackend')

return redirect('home')
return redirect('login')


def _fetch_and_validate_token(request, code, oauth_session):
Expand All @@ -549,6 +549,7 @@ def _fetch_and_validate_token(request, code, oauth_session):

try:
validators.validate_orcid_token(token['access_token'])
validators.validate_orcid_id_token(token['id_token'])
return True, token
except ValidationError:
messages.error(request, 'Validation Error: ORCID token validation failed.')
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ hdn-research-environment = "2.3.8"
django-oauth-toolkit = "^2.2.0"
django-cors-headers = "^3.14.0"
urllib3 = "^1.26.19"
pyjwt = "^2.9.0"

[tool.poetry.dev-dependencies]
coverage = "^7.2.3"
Expand Down

0 comments on commit 9e4da39

Please sign in to comment.