fix: api-authorization create/update payload shape#46
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes the request payload shape and input validation for the create_api_authorization and update_api_authorization MCP tools so they work with the OneLogin API’s expected structure (notably, nesting audience/token settings under configuration and requiring name on update).
Changes:
- Added
buildAuthorizationBody()to whitelist/reshape allowed fields and hoist convenience top-level fields intoconfiguration. - Updated
create_api_authorizationto send the reshaped body instead of raw args. - Updated
update_api_authorizationto requirenameand to send the reshaped body (excludingauth_id).
- Throw on conflicting audience/audiences aliases; document precedence (configuration.audiences > audiences > audience). - Tighten scopes/claims item schemas to the fields actually accepted (value/description for scopes; name/user_attribute_mappings/etc. for claims), with the required fields marked. - configuration.additionalProperties: false to surface typos early — core-api silently drops unknown config keys, so this only catches caller mistakes, not legitimate extensibility.
There was a problem hiding this comment.
Pull request overview
Fixes the create_api_authorization and update_api_authorization MCP tools so they send an API-compatible payload shape to OneLogin, including properly nesting authorization configuration and enforcing the API’s requirement that name be present on update.
Changes:
- Added a
buildAuthorizationBody()helper to normalize/hoist top-level convenience fields intoconfigurationand to avoid sending unsupported top-level keys. - Updated create/update handlers to use the new body builder; update now enforces
namebefore calling the API. - Expanded and tightened JSON schemas for create/update to expose
connector_id,configuration, and optionalscopes/claims, and to requirenameon update.
- update_api_authorization now also sets configuration.additionalProperties to false, matching create (was inconsistently left at true). - Docstring on buildAuthorizationBody() rewritten to match the strict policy the schemas actually enforce. - create_api_authorization description now accurately describes the claims item shape (name + user_attribute_mappings required).
There was a problem hiding this comment.
Pull request overview
This PR fixes the request payload shape and validation for the create_api_authorization and update_api_authorization MCP tools so they work with OneLogin’s API expectations (notably nesting audience/token settings under configuration and requiring name on update).
Changes:
- Added a
buildAuthorizationBody()helper to normalize/hoist convenience top-level fields into a nestedconfigurationobject and drop unknown keys. - Updated
createApiAuthorizationandupdateApiAuthorizationto send the normalized body (and madenamerequired for updates both in runtime checks and schema). - Expanded the
create_api_authorizationschema to exposeconnector_id,configuration, and optionalscopes/claims, and made create/update schemas strict (additionalProperties: false).
- Clarify buildAuthorizationBody() docstring: connector_id/scopes/claims
are create-only (connector_id is attr_readonly on the model; scopes and
claims are 'only accepted while creating the App' per the core-api
adapter). The update tool schema correctly omits them.
- Align connector_id wording between the tool description and the
schema property description ('account default API authorization
connector').
- Update tool description now explicitly calls out the asymmetry and
points callers at add_authorization_scopes / add_authorization_claim
for post-create management.
Summary
Fixes #45 —
create_api_authorizationandupdate_api_authorizationMCP tools both failed against the OneLogin API.Root cause
ApiAuthorizationAppmodel onlyattr_accessiblesname,description, andapi_authorization_config_values_attributes. The MCP was sendingaudienceat the top level, but the adapter expects it nested underconfiguration.audiences(plural). Unknown top-level fields are rejected.Api::V5::ApiAuthAppsControllerdeclaresrequired_params :name, :only => [:create, :update]— so update is not a partial update. The MCP schema marked onlyauth_idrequired, so the model frequently omittednameand got a 400.Changes
buildAuthorizationBody()helper hoists top-levelaudience/audiences/resource_identifier/access_token_expiration_minutes/refresh_token_expiration_minutesinto a nestedconfigurationobject. Throws if conflicting top-levelaudience/audiencesvalues are provided; precedence isconfiguration.audiences>audiences>audience.updateApiAuthorizationnow requiresname(matches the server) and throws a descriptive error if missing.create_api_authorizationschema exposesconnector_id, nestedconfiguration, and typedscopes({value, description?}, value required) andclaims({name, user_attribute_mappings, user_attribute_macros?, attributes_transformations?}, name + user_attribute_mappings required) arrays.additionalProperties: falseat every level.update_api_authorizationschema requiresnamein addition toauth_id, and intentionally does not exposeconnector_id/scopes/claims—connector_idisattr_readonlyon the model, and scopes/claims are create-only per the core-api adapter. Useadd_authorization_scopes/add_authorization_claimetc. to manage them afterwards.Test plan
create_api_authorizationwith{name, description}succeeds (uses account default connector)create_api_authorizationwith{name, audience: "foo"}succeeds — audience is nested into configurationcreate_api_authorizationwith{name, configuration: {audiences: "foo"}}succeedscreate_api_authorizationwith bothaudience: "a"andaudiences: "b"fails with a clear errorupdate_api_authorizationwith{auth_id, name, description}succeedsupdate_api_authorizationwithoutnamereturns a clear error before hitting the APIdelete_api_authorizationstill works (regression check)