Module: Keycardai::OAuth::PKCE
- Defined in:
- lib/keycardai/oauth/pkce.rb
Overview
PKCE primitives (RFC 7636): generate a code verifier and derive its challenge. S256 is the default and the method public clients should use; plain is RFC-permitted but not recommended.
Defined Under Namespace
Classes: Pair
Constant Summary collapse
- VERIFIER_CHARSET =
[*"A".."Z", *"a".."z", *"0".."9", "-", ".", "_", "~"].freeze
- DEFAULT_VERIFIER_LENGTH =
128- METHODS =
%w[S256 plain].freeze
Class Method Summary collapse
-
.generate_code_challenge(code_verifier, method: "S256") ⇒ String
Derive the challenge for a verifier (RFC 7636 §4.2).
-
.generate_code_verifier(length: DEFAULT_VERIFIER_LENGTH) ⇒ String
Generate a cryptographically random verifier (RFC 7636 §4.1).
-
.generate_pair(length: DEFAULT_VERIFIER_LENGTH, method: "S256") ⇒ Pair
Generate a verifier and its challenge together.
Class Method Details
.generate_code_challenge(code_verifier, method: "S256") ⇒ String
Derive the challenge for a verifier (RFC 7636 §4.2).
36 37 38 39 40 41 42 43 44 45 |
# File 'lib/keycardai/oauth/pkce.rb', line 36 def generate_code_challenge(code_verifier, method: "S256") case method when "S256" [OpenSSL::Digest.digest("SHA256", code_verifier)].pack("m0").tr("+/", "-_").delete("=") when "plain" code_verifier else raise ArgumentError, "unsupported code_challenge_method #{method.inspect}" end end |
.generate_code_verifier(length: DEFAULT_VERIFIER_LENGTH) ⇒ String
Generate a cryptographically random verifier (RFC 7636 §4.1).
25 26 27 28 29 |
# File 'lib/keycardai/oauth/pkce.rb', line 25 def generate_code_verifier(length: DEFAULT_VERIFIER_LENGTH) raise ArgumentError, "verifier length must be between 43 and 128, got #{length}" unless (43..128).cover?(length) Array.new(length) { VERIFIER_CHARSET[SecureRandom.random_number(VERIFIER_CHARSET.length)] }.join end |
.generate_pair(length: DEFAULT_VERIFIER_LENGTH, method: "S256") ⇒ Pair
Generate a verifier and its challenge together.
52 53 54 55 56 57 58 59 |
# File 'lib/keycardai/oauth/pkce.rb', line 52 def generate_pair(length: DEFAULT_VERIFIER_LENGTH, method: "S256") code_verifier = generate_code_verifier(length: length) Pair.new( code_verifier: code_verifier, code_challenge: generate_code_challenge(code_verifier, method: method), code_challenge_method: method ) end |