-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[REF] Manually verify ID token using PyJWT instead of google_auth (#139)
* manually verify ID token using PyJWT instead of google_auth * update issuer and keys URL for auth0, update comments * update authorization endpoint for oauth2_scheme docs * refactor out token extraction from verification * update tests * remove google-auth from dependencies * update docstring * refactor our JKWS client into a constant * add positive unit test for verify_token * remove print statement
- Loading branch information
Showing
7 changed files
with
94 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,7 @@ | ||
import pytest | ||
from fastapi import HTTPException | ||
from google.oauth2 import id_token | ||
|
||
from app.api.security import verify_and_extract_token | ||
from app.api.security import extract_token, verify_token | ||
|
||
|
||
def test_missing_client_id_raises_error_when_auth_enabled( | ||
|
@@ -38,10 +37,12 @@ def test_missing_client_id_ignored_when_auth_disabled(monkeypatch, test_app): | |
"invalid_token", | ||
["Bearer faketoken", "Bearer", "faketoken", "fakescheme faketoken"], | ||
) | ||
def test_invalid_token_raises_error(invalid_token): | ||
def test_invalid_token_raises_error(monkeypatch, invalid_token): | ||
"""Test that an invalid token raises an error from the verification process.""" | ||
monkeypatch.setattr("app.api.security.CLIENT_ID", "foo.id") | ||
|
||
with pytest.raises(HTTPException) as exc_info: | ||
verify_and_extract_token(invalid_token) | ||
verify_token(invalid_token) | ||
|
||
assert exc_info.value.status_code == 401 | ||
assert "Invalid token" in exc_info.value.detail | ||
|
@@ -53,7 +54,7 @@ def test_invalid_token_raises_error(invalid_token): | |
) | ||
def test_query_with_malformed_auth_header_fails( | ||
test_app, | ||
set_mock_verify_and_extract_token, | ||
set_mock_verify_token, | ||
enable_auth, | ||
invalid_auth_header, | ||
monkeypatch, | ||
|
@@ -72,33 +73,38 @@ def test_query_with_malformed_auth_header_fails( | |
assert response.status_code == 403 | ||
|
||
|
||
def test_verified_token_returned_without_auth_scheme(monkeypatch, enable_auth): | ||
def test_token_returned_without_auth_scheme(monkeypatch, enable_auth): | ||
""" | ||
Test that when a token is valid, verify_token correctly returns the token with the authorization scheme stripped. | ||
""" | ||
mock_valid_token = "Bearer foo" | ||
mock_id_info = { | ||
"iss": "https://accounts.google.com", | ||
"azp": "123abc.apps.googleusercontent.com", | ||
"aud": "123abc.apps.googleusercontent.com", | ||
"sub": "1234567890", | ||
"email": "[email protected]", | ||
"email_verified": True, | ||
"nbf": 1730476622, | ||
"name": "Jane Doe", | ||
"picture": "https://lh3.googleusercontent.com/a/example1234567890", | ||
"given_name": "Jane", | ||
"family_name": "Doe", | ||
"iat": 1730476922, | ||
"exp": 1730480522, | ||
"jti": "123e4567-e89b", | ||
} | ||
|
||
def mock_oauth2_verify_token(param, request, client_id, **kwargs): | ||
return mock_id_info | ||
assert extract_token(mock_valid_token) == "foo" | ||
|
||
|
||
def test_valid_token_does_not_error_out(monkeypatch, enable_auth): | ||
""" | ||
Test that when a valid token is passed to verify_token, the token is returned without errors. | ||
""" | ||
|
||
def mock_get_signing_key_from_jwt(*args, **kwargs): | ||
# NOTE: The actual get_signing_key_from_jwt method should return a key object | ||
return "signingkey" | ||
|
||
def mock_jwt_decode(*args, **kwargs): | ||
return { | ||
"iss": "https://myissuer.com", | ||
"aud": "123abc.myapp.com", | ||
"sub": "1234567890", | ||
"name": "John Doe", | ||
"iat": 1730476922, | ||
"exp": 1730480522, | ||
} | ||
|
||
monkeypatch.setattr("app.api.security.CLIENT_ID", "123abc.myapp.com") | ||
monkeypatch.setattr( | ||
id_token, "verify_oauth2_token", mock_oauth2_verify_token | ||
"app.api.security.JWKS_CLIENT.get_signing_key_from_jwt", | ||
mock_get_signing_key_from_jwt, | ||
) | ||
monkeypatch.setattr("app.api.security.jwt.decode", mock_jwt_decode) | ||
|
||
assert verify_and_extract_token(mock_valid_token) == "foo" | ||
assert verify_token("Bearer myvalidtoken") == "myvalidtoken" |