Module: WorkOS::Actions
- Defined in:
- lib/workos/actions.rb
Overview
AuthKit Actions request verification + response signing.
action = client.actions.construct_action(
payload: req.body, sig_header: req.headers["WorkOS-Signature"],
secret: ENV["WORKOS_ACTIONS_SECRET"]
)
resp = client.actions.sign_response(
action_type: "authentication", verdict: "Allow",
secret: ENV["WORKOS_ACTIONS_SECRET"]
)
Constant Summary collapse
- DEFAULT_TOLERANCE_SECONDS =
30- ACTION_TYPE_TO_RESPONSE_OBJECT =
{ "authentication" => "authentication_action_response", "user_registration" => "user_registration_action_response" }.freeze
Class Method Summary collapse
-
.compute_signature(payload:, timestamp:, secret:) ⇒ Object
Compute HMAC-SHA256 hex signature for a (timestamp, payload) pair.
-
.construct_action(payload:, sig_header:, secret:, tolerance: DEFAULT_TOLERANCE_SECONDS) ⇒ Object
Verify and deserialize an Actions request payload.
-
.parse_signature_header(sig_header) ⇒ Object
Parse a “t=<ms>, v1=<sig>” header into [timestamp, signature].
- .secure_compare(a, b) ⇒ Object
-
.sign_response(action_type:, verdict:, secret:, error_message: nil) ⇒ Object
Build and sign an Actions response.
-
.verify_header(payload:, sig_header:, secret:, tolerance: DEFAULT_TOLERANCE_SECONDS) ⇒ Object
Verify a request signature; raises on failure.
Class Method Details
.compute_signature(payload:, timestamp:, secret:) ⇒ Object
Compute HMAC-SHA256 hex signature for a (timestamp, payload) pair.
78 79 80 |
# File 'lib/workos/actions.rb', line 78 def compute_signature(payload:, timestamp:, secret:) WorkOS::Util::Signature.compute(payload: payload, timestamp: , secret: secret) end |
.construct_action(payload:, sig_header:, secret:, tolerance: DEFAULT_TOLERANCE_SECONDS) ⇒ Object
Verify and deserialize an Actions request payload.
55 56 57 58 |
# File 'lib/workos/actions.rb', line 55 def construct_action(payload:, sig_header:, secret:, tolerance: DEFAULT_TOLERANCE_SECONDS) verify_header(payload: payload, sig_header: sig_header, secret: secret, tolerance: tolerance) JSON.parse(payload) end |
.parse_signature_header(sig_header) ⇒ Object
Parse a “t=<ms>, v1=<sig>” header into [timestamp, signature].
83 84 85 86 87 |
# File 'lib/workos/actions.rb', line 83 def parse_signature_header(sig_header) WorkOS::Util::Signature.parse_header(sig_header) rescue ArgumentError => e raise WorkOS::SignatureVerificationError.new(message: e., http_status: nil) end |
.secure_compare(a, b) ⇒ Object
89 90 91 |
# File 'lib/workos/actions.rb', line 89 def secure_compare(a, b) WorkOS::Util::Signature.secure_compare(a, b) end |
.sign_response(action_type:, verdict:, secret:, error_message: nil) ⇒ Object
Build and sign an Actions response. action_type is “authentication” or “user_registration”; verdict is “Allow” or “Deny”.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/workos/actions.rb', line 62 def sign_response(action_type:, verdict:, secret:, error_message: nil) object_type = ACTION_TYPE_TO_RESPONSE_OBJECT[action_type.to_s] raise ArgumentError, "Unknown action_type: #{action_type}" unless object_type = (Time.now.to_f * 1000).to_i response_payload = {"timestamp" => , "verdict" => verdict} response_payload["error_message"] = if payload_json = JSON.generate(response_payload) signed_payload = "#{}.#{payload_json}" { "object" => object_type, "payload" => response_payload, "signature" => OpenSSL::HMAC.hexdigest("SHA256", secret, signed_payload) } end |
.verify_header(payload:, sig_header:, secret:, tolerance: DEFAULT_TOLERANCE_SECONDS) ⇒ Object
Verify a request signature; raises on failure.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/workos/actions.rb', line 35 def verify_header(payload:, sig_header:, secret:, tolerance: DEFAULT_TOLERANCE_SECONDS) , signature_hash = parse_signature_header(sig_header) issued_at = .to_i / 1000.0 if (Time.now.to_f - issued_at) > tolerance raise WorkOS::SignatureVerificationError.new( message: "Timestamp outside the tolerance zone", http_status: nil ) end expected = compute_signature(payload: payload, timestamp: , secret: secret) unless secure_compare(signature_hash, expected) raise WorkOS::SignatureVerificationError.new( message: "Signature hash does not match the expected signature hash for payload", http_status: nil ) end true end |