Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow users to specify non-globalforestwatch domains in api key #532

Merged
merged 3 commits into from
May 31, 2024
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
36 changes: 9 additions & 27 deletions app/authentication/api_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,32 +93,14 @@ def api_key_is_valid(
return is_valid


def api_key_is_internal(
domains: List[str],
user_id: Optional[str] = None,
origin: Optional[str] = None,
referrer: Optional[str] = None,
) -> bool:

is_internal: bool = False
if origin and domains:
is_internal = any(
[
re.search(_to_regex(internal_domain.strip()), domain)
for domain in domains
for internal_domain in INTERNAL_DOMAINS.split(",")
]
)
elif referrer and domains:
is_internal = any(
[
re.search(_to_regex(domain), internal_domain)
for domain in domains
for internal_domain in INTERNAL_DOMAINS.split(",")
]
)

return is_internal
def api_key_is_internal(domains: List[str]) -> bool:
return any(
[
re.search(_to_regex(internal_domain.strip()), domain)
for domain in domains
for internal_domain in INTERNAL_DOMAINS.split(",")
]
)


def _api_key_origin_auto_error(
Expand All @@ -139,7 +121,7 @@ def _api_key_origin_auto_error(

def _to_regex(domain):
result = domain.replace(".", r"\.").replace("*", ".*")
return fr"^{result}$"
return rf"^{result}$"


def _extract_domain(url: str) -> str:
Expand Down
14 changes: 2 additions & 12 deletions app/routes/authentication/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,8 @@ async def create_api_key(

input_data = api_key_data.dict(by_alias=True)

origin = request.headers.get("origin")
referrer = request.headers.get("referer")
if not api_key_is_valid(input_data["domains"], origin=origin, referrer=referrer):
Copy link
Member Author

@solomon-negusse solomon-negusse May 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This prevents users from creating api keys from anywhere but the domain they plan to use the api key for (for example, one wouldn't be able to use postman to create an api key for mapbuilder (listed in the domains request body)) because the origin or referer wouldn't point to that and this check will fail.
This check gets applied correctly checking requests coming in with an api key (https://github.com/wri/gfw-data-api/blob/master/app/authentication/api_keys.py#L53)

raise HTTPException(
status_code=400,
detail="Domain name did not match the request origin or referrer.",
)

# Give a good error code/message if user is specifying an alias that exists for
# another one of his API keys.
# another one of their API keys.
prev_keys: List[ORMApiKey] = await api_keys.get_api_keys_from_user(user_id=user.id)
for key in prev_keys:
if key.alias == api_key_data.alias:
Expand All @@ -94,9 +86,7 @@ async def create_api_key(

row: ORMApiKey = await api_keys.create_api_key(user_id=user.id, **input_data)

is_internal = api_key_is_internal(
api_key_data.domains, user_id=None, origin=origin, referrer=referrer
)
is_internal = api_key_is_internal(api_key_data.domains)
usage_plan_id = (
API_GATEWAY_INTERNAL_USAGE_PLAN
if is_internal is True
Expand Down
1 change: 1 addition & 0 deletions app/settings/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
"api.resourcewatch.org",
"my.gfw-mapbuilder.org",
"resourcewatch.org",
"*.wri.org",
]
)

Expand Down
Loading