class Darrrr::RecoveryProvider

Constants

BASE64_FIELDS
INTEGER_FIELDS
REQUIRED_FIELDS
URL_FIELDS

Attributes

icon_152px[RW]

optional field

save_token_async_api_iframe[RW]
signing_private_key[W]
token_max_size[W]

Public Instance Methods

countersign_token(token:, context: nil, options: 0x00) click to toggle source

Takes a binary representation of a token and signs if for a given account provider. Do not pass in a RecoveryToken object. The wrapping data structure is identical to the structure it's wrapping in format.

token: the to_binary_s or binary representation of the recovery token context: an arbitrary object that is passed to lower level crypto operations options: the value to set in the options byte field of the recovery

token (defaults to 0x00)

returns a Base64 encoded representation of the countersigned token and the signature over the token.

# File lib/darrrr/recovery_provider.rb, line 75
def countersign_token(token:, context: nil, options: 0x00)
  begin
    account_provider = RecoveryToken.account_provider_issuer(token)
  rescue RecoveryTokenSerializationError, UnknownProviderError
    raise TokenFormatError, "Could not determine provider"
  end

  counter_recovery_token = RecoveryToken.build(
    issuer: self,
    audience: account_provider,
    type: COUNTERSIGNED_RECOVERY_TOKEN_TYPE,
    options: options,
  )

  counter_recovery_token.data = token
  seal(counter_recovery_token, context)
end
encryptor_key() click to toggle source
# File lib/darrrr/recovery_provider.rb, line 60
def encryptor_key
  :darrrr_recovery_provider_encryptor
end
recovery_url(token_id) click to toggle source

The URL representing the location of the token. Used to initiate a recovery.

token_id: the shared ID representing a token.

# File lib/darrrr/recovery_provider.rb, line 56
def recovery_url(token_id)
  [self.recover_account, "?token_id=", URI.escape(token_id)].join
end
to_h() click to toggle source

Used to serve content at /.well-known/delegated-account-recovery/configuration

# File lib/darrrr/recovery_provider.rb, line 27
def to_h
  {
    "issuer" => self.issuer,
    "countersign-pubkeys-secp256r1" => self.unseal_keys.dup,
    "token-max-size" => self.token_max_size,
    "save-token" => self.save_token,
    "recover-account" => self.recover_account,
    "save-token-async-api-iframe" => self.save_token_async_api_iframe,
    "privacy-policy" => self.privacy_policy
  }
end
unseal_keys(context = nil) click to toggle source

The CryptoHelper defines an `unseal` method that requires us to define a `unseal_keys` method that will return the set of keys that are valid when verifying the signature on a sealed key.

returns the value of `countersign_pubkeys_secp256r1` or executes a proc passing `self` as the first argument.

# File lib/darrrr/recovery_provider.rb, line 45
def unseal_keys(context = nil)
  if @countersign_pubkeys_secp256r1.respond_to?(:call)
    @countersign_pubkeys_secp256r1.call(context)
  else
    @countersign_pubkeys_secp256r1
  end
end
validate_recovery_token!(token, context = {}) click to toggle source

Validate the token according to the processing instructions for the save-token endpoint.

Returns a validated token

# File lib/darrrr/recovery_provider.rb, line 97
def validate_recovery_token!(token, context = {})
  errors = []

  # 1. Authenticate the User. The exact nature of how the Recovery Provider authenticates the User is beyond the scope of this specification.
  # handled in before_filter

  # 4. Retrieve the Account Provider configuration as described in Section 2 using the issuer field of the token as the subject.
  begin
    account_provider = RecoveryToken.account_provider_issuer(token)
  rescue RecoveryTokenSerializationError, UnknownProviderError, TokenFormatError => e
    raise RecoveryTokenError, "Could not determine provider: #{e.message}"
  end

  # 2. Parse the token.
  # 3. Validate that the version value is 0.
  # 5. Validate the signature over the token according to processing rules for the algorithm implied by the version.
  begin
    recovery_token = account_provider.unseal(token, context)
  rescue CryptoError => e
    raise RecoveryTokenError.new("Unable to verify signature of token")
  rescue TokenFormatError => e
    raise RecoveryTokenError.new(e.message)
  end

  # 6. Validate that the audience field of the token identifies an origin which the provider considers itself authoritative for. (Often the audience will be same-origin with the Recovery Provider, but other values may be acceptable, e.g. "https://mail.example.com" and "https://social.example.com" may be acceptable audiences for "https://recovery.example.com".)
  unless self.origin == recovery_token.audience
    raise RecoveryTokenError.new("Unnacceptable audience")
  end

  if DateTime.parse(recovery_token.issued_time).utc < (Time.now - CLOCK_SKEW).utc
    raise RecoveryTokenError.new("Issued at time is too far in the past")
  end

  recovery_token
end