Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions skeletonservice/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ class BaseConfig(object):
LIMITER_CATEGORIES = "CONFIGURE_ME"
LIMITER_URI = "CONFIGURE_ME"

# Lifetime of downscoped GCS tokens issued by the skeleton token endpoint (in minutes).
# Clients should treat tokens as expired after this many minutes. Defaults to 1 hour.
SKELETON_TOKEN_EXPIRATION_MINUTES = 60

NEUROGLANCER_URL = "https://neuroglancer-demo.appspot.com"
if os.environ.get("DAF_CREDENTIALS", None) is not None:
with open(os.environ.get("DAF_CREDENTIALS"), "r") as f:
Expand Down
6 changes: 4 additions & 2 deletions skeletonservice/datasets/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ class SkeletonResource__get_skeleton_token(Resource):
]

@staticmethod
def process(datastack_name: str, skvn: int, rids: list, verbose_level: int = 0):
def process(datastack_name: str, skvn: int, rids: list, expiration_minutes: int = 60, verbose_level: int = 0):
SkelClassVsn = SkeletonService.get_version_specific_handler(skvn)

return SkelClassVsn.get_skeleton_token_by_datastack_and_rids(
Expand All @@ -977,6 +977,7 @@ def process(datastack_name: str, skvn: int, rids: list, verbose_level: int = 0):
collapse_soma=True,
collapse_radius=7500,
skeleton_version=skvn,
expiration_minutes=expiration_minutes,
session_timestamp_=SkeletonService.get_session_timestamp(),
verbose_level_=verbose_level,
)
Expand All @@ -991,4 +992,5 @@ def post(self, datastack_name: str, skvn: int):
rids = rids[:MAX_BULK_CACHED_SKELETONS]
verbose_level = int(data.get("verbose_level", 0))
verbose_level = max(int(request.args.get("verbose_level", 0)), verbose_level)
return self.process(datastack_name, skvn, rids, verbose_level)
expiration_minutes = int(current_app.config.get("SKELETON_TOKEN_EXPIRATION_MINUTES", 60))
return self.process(datastack_name, skvn, rids, expiration_minutes, verbose_level)
17 changes: 16 additions & 1 deletion skeletonservice/datasets/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2479,6 +2479,7 @@ def get_skeleton_token_by_datastack_and_rids(
collapse_soma: bool,
collapse_radius: int,
skeleton_version: int = 0,
expiration_minutes: int = 60,
session_timestamp_: str = "not_provided",
verbose_level_: int = 0,
):
Expand All @@ -2495,11 +2496,14 @@ def get_skeleton_token_by_datastack_and_rids(
(V{HIGHEST_SKELETON_VERSION}). If a different skeleton_version is requested,
it will be overridden to HIGHEST_SKELETON_VERSION.

The token lifetime is capped at expiration_minutes (server-side config, default 60).

Returns a dict:
"token": short-lived Bearer token
"token_type": "Bearer"
"expiry": ISO-8601 expiry datetime string
"bucket": GCS bucket name (without gs:// scheme)
"skeleton_version": skeleton version used (always HIGHEST_SKELETON_VERSION)
"object_paths": {rid: GCS object path within the bucket}
"missing": [rids not found in cache]
"""
Expand Down Expand Up @@ -2591,7 +2595,18 @@ def get_skeleton_token_by_datastack_and_rids(
)
downscoped_creds.refresh(google.auth.transport.requests.Request())

expiry_str = downscoped_creds.expiry.isoformat() if downscoped_creds.expiry else None
# Cap the reported expiry to the server-configured expiration_minutes.
# Clients should treat the token as invalid after this time.
max_expiry = datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(minutes=expiration_minutes)
if downscoped_creds.expiry is not None:
cred_expiry = downscoped_creds.expiry
# google-auth returns naive UTC datetimes; make timezone-aware for comparison
if cred_expiry.tzinfo is None:
cred_expiry = cred_expiry.replace(tzinfo=datetime.timezone.utc)
effective_expiry = min(cred_expiry, max_expiry)
else:
effective_expiry = max_expiry
expiry_str = effective_expiry.isoformat()

return {
"token": downscoped_creds.token,
Expand Down