~arestifo/crystal-webauthn

626dede5d8baf691e2f77bfbea0471fd0b8af739 — Alberto Restifo 4 years ago 60f9470 master
Refactor modules namespacing and add challenge spec
A spec/webauthn/public_key_credential/options_spec.cr => spec/webauthn/public_key_credential/options_spec.cr +27 -0
@@ 0,0 1,27 @@
require "../../spec_helper"

describe WebAuthn::PublicKeyCredential::Options do
  describe "#challenge" do
    it "creates a challenge of at least 16 bytes" do
      challenge = TestOptions.new.challenge

      challenge.bytesize.should be >= 16
    end

    it "crates a random challenge each time it's instanciated" do
      ch1 = TestOptions.new.challenge
      ch2 = TestOptions.new.challenge

      ch1.should_not eq(ch2)
    end

    it "an instance always returns the same challenge" do
      opt = TestOptions.new

      opt.challenge.should eq(opt.challenge)
    end
  end
end

class TestOptions < WebAuthn::PublicKeyCredential::Options
end

M src/webauthn/public_key_credential/creation_options.cr => src/webauthn/public_key_credential/creation_options.cr +11 -5
@@ 1,9 1,15 @@
class WebAuthn::PublicKeyCredential::CreationOptions
  include JSON::Serializable
require "./options"

  getter rp : WebAuthn::PublicKeyCredential::RPEntity
  getter user : WebAuthn::PublicKeyCredential::User
module WebAuthn
  module PublicKeyCredential
    class CreationOptions < Options
      include JSON::Serializable

  def initialize(@rp, @user)
      getter rp : WebAuthn::PublicKeyCredential::RPEntity
      getter user : WebAuthn::PublicKeyCredential::User

      def initialize(@rp, @user)
      end
    end
  end
end

M src/webauthn/public_key_credential/entity.cr => src/webauthn/public_key_credential/entity.cr +8 -4
@@ 1,6 1,10 @@
class WebAuthn::PublicKeyCredential::Entity
  include JSON::Serializable
module WebAuthn
  module PublicKeyCredential
    class Entity
      include JSON::Serializable

  @[JSON::Field(key: "name")]
  getter name : String
      @[JSON::Field(key: "name")]
      getter name : String
    end
  end
end

M src/webauthn/public_key_credential/options.cr => src/webauthn/public_key_credential/options.cr +15 -6
@@ 1,10 1,19 @@
abstract class Options
  CHALLENGE_LENGTH = 32
module WebAuthn
  module PublicKeyCredential
    abstract class Options
      CHALLENGE_LENGTH = 32

  abstract def to_json : String
  abstract def to_json(io : IO)
      abstract def to_json
      abstract def to_json(io : IO)

  def challenge : String
    @challenge ||= Random::Secure.urlsafe_base64(CHALLENGE_LENGTH, false)
      # The challenge is a secure-random string used to avoid reply attacks.
      # This vlaue should be stored for the duration of the auth session and
      # verified by the server.
      #
      # See: https://www.w3.org/TR/webauthn/#cryptographic-challenges
      def challenge : String
        @challenge ||= Random::Secure.urlsafe_base64(CHALLENGE_LENGTH, false)
      end
    end
  end
end

D src/webauthn/public_key_credential/relying_party.cr => src/webauthn/public_key_credential/relying_party.cr +0 -2
@@ 1,2 0,0 @@
class WebAuthn::PublicKeyCredential::RelyingParty
end

M src/webauthn/public_key_credential/rp_entity.cr => src/webauthn/public_key_credential/rp_entity.cr +7 -5
@@ 1,8 1,10 @@
class WebAuthn::PublicKeyCredential::RPEntity < WebAuthn::PublicKeyCredential::Entity
  include JSON::Serializable
module WebAuthn
  module PublicKeyCredential
    class RPEntity < Entity
      getter id : String

  getter id : String

  def initialize(@name, @id)
      def initialize(@name, @id)
      end
    end
  end
end

M src/webauthn/public_key_credential/user.cr => src/webauthn/public_key_credential/user.cr +10 -8
@@ 1,12 1,14 @@
class WebAuthn::PublicKeyCredential::User < WebAuthn::PublicKeyCredential::Entity
  include JSON::Serializable
module WebAuthn
  module PublicKeyCredential
    class User < Entity
      @[JSON::Field(key: "id", converter: WebAuthn::Base64)]
      getter id : String

  @[JSON::Field(key: "id", converter: WebAuthn::Base64)]
  getter id : String
      @[JSON::Field(key: "displayName")]
      getter display_name : String

  @[JSON::Field(key: "displayName")]
  getter display_name : String

  def initialize(@id, @name, @display_name)
      def initialize(@id, @name, @display_name)
      end
    end
  end
end