Module: Communication::CanaryToken

Defined in:
app/services/communication/canary_token.rb

Overview

Mints and verifies the tamper-resistant token embedded in an email's invisible
canary link (see Communication#canary_link_html and Api::V1::EmailCanaryController).
The token encodes a CommunicationRecipient id, signed with a key derived from the
app secret — mirroring EmailPreference's MessageVerifier scheme — so a scanner
(or anyone) cannot forge a hit for an arbitrary recipient.

Constant Summary collapse

PURPOSE =
:email_canary

Class Method Summary collapse

Class Method Details

.decode(token) ⇒ Integer?

Returns the recipient id, or nil if the token is missing/forged/expired.

Parameters:

  • token (String)

Returns:

  • (Integer, nil)

    the recipient id, or nil if the token is missing/forged/expired



19
20
21
22
23
# File 'app/services/communication/canary_token.rb', line 19

def self.decode(token)
  verifier.verified(token.to_s, purpose: PURPOSE)
rescue StandardError
  nil
end

.encode(communication_recipient_id) ⇒ String

Returns signed token for the canary URL.

Parameters:

  • communication_recipient_id (Integer)

Returns:

  • (String)

    signed token for the canary URL



13
14
15
# File 'app/services/communication/canary_token.rb', line 13

def self.encode(communication_recipient_id)
  verifier.generate(communication_recipient_id.to_i, purpose: PURPOSE)
end

.verifierActiveSupport::MessageVerifier

Returns:

  • (ActiveSupport::MessageVerifier)


26
27
28
29
30
31
32
# File 'app/services/communication/canary_token.rb', line 26

def self.verifier
  @verifier ||= ActiveSupport::MessageVerifier.new(
    Rails.application.key_generator.generate_key('email_canary/v1'),
    digest: 'SHA256',
    serializer: JSON
  )
end