Skip to content

Commit

Permalink
Adding security scope validation to api endpoints (nasa-gcn#1874)
Browse files Browse the repository at this point in the history
Fixes nasa-gcn#1862. Addresses nasa-gcn#1833.

---------

Co-authored-by: Leo Singer <[email protected]>
  • Loading branch information
swyatt7 and lpsinger authored Feb 7, 2024
1 parent b10fa7a commit 42df852
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 5 deletions.
17 changes: 16 additions & 1 deletion python/across_api/across/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

from typing import Annotated, Optional

from fastapi import Depends, Query
from fastapi import Depends, Query, Security

from ..base.api import app
from ..auth.api import scope_authorize
from .hello import Hello
from .resolve import Resolve
from .schema import HelloSchema, ResolveSchema
Expand Down Expand Up @@ -47,6 +48,20 @@ def hello(name: YourNameDep) -> HelloSchema:
return Hello(name=name).schema


@app.get(
"/secure_hello",
dependencies=[
Security(scope_authorize, scopes=["gcn.nasa.gov/kafka-public-consumer"])
],
)
async def secure_hello(name: YourNameDep) -> HelloSchema:
"""
This function returns a JSON response with a greeting message and an optional name parameter.
If the name parameter is provided, the greeting message will include the name.
"""
return Hello(name=name).schema


@app.get("/across/resolve")
def resolve(name: SourceNameDep) -> ResolveSchema:
"""
Expand Down
24 changes: 20 additions & 4 deletions python/across_api/auth/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
from jose import jwt
from jose.exceptions import JWTError
import httpx # type: ignore
from fastapi import Depends, HTTPException
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from fastapi import Depends, HTTPException, Security
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer, SecurityScopes

from ..base.api import app
from .schema import VerifyAuth
Expand Down Expand Up @@ -77,10 +77,26 @@ async def claims(
raise HTTPException(status_code=401, detail=f"Authentication error: {e}")


JWTBearerDep = [Depends(claims)]
async def scope_authorize(
security_scopes: SecurityScopes,
access_token: Annotated[dict, Depends(claims)],
):
# retrieve scopes from access token
scopes = access_token.get("scope", "")

# assuming the jwt scopes will be comma separated
token_scopes = scopes.split(",")

@app.get("/auth/verify", dependencies=JWTBearerDep)
# raise exception if user.role not in endpoint scope
if not all(scope in token_scopes for scope in security_scopes.scopes):
raise HTTPException(
status_code=401,
detail="Bearer token scope(s) not in endpoint scope",
headers={"WWW-Authenticate": "Bearer"},
)


@app.get("/auth/verify", dependencies=[Security(scope_authorize, scopes=[])])
async def verify_authentication() -> VerifyAuth:
"""Verify that the user is authenticated."""
return VerifyAuth()

0 comments on commit 42df852

Please sign in to comment.