Skip to content

Commit

Permalink
Merge pull request developmentseed#10 from SIAnalytics/feat/auth-with…
Browse files Browse the repository at this point in the history
…-token

JWT logic modified. Token should be sent in parameters.
  • Loading branch information
NI-DoHo authored Dec 18, 2023
2 parents fdc092e + cca18c5 commit dacc7fa
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/titiler/application/titiler/application/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
)

if api_settings.jwt_secret:
app.add_middleware(JWTAuthenticationMiddleware, secret=api_settings.jwt_secret)
app.add_middleware(JWTAuthenticationMiddleware, secret=api_settings.jwt_secret, user_key="id")

if api_settings.debug:
logging.basicConfig(level=logging.DEBUG)
Expand Down
4 changes: 2 additions & 2 deletions src/titiler/application/titiler/application/settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Titiler API settings."""

import os
from pydantic import field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict

Expand All @@ -20,7 +20,7 @@ class ApiSettings(BaseSettings):

lower_case_query_parameters: bool = False
fake_https: bool = False
jwt_secret: str = ""
jwt_secret: str = os.getenv("OVISION_TOKEN", "")

model_config = SettingsConfigDict(env_prefix="TITILER_API_", env_file=".env")

Expand Down
38 changes: 23 additions & 15 deletions src/titiler/core/titiler/core/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,18 @@ async def send_wrapper(message: Message):
except:
user = None
if user:
log['user'] = user
log['status'] = message["status"]
log["user"] = user
log["status"] = message["status"]

if self.headers:
log['res.headers'] = message["headers"]
log["res.headers"] = message["headers"]

self.logger.debug(log)
await send(message)

await self.app(scope, receive, send_wrapper)



class LowerCaseQueryStringMiddleware:
"""Middleware to make URL parameters case-insensitive.
taken from: https://github.com/tiangolo/fastapi/issues/826
Expand Down Expand Up @@ -212,9 +211,11 @@ async def __call__(self, scope: Scope, receive: Receive, send: Send):


class JWTAuthenticationMiddleware:
"""Middleware to authentication with jwt"""
"""Middleware for authentication with jwt"""

def __init__(self, app: ASGIApp, secret: str, user_key="user", algorithms: List[str]=None) -> None:
def __init__(
self, app: ASGIApp, secret: str, user_key="user", algorithms: List[str] = None
) -> None:
"""Init Middleware.
Args:
Expand All @@ -224,35 +225,42 @@ def __init__(self, app: ASGIApp, secret: str, user_key="user", algorithms: List[
algorithms (List[str]): algorithms for decode jwt. default ["HS512"]
"""
if algorithms is None:
algorithms = ["HS512"]
algorithms = ["HS256"]
from fastapi.security import HTTPBearer

self.app = app
self.secret = secret
self.http_bearer = HTTPBearer(bearerFormat="jwt", auto_error=False)
self.algorithms = algorithms
self.user_key = user_key

async def __call__(self, scope: Scope, receive: Receive, send: Send):
async def response401(message: str="Not authenticated"):
response = JSONResponse(content={"detail": message},
status_code=starlette.status.HTTP_401_UNAUTHORIZED)
async def response401(message: str = "Not authenticated"):
response = JSONResponse(
content={"detail": message},
status_code=starlette.status.HTTP_401_UNAUTHORIZED,
)
await response(scope, receive, send)

"""Handle call."""
if scope["type"] == "http":
request = Request(scope)
credentials = await self.http_bearer(request)
if not credentials:

access_token = request.query_params.get("access_token")
if not access_token:
await response401("access token is required")
return
try:
payload = jwt.decode(credentials.credentials, self.secret, algorithms=self.algorithms)
payload = jwt.decode(
access_token, self.secret, algorithms=self.algorithms
)
except jwt.DecodeError as e:
await response401("unsupported token")
except jwt.InvalidTokenError as e:
await response401("invalid token")
return
user = payload[self.user_key]
scope['auth'] = credentials.credentials
scope['user'] = user
scope["auth"] = access_token
scope["user"] = user

await self.app(scope, receive, send)

0 comments on commit dacc7fa

Please sign in to comment.