Skip to content

fix: parse AuthKit Actions request into flat ActionContext - #115

Merged
gjtorikian merged 2 commits into
mainfrom
fix/actions-construct-wire-format
Aug 11, 2026
Merged

fix: parse AuthKit Actions request into flat ActionContext#115
gjtorikian merged 2 commits into
mainfrom
fix/actions-construct-wire-format

Conversation

@gjtorikian

Copy link
Copy Markdown
Contributor

Summary

WorkOS.Actions.construct_action/4 deserialized the verified AuthKit Action request into the generic WorkOS.EventSchema envelope ({object, id, event, data, created_at}). The real Actions wire format is a flat context object discriminated by object (authentication_action_context / user_registration_action_context), not an event envelope — so parsing it into EventSchema populated only object and id, leaving event empty and data nil. Every useful field (user, user_data, ip_address, user_agent, device_fingerprint, issuer, organization, invitation, …) was silently dropped with no error.

This mirrors the bug reported against workos-go (see workos-go #594 / PR #595). workos-node is the authoritative reference: its Actions.constructAction deserializes into a flat ActionContext (src/actions/interfaces/action.interface.ts).

Changes

  • Replace the EventSchema return with a typed WorkOS.ActionContext (+ WorkOS.ActionUserData), mirroring workos-node and reusing the generated User, Organization, OrganizationMembership, and Invitation models for nested objects. Dispatch on :object to read the type-specific fields.
  • Add tests for both context types against the real wire format; the prior test used a fabricated event envelope that never matched what WorkOS sends.

Validation

  • mix test test/workos/actions_test.exs → 7 passed
  • mix format --check-formatted clean

Scope / follow-up

This fixes the request-parsing side (the reported bug). The response side (sign_response/3) still emits the base64 {payload, sig} shape, which differs from workos-node's {object, payload, signature} — that is a separate gap not addressed here.

This is a breaking change to construct_action's return type (EventSchema.t()ActionContext.t()). The previous behavior never worked (every field was dropped), so no working code depends on the old return shape.

construct_action/4 deserialized the verified action request into the generic
EventSchema envelope ({object, id, event, data, created_at}). The real
Actions wire format is a flat context object discriminated by 'object'
(authentication_action_context / user_registration_action_context), so
parsing it into EventSchema silently dropped every useful field (user,
user_data, ip_address, device_fingerprint, issuer, ...) with no error.

Replace the EventSchema return with a typed WorkOS.ActionContext
(+ WorkOS.ActionUserData), mirroring workos-node's ActionContext and
reusing the generated User, Organization, OrganizationMembership, and
Invitation models for nested objects. Dispatch on :object to read the
type-specific fields.

Tests now exercise the real wire format for both context types; the prior
test used a fabricated event envelope that never matched what WorkOS sends.
@gjtorikian
gjtorikian requested a review from a team as a code owner August 10, 2026 16:30
@greptile-apps

greptile-apps Bot commented Aug 10, 2026

Copy link
Copy Markdown

Greptile Summary

The PR replaces event-envelope parsing with typed, flat AuthKit action contexts and revises action-response serialization.

  • Adds ActionContext and ActionUserData models.
  • Parses verified action requests into the new context structure.
  • Updates response signing and tests for authentication and registration actions.

Confidence Score: 5/5

The PR appears safe to merge because no eligible blocking failure or outstanding prior finding remains.

No blocking failure remains.

Important Files Changed

Filename Overview
lib/workos/action_context.ex Adds the flat AuthKit action-context struct and conversion of nested resources.
lib/workos/action_user_data.ex Adds typed provisional user-registration data parsing.
lib/workos/actions.ex Switches request deserialization to ActionContext and revises response construction and signing.
test/workos/actions_test.exs Replaces fabricated event-envelope coverage with authentication and registration context tests and updated response assertions.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Signed AuthKit request] --> B[Verify signature]
  B --> C[Decode flat JSON context]
  C --> D[ActionContext]
  D --> E[Application decision]
  E --> F[Build response payload]
  F --> G[Sign response]
  G --> H[AuthKit action response]
Loading

Reviews (2): Last reviewed commit: "fix: sign action response in workos-node..." | Re-trigger Greptile

sign_response emitted a base64 {payload, sig} shape that no other SDK
produces. The real Actions response wire format (workos-node + python,
ruby, php, dotnet, kotlin) is {object, payload, signature}, where
signature = HMAC-SHA256(secret, "<timestamp>.<JSON(payload)>") and
payload = {timestamp, verdict, error_message?}.

Switch the return to %{object, payload, signature}, signing over
JSON.encode!(payload) so the signed bytes match the transmitted payload
bytes. error_message is included only on a Deny verdict with a non-empty
message, matching workos-node.
@gjtorikian
gjtorikian merged commit bd0a7a0 into main Aug 11, 2026
9 checks passed
@gjtorikian
gjtorikian deleted the fix/actions-construct-wire-format branch August 11, 2026 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant