Fix: Add UserFactorSignedNonce Schema and Discriminator Mapping for Okta FastPass#551
Open
BinoyOza-okta wants to merge 2 commits into
Open
Fix: Add UserFactorSignedNonce Schema and Discriminator Mapping for Okta FastPass#551BinoyOza-okta wants to merge 2 commits into
UserFactorSignedNonce Schema and Discriminator Mapping for Okta FastPass#551BinoyOza-okta wants to merge 2 commits into
Conversation
…kta FastPass factor
This commit fixes deserialization failures in `list_factors()` (GET `/api/v1/users/{userId}/factors`) for users enrolled with the Okta FastPass `signed_nonce` factor type.
Problem:
- `UserApi.list_factors()` raised a Pydantic ValidationError whenever the response contained a factor with `factorType: "signed_nonce"`.
- The `UserFactorType` enum already included `signed_nonce`, but the `UserFactor` schema in the OpenAPI spec lacked both a discriminator mapping for it and a dedicated `UserFactorSignedNonce` subschema.
- As a result, the generated SDK had no class to route the payload to, and discriminator validation rejected the response: Discriminator property name: factorType, mapping: {"call": ..., "email": ..., "push": ..., "question": ..., "sms": ..., "token": ..., "token:hardware": ..., "token:hotp": ..., "token:software:totp": ..., "u2f": ..., "web": ..., "webauthn": ...} (no entry for `signed_nonce`).
Root Cause:
- Missing `signed_nonce: '#/components/schemas/UserFactorSignedNonce'` entry under `UserFactor.discriminator.mapping` in `openapi/api.yaml`.
- Missing `UserFactorSignedNonce`, `UserFactorSignedNonceProfile`, and `UserFactorSignedNonceProfileKey` schema definitions describing the Okta FastPass payload (device metadata + JWK-style key material).
Solution:
1. Added `signed_nonce` to the `UserFactor` discriminator mapping in `openapi/api.yaml`.
2. Defined three new component schemas in `openapi/api.yaml`:
- `UserFactorSignedNonce` (allOf `UserFactor` + `provider: OKTA`, `factorType: signed_nonce`, `profile`)
- `UserFactorSignedNonceProfile` (device metadata: `credentialId`, `deviceType`, `name`, `platform`, `version`, `keys[]`)
- `UserFactorSignedNonceProfileKey` (JWK fields: `kty`, `use`, `kid`, `jwkType`, `e`, `n`, `crv`, `x`, `y`, `x5c`)
3. Regenerated model files:
- `okta/models/user_factor_signed_nonce.py`
- `okta/models/user_factor_signed_nonce_profile.py`
- `okta/models/user_factor_signed_nonce_profile_key.py`
4. Updated `okta/models/user_factor.py` to register the new subclass in the discriminator map, the `oneOf` union, and `from_dict()` routing.
5. Wired the new models into the lazy-import maps in `okta/__init__.py` and `okta/models/__init__.py` (added to the `user_factor` model group).
6. Added API docs: `docs/UserFactorSignedNonce.md`, `docs/UserFactorSignedNonceProfile.md`, `docs/UserFactorSignedNonceProfileKey.md`.
Testing:
- Verified against a live Okta org with a user enrolled in Okta FastPass (`signed_nonce`). `client.list_factors(user_id)` now returns the full factor list, including `UserFactorSignedNonce` instances correctly deserialized with populated `profile` and `profile.keys` fields.
- No breaking changes to existing factor types; all other discriminator mappings remain intact.
Related:
- #311
- #387
Fixes: OKTA-1152856
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix: Add
UserFactorSignedNonceSchema and Discriminator Mapping for Okta FastPassSummary
Adds the missing
signed_noncediscriminator branch (Okta FastPass) to theUserFactorpolymorphic model, along with three new component schemas (UserFactorSignedNonce,UserFactorSignedNonceProfile,UserFactorSignedNonceProfileKey). This unblockslist_factors()for any user enrolled in Okta FastPass.Ticket: OKTA-1152856
Problem
UserApi.list_factors()(GET/api/v1/users/{userId}/factors) failed with a PydanticValidationErrorwhenever the response contained a factor withfactorType: "signed_nonce":There is no entry for
signed_nonce, so the SDK has nothing to deserialize the payload into. TheUserFactorTypeenum already advertisessigned_nonceas a valid value, but the corresponding subschema and discriminator mapping were never added to the OAS spec.Affected endpoint:
UserApi.list_factors(user_id)Root Cause
UserFactor.discriminator.mappinginopenapi/api.yamlhad nosigned_nonce→ schema mapping.UserFactorSignedNonce(or supportingUserFactorSignedNonceProfile/UserFactorSignedNonceProfileKey) schema existed to describe the Okta FastPass payload (device metadata + JWK-style key material returned for each enrolled device).The OAS3 spec issue has been fixed upstream; this PR mirrors that fix in the SDK spec snapshot (
openapi/api.yaml) and regenerates the affected models.Solution
Spec changes —
openapi/api.yamlAdded the discriminator mapping:
Added three new component schemas:
UserFactorSignedNonce—allOfextension ofUserFactor, pinningfactorType: signed_nonce,provider: OKTA, and aprofilereference. Documents that enrollment/activation must go through the Okta Verify authenticator flow; the Factors API only supports list/delete for this type.UserFactorSignedNonceProfile— Device metadata for an Okta FastPass registration:credentialId,deviceType,name,platform,version, and akeys[]array.UserFactorSignedNonceProfileKey— JWK-style key entry:kty(RSA/EC),use,kid,jwkType(proofOfPossession/userVerification/userVerificationBioOrPin), RSA fields (e,n), EC fields (crv,x,y), andx5c.Generated model changes
okta/models/user_factor_signed_nonce.py(new, generated)okta/models/user_factor_signed_nonce_profile.py(new, generated)okta/models/user_factor_signed_nonce_profile_key.py(new, generated)Discriminator routing —
okta/models/user_factor.pyUserFactorSignedNoncein:__discriminator_value_class_map("signed_nonce": "UserFactorSignedNonce").Union[...]of concrete subclasses returned byfrom_json/from_dict.from_dict()dispatch chain (with the same self-recursion guard used for the other variants).TYPE_CHECKINGimport block.Lazy-import wiring
okta/__init__.py— Added the three new classes to_LAZY_IMPORT_MAPso they can be imported asfrom okta import UserFactorSignedNonce.okta/models/__init__.py— Added the same entries to the model-level_LAZY_IMPORT_MAPand addedUserFactorSignedNonceto theuser_factormodel group in_MODEL_GROUPS.Docs
docs/UserFactorSignedNonce.md(new)docs/UserFactorSignedNonceProfile.md(new)docs/UserFactorSignedNonceProfileKey.md(new)Files Changed
openapi/api.yamlokta/models/user_factor.pyokta/models/user_factor_signed_nonce.pyokta/models/user_factor_signed_nonce_profile.pyokta/models/user_factor_signed_nonce_profile_key.pyokta/__init__.pyokta/models/__init__.pyuser_factorgroup entrydocs/UserFactorSignedNonce.mddocs/UserFactorSignedNonceProfile.mddocs/UserFactorSignedNonceProfileKey.mdTesting
signed_nonce):client.list_factors(user_id)returns the complete factor list with no validation errors.UserFactorSignedNonceinstances deserialize correctly, with populatedprofile.deviceType,profile.platform,profile.version, andprofile.keys[](including both RSA and EC keys,proofOfPossessionanduserVerificationvariants).push,webauthn,token:software:totp, etc.) — the discriminator map still routes all existing values to their original subclasses.from okta import UserFactorSignedNonceresolves through_LAZY_IMPORT_MAPwithout eagerly loading all 1000+ models.Backward Compatibility
ValidationErrorfromlist_factors()for FastPass users can now remove that workaround.Related
Upstream
The OAS3 spec issue has been fixed in
specs/monolith/management/spec/v1/am/factors.yaml. Once that fix propagates to the canonicalapi.yamlsource, regenerating the SDK from the upstream spec should produce equivalent output to this PR.