Skip to content

list_policy_rules raises ValidationError on Knowledge/PossessionConstraint when the Management API returns lowercase types #548

@danibarranqueroo

Description

@danibarranqueroo

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request.
  • Please do not leave +1 or me too comments, they generate extra noise for issue followers and do not help prioritize the request.
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment.
    Before submitting a bug report, we ask that you first search existing issues and pull requests to see if someone else may have experienced the same issue or may have already submitted a fix for it.

Python Version & Okta SDK Version(s)

Python 3.12.10
okta 3.4.2

Affected Class/Method(s)

Method Path Failing response type
list_policy_rules() GET /api/v1/policies/{policyId}/rules AccessPolicyRule (200) → nested KnowledgeConstraint/PossessionConstraint

Failing validators:

  • okta/models/knowledge_constraint.py:120KnowledgeConstraint.types_validate_enum
  • okta/models/possession_constraint.py:161PossessionConstraint.types_validate_enum

Customer Information

Organization Name: Prowler
Paid Customer: no

Code Snippet

import asyncio
from okta.client import Client as OktaClient

async def main():
config = {
    "authorizationMode": "PrivateKey",
    "orgUrl": "https://<your-org>.okta.com",
    "scopes": ["okta.policies.read"],
    "clientId": "<client-id>",
    "privateKey": "<pem>",
}
client = OktaClient(config)
# policy_id of any ACCESS_POLICY that contains a rule whose
# actions.appSignOn.verificationMethod.constraints[].knowledge.types is
# returned by the API as lowercase (e.g. ["password"])
rules, resp, err = await client.list_policy_rules("<access_policy_id>", limit="100")
print(rules, err)

asyncio.run(main())

Debug Output / Traceback

pydantic_core._pydantic_core.ValidationError: 1 validation error for KnowledgeConstraint types Value error, each list item must be one of ('SECURITY_KEY', 'PHONE', 'EMAIL', 'PASSWORD', 'SECURITY_QUESTION', 'APP', 'FEDERATED') [type=value_error, input_value=['password'],
input_type=list] For further information visit https://errors.pydantic.dev/2.12/v/value_error

PossessionConstraint.types has the same bug (same enum, same field_validator block at okta/models/possession_constraint.py:161). It surfaces when the API returns any of the seven values in lowercase ("password", "phone", "email", "security_key", "security_question", "app", "federated").

Expected Behavior

list_policy_rules() returns the rules tuple (items, response, None). The types validator should either:

  1. Normalize input case before checking (value.upper() in allowed_set), or
  2. Be dropped in favor of accepting whatever the Management API returns (matching the contract of the other SDKs and the API's actual response), or
  3. The OpenAPI spec the SDK is generated from is updated to declare the enum case-insensitively (or to use the actual values returned).

This pattern matches the resolution of related issues #419, #420, #481, #498, and #536 where strict pydantic validators were relaxed to accept the API's actual payload.

Actual Behavior

The SDK raises pydantic_core._pydantic_core.ValidationError during deserialization of the rule list. The HTTP call succeeded — the response body is valid — but the SDK refuses to surface it.
The caller never receives (rules, response, error); the exception propagates instead. The only workaround is to bypass the typed list_policy_rules() and call client._request_executor.create_request + .execute(request) without a response type, parsing the raw JSON manually.

Steps to reproduce

  1. Tenant on Okta Identity Engine with at least one ACCESS_POLICY rule whose actions.appSignOn.verificationMethod.constraints[].knowledge.types (or possession.types) is returned by the Management API as a lowercase value such as ["password"]. In Prowler's own scans this was observed against the default policies bound to the Okta Admin Console (saasure) and Okta Dashboard (okta_enduser) first-party apps.
  2. Call await client.list_policy_rules(policy_id, limit="100") against that policy.
  3. Observe pydantic_core._pydantic_core.ValidationError: 1 validation error for KnowledgeConstraint / types: each list item must be one of ('SECURITY_KEY', 'PHONE', 'EMAIL', 'PASSWORD', 'SECURITY_QUESTION', 'APP', 'FEDERATED').

The validator can be reproduced in isolation without any tenant:

from okta.models.knowledge_constraint import KnowledgeConstraint
from okta.models.possession_constraint import PossessionConstraint

KnowledgeConstraint(types=["password"]) # raises ValidationError
PossessionConstraint(types=["phone"]) # raises ValidationError

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions