Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
860f666
feat: add list tenants with create/update scopes endpoint
botanical Dec 9, 2025
a46fd48
fix: modify output based on feedback
botanical Dec 9, 2025
03f49a5
fix: make function less complex
botanical Dec 10, 2025
fb355cd
fix: update to retrieve keycloak client creds from secret
botanical Jan 9, 2026
1539f6f
fix: remove fallback
botanical Jan 10, 2026
29e7f4b
fix: update lambda to grant read access to keycloak secret
botanical Jan 10, 2026
a8df729
fix: grant permission to get keycloak secret
botanical Jan 12, 2026
7a7c71c
fix: update to use secret name instead of arn
botanical Jan 12, 2026
c72d104
fix: update keycloak client credentials function to use secret name i…
botanical Jan 12, 2026
8d6f610
fix: update to use kms key, add to example.env
botanical Jan 12, 2026
de22e08
fix: add error handling for getting keycloak secret
botanical Jan 12, 2026
c265ec4
fix: attempt to make less complex
botanical Jan 12, 2026
0dddbbc
fix: update credential variables to retrieve
botanical Jan 12, 2026
b8bb796
fix: add debugging to stac api step
botanical Jan 13, 2026
a9a1c82
fix: revert debugging in pr.yml
botanical Jan 13, 2026
8ebd647
fix: add debugging to pr.yml test step
botanical Jan 13, 2026
78600b7
fix: update default resource server secret name and simplify try catc…
botanical Jan 13, 2026
3968802
fix: try waiting for oidc to be ready
botanical Jan 13, 2026
0db0c7d
fix: revert docker veda.stac logging and install veda_auth for ingest…
botanical Jan 13, 2026
e014cf4
fix: final docs updates
botanical Jan 13, 2026
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
2 changes: 2 additions & 0 deletions .example.env
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,5 @@ VEDA_SHARED_WEB_ACL_ID=[OPTIONAL ID ARN for WEB ACL]
VEDA_DISABLE_DEFAULT_APIGW_ENDPOINT=[OPTIONAL BOOL TO DISABLE DEFAULT API GATEWAY ENDPOINTS]
VEDA_STAC_ENABLE_STAC_AUTH_PROXY=
VEDA_TENANT_FILTER_FIELD=[OPTIONAL STRING, DEFAULTS TO "eic:tenant"]
VEDA_KEYCLOAK_UMA_RESOURCE_SERVER_CLIENT_SECRET_NAME=[OPTIONAL]
VEDA_KEYCLOAK_SECRET_KMS_KEY_ARN=[OPTIONAL, REQUIRED TO READ KEYCLOAK SECRETS]
4 changes: 3 additions & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ jobs:
run: python -m pytest .github/workflows/tests/ -vv -s

- name: Install reqs for ingest api
run: python -m pip install -r ingest_api/runtime/requirements_dev.txt
run: |
python -m pip install -r ingest_api/runtime/requirements_dev.txt
python -m pip install common/auth/

- name: Install reqs for stac api
run: python -m pip install stac_api/runtime/
Expand Down
161 changes: 161 additions & 0 deletions common/auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# VEDA Auth

Authentication and authorization utilities for veda-backend

## KeycloakPDPClient

A client for interacting with Keycloak's Authorization Services using the UMA (User-Managed Access) protocol to make authorization decisions.

### Overview

The `KeycloakPDPClient` enables applications to:

- Request a RPT (Requesting Party Token) from Keycloak
- Check user permissions for specific resources and scopes
- Extract tenant information from user tokens
- Get lists of tenants where users have create/update access

### Installation

The client is part of the `veda_auth` package. You can install it with:

```bash
pip install common/auth/
```

### Basic Usage

```python
from veda_auth.keycloak_client import KeycloakPDPClient

# Initialize the client
pdp_client = KeycloakPDPClient(
keycloak_url="https://keycloak.example.com",
realm="my-realm",
client_id="my-resource-server-client",
client_secret="my-client-secret", # Optional for confidential clients to retrieve values from AWS secrets
timeout=10.0
)

try:
# Get tenants with create/update access
tenants = pdp_client.get_tenants_with_create_update_access(
access_token=user_access_token,
resource_type="collection"
)

# Check specific permission via scope (scopes represent an action you can take on a resource)
has_permission = pdp_client.check_permission(
access_token=user_access_token,
resource_id="collection:tenant-name",
scope="create"
)
finally:
pdp_client.close()
```

### Configuration

#### Required Parameters

- `keycloak_url`: Base URL of your Keycloak instance (e.g., `https://keycloak.example.com`)
- `realm`: Keycloak realm name
- `client_id`: Client ID for the resource server in Keycloak

#### Optional Parameters

- `client_secret`: Client secret (required for confidential clients)
- `timeout`: Request timeout in seconds (default: 5.0)

### Key Methods

#### `get_tenants_with_create_update_access(access_token, resource_type, tenant_list=None)`

Returns a list of tenant names where the user has both `create` and `update` scopes for the specified resource type.

**Parameters:**

- `access_token` (str): User's OAuth2 access token
- `resource_type` (str): Type of resource (`"collection"` or `"item"`)
- `tenant_list` (List[str], optional): Pre-filtered list of tenants to check

**Returns:**

- `List[str]`: Sorted list of tenant names with create/update access

**Example:**

```python
tenants = pdp_client.get_tenants_with_create_update_access(
access_token=token,
resource_type="collection"
)
# Returns: ["tenant1", "tenant2", "public"]
```

#### `check_permission(access_token, resource_id, scope)`

Checks if a user has a specific permission for a resource.

**Parameters:**
- `access_token` (str): User's OAuth2 access token
- `resource_id` (str): Resource identifier (e.g., `"collection:tenant-name"`)
- `scope` (str): Permission scope to check (e.g., `"create"`, `"update"`, `"read"`)

The scope is defined by the resource server. To see the definition for veda, check out [veda-keycloak config](https://github.com/NASA-IMPACT/veda-keycloak/blob/main/keycloak-config-cli/config/dev/veda.yaml#L340-L344)

**Returns:**

- `bool`: `True` if permission granted, `False` otherwise

**Example:**

```python
can_create = pdp_client.check_permission(
access_token=token,
resource_id="collection:my-tenant",
scope="create"
)
```

#### `get_rpt(access_token, resources)`

Requests an RPT (Requesting Party Token) from Keycloak containing the user's permissions.

**Parameters:**

- `access_token` (str): User's OAuth2 access token
- `resources` (List[Dict]): List of resources to request permissions for. Each resource should have:
- `resource_id`: Resource identifier
- `resource_scopes`: List of scopes to check

**Returns:**

- `Dict`: RPT response containing permissions or an access token JWT

### Resource Identifier Format

Resources in Keycloak should follow this naming convention:
```
stac:{resource_type}:{tenant_name}
```

They are defined by the resource server configuration settings. For more examples, see [veda-keycloak config](https://github.com/NASA-IMPACT/veda-keycloak/blob/main/keycloak-config-cli/config/dev/veda.yaml#L331)

Examples:

- `stac:collection:tenant1`
- `stac:item:tenant2`
- `stac:collection:public`

### Token Claims

The client extracts tenant information from JWT token claims. It looks for tenants in:

- `group_membership.tenants` array
- `groups` array

### See Also

- [Keycloak Authorization Services Documentation](https://www.keycloak.org/docs/latest/authorization_services/)
- [Keycloak Resource Server Settings](https://www.keycloak.org/docs/latest/authorization_services/#resource_server_settings)
1 change: 1 addition & 0 deletions common/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
""" Common auth """
8 changes: 7 additions & 1 deletion common/auth/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@

from setuptools import find_packages, setup

inst_reqs = ["cryptography>=42.0.5", "pyjwt>=2.8.0", "fastapi", "pydantic"]
inst_reqs = [
"cryptography>=42.0.5",
"pyjwt>=2.8.0",
"fastapi",
"pydantic",
"httpx>=0.24.0",
]

setup(
name="veda_auth",
Expand Down
Loading