POST /authorize Endpoint

The /authorize endpoint provides authorization decisions for external services. It evaluates whether a user is allowed to perform a specific action on a resource based on OPA policies.

Request

URL

POST /authorize

Headers

Header

Required

Description

Content-Type

Yes

Must be application/json

Request Body

{
  "resource": "timeseries",
  "action": "read",
  "user": {
    "id": "m5hectest",
    "username": "m5hectest",
    "roles": ["CWMS Users", "TS ID Creator"],
    "offices": ["SWT"],
    "persona": "operator",
    "shift_start": 6,
    "shift_end": 18,
    "timezone": "America/Chicago"
  },
  "context": {
    "office_id": "SWT",
    "data_source": "USGS"
  }
}

Body Parameters

Parameter

Type

Required

Description

resource

string

Yes

Resource being accessed (e.g., timeseries, locations, offices)

action

string

Yes

Action being performed: read, create, update, delete

user

object

No

User context object (alternative to jwt_token)

context

object

No

Additional context for authorization decision

jwt_token

string

No

JWT token for user authentication (alternative to user object)

User Object Fields

Field

Type

Description

id

string

User identifier

username

string

Username

roles

array

List of user roles

offices

array

List of offices the user belongs to

persona

string

Active persona (e.g., operator, analyst)

shift_start

number

Shift start hour (0-23)

shift_end

number

Shift end hour (0-23)

timezone

string

User timezone (IANA format)

Context Object Fields

Field

Type

Description

office_id

string

Office ID for the requested data

data_source

string

Data source identifier

created_ns

number

Creation timestamp in nanoseconds

timestamp_ns

number

Data timestamp in nanoseconds

Additional fields can be included as needed by the OPA policy.

Response

Success Response (200 OK)

{
  "decision": {
    "allow": true,
    "decision_id": "proxy-a1b2c3d4",
    "reason": "User has read access to timeseries in office SWT"
  },
  "user": {
    "id": "m5hectest",
    "username": "m5hectest",
    "email": "m5hectest@example.com",
    "roles": ["CWMS Users", "TS ID Creator"],
    "offices": ["SWT"],
    "primary_office": "SWT",
    "persona": "operator"
  },
  "constraints": {
    "allowed_offices": ["SWT"],
    "embargo_rules": {
      "SWT": 72,
      "default": 168
    },
    "embargo_exempt": false,
    "time_window": {
      "restrict_hours": 8
    },
    "data_classification": ["public", "internal"]
  },
  "timestamp": "2024-01-15T10:30:00.000Z"
}

Response Fields

Field

Type

Description

decision.allow

boolean

Whether the action is allowed

decision.decision_id

string

Unique identifier for this decision (for audit logging)

decision.reason

string

Human-readable explanation of the decision

user

object

Resolved user information

constraints

object

Data filtering constraints to apply

timestamp

string

ISO 8601 timestamp of the decision

Constraints Object

Field

Type

Description

allowed_offices

array

Offices the user can access, or ["*"] for all

embargo_rules

object

Hours of embargo per office (data newer than X hours restricted)

embargo_exempt

boolean

Whether user is exempt from embargo rules

time_window

object

Time window restrictions for historical data

data_classification

array

Classification levels the user can access

Error Responses

400 Bad Request

Missing required fields:

{
  "error": "Bad Request",
  "message": "resource and action are required fields"
}

Invalid action value:

{
  "error": "Bad Request",
  "message": "action must be one of: read, create, update, delete"
}

500 Internal Server Error

{
  "error": "Internal Server Error",
  "message": "Authorization processing failed"
}

Examples

Using curl with User Object

curl -X POST http://localhost:3001/authorize \
  -H "Content-Type: application/json" \
  -d '{
    "resource": "timeseries",
    "action": "read",
    "user": {
      "id": "m5hectest",
      "username": "m5hectest",
      "roles": ["CWMS Users"],
      "offices": ["SWT"]
    },
    "context": {
      "office_id": "SWT"
    }
  }'

Using curl with JWT Token

curl -X POST http://localhost:3001/authorize \
  -H "Content-Type: application/json" \
  -d '{
    "resource": "timeseries",
    "action": "create",
    "jwt_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
    "context": {
      "office_id": "SWT"
    }
  }'

Checking Write Permission

curl -X POST http://localhost:3001/authorize \
  -H "Content-Type: application/json" \
  -d '{
    "resource": "timeseries",
    "action": "update",
    "user": {
      "id": "m5hectest",
      "username": "m5hectest",
      "roles": ["CWMS Users", "TS ID Creator"],
      "offices": ["SWT"]
    },
    "context": {
      "office_id": "SWT",
      "data_source": "manual"
    }
  }'

Use Cases

Pre-flight Authorization Check

External services can check authorization before attempting an operation:

        sequenceDiagram
    participant Client
    participant Proxy
    participant OPA

    Client->>Proxy: POST /authorize
    Proxy->>OPA: Evaluate policy
    OPA-->>Proxy: Decision + constraints
    Proxy-->>Client: Allow/Deny + constraints

    alt Allowed
        Client->>Proxy: Actual API request
    else Denied
        Client->>Client: Handle denial
    end
    

Batch Authorization

For batch operations, check authorization once and cache the constraints:

# Get constraints for the session
CONSTRAINTS=$(curl -s -X POST http://localhost:3001/authorize \
  -H "Content-Type: application/json" \
  -d '{"resource": "timeseries", "action": "read", "jwt_token": "'$TOKEN'"}' \
  | jq -r '.constraints')

# Use constraints for multiple requests
echo $CONSTRAINTS