Skip to content

Fix webauthn_id generated by after_initialize is never persisted for existing users #104

Description

@santiagorodriguez96

Our WebauthnAuthenticationGenerator injects webauthn logic to the user model, and as part of that logic, it generates an after_initialize callback that is used to set the webauthn_id:

def inject_webauthn_content_to_user_model
inject_into_file "app/models/user.rb", after: "normalizes :email_address, with: ->(e) { e.strip.downcase }\n" do
<<-RUBY.strip_heredoc.indent(2)
has_many :webauthn_credentials, dependent: :destroy
with_options class_name: "WebauthnCredential" do
has_many :second_factor_webauthn_credentials, -> { second_factor }
has_many :passkeys, -> { passkey }
end
after_initialize do
self.webauthn_id ||= WebAuthn.generate_user_id
end
def second_factor_enabled?
webauthn_credentials.any?
end
RUBY
end

The problem is that this callback sets webauthn_id in memory on every model load, but for existing users who don't yet have a webauthn_id, the generated value is not saved to the database until the user is updated in some way. Until that happens, since no controller in the passkeys/security keys registration flow calls save on the user record, each request generates a different ephemeral value, which makes it so that the credentials are stored in the authenticators with different identifiers for the same user.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions