Skip to content

Commit 9e4d9a1

Browse files
committed
feat: make AuthSettings compatible with single key
1 parent b4aba47 commit 9e4d9a1

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

diracx-core/src/diracx/core/settings.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222
from botocore.config import Config
2323
from botocore.errorfactory import ClientError
2424
from cryptography.fernet import Fernet
25-
from joserfc.jws import KeySet
25+
from joserfc.jwk import KeySet, RSAKey
2626
from pydantic import (
27+
AliasChoices,
2728
AnyUrl,
2829
BeforeValidator,
2930
Field,
@@ -70,7 +71,7 @@ def __init__(self, data: str):
7071

7172

7273
def _maybe_load_keys_from_file(value: Any) -> Any:
73-
"""Load private keys from files if needed."""
74+
"""Load jwks from files if needed."""
7475
if isinstance(value, str):
7576
# If the value is a string, we need to check if it is a JSON string or a file URL
7677
if not (value.strip().startswith("{") or value.startswith("[")):
@@ -80,13 +81,25 @@ def _maybe_load_keys_from_file(value: Any) -> Any:
8081
raise ValueError("Only file:// URLs are supported")
8182
if url.path is None:
8283
raise ValueError("No path specified")
83-
return Path(url.path).read_text()
84-
84+
value = Path(url.path).read_text()
85+
86+
if isinstance(value, str) and value.strip().startswith("-----BEGIN"):
87+
return json.dumps(
88+
KeySet(
89+
keys=[
90+
RSAKey.import_key(
91+
value, # type: ignore
92+
parameters={"key_ops": ["sign", "verify"]}, # type: ignore
93+
)
94+
]
95+
).as_dict(private=True)
96+
)
8597
return value
8698

8799

88100
TokenSigningKeyStore = Annotated[
89-
_TokenSigningKeyStore, BeforeValidator(_maybe_load_keys_from_file)
101+
_TokenSigningKeyStore,
102+
BeforeValidator(_maybe_load_keys_from_file),
90103
]
91104

92105

@@ -138,7 +151,9 @@ def create(cls) -> Self:
138151
class AuthSettings(ServiceSettingsBase):
139152
"""Settings for the authentication service."""
140153

141-
model_config = SettingsConfigDict(env_prefix="DIRACX_SERVICE_AUTH_")
154+
model_config = SettingsConfigDict(
155+
env_prefix="DIRACX_SERVICE_AUTH_", validate_by_name=True
156+
)
142157

143158
dirac_client_id: str = "myDIRACClientID"
144159
# TODO: This should be taken dynamically
@@ -151,7 +166,13 @@ class AuthSettings(ServiceSettingsBase):
151166
state_key: FernetKey
152167

153168
token_issuer: str
154-
token_keystore: TokenSigningKeyStore
169+
token_keystore: TokenSigningKeyStore = Field(
170+
validation_alias=AliasChoices(
171+
"token_keystore",
172+
"DIRACX_SERVICE_AUTH_TOKEN_KEYSTORE",
173+
"DIRACX_SERVICE_AUTH_TOKEN_KEY",
174+
)
175+
)
155176
token_allowed_algorithms: list[str] = ["RS256", "EdDSA"] # noqa: S105
156177
access_token_expire_minutes: int = 20
157178
refresh_token_expire_minutes: int = 60

diracx-logic/src/diracx/logic/auth/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from cachetools import TTLCache
1010
from cryptography.fernet import Fernet
1111
from joserfc import jwt
12-
from joserfc.jws import KeySet
12+
from joserfc.jwk import KeySet
1313
from joserfc.jwt import Claims, JWTClaimsRegistry
1414
from typing_extensions import TypedDict
1515
from uuid_utils import UUID

diracx-routers/tests/auth/test_standard.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
import jwt
1313
import pytest
1414
from cryptography.fernet import Fernet
15-
from joserfc.jwk import RSAKey, OKPKey
16-
from joserfc.jws import KeySet
15+
from joserfc.jwk import RSAKey, OKPKey, KeySet
1716
from joserfc.errors import UnsupportedKeyOperationError
1817
from pytest_httpx import HTTPXMock
1918
from uuid_utils import uuid7

0 commit comments

Comments
 (0)