Module: Pray::AuthClient
- Defined in:
- lib/pray/auth_client.rb
Class Method Summary collapse
- .login_with_passkey(server_url, credential_id, private_key_path, session_root, email:) ⇒ Object
- .login_with_ssh_agent(server_url, public_key_path, session_root, email:) ⇒ Object
- .persist_login(server_url, response, email, kind, fingerprint, session_root) ⇒ Object
- .post_json(url, body) ⇒ Object
- .sign_ed25519(seed, message) ⇒ Object
- .trim_slash(value) ⇒ Object
Class Method Details
.login_with_passkey(server_url, credential_id, private_key_path, session_root, email:) ⇒ Object
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/pray/auth_client.rb', line 13 def login_with_passkey(server_url, credential_id, private_key_path, session_root, email:) challenge = post_json( "#{trim_slash(server_url)}/v1/auth/passkeys/challenge", {"credential_id" => credential_id} ) seed = File.binread(private_key_path) unless seed.bytesize == 32 raise Error.unsupported("passkey private key must be 32 raw bytes") end signature = Base64.strict_encode64(sign_ed25519(seed, challenge["challenge"].to_s)) response = post_json( "#{trim_slash(server_url)}/v1/auth/passkeys/login", { "credential_id" => credential_id, "challenge_id" => challenge["challenge_id"], "signature" => signature } ) persist_login(server_url, response, email, "passkey", nil, session_root) end |
.login_with_ssh_agent(server_url, public_key_path, session_root, email:) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/pray/auth_client.rb', line 35 def login_with_ssh_agent(server_url, public_key_path, session_root, email:) public_key = File.read(public_key_path).strip challenge = post_json( "#{trim_slash(server_url)}/v1/auth/ssh-keys/challenge", {"public_key" => public_key} ) signature = SshAgent.sign(public_key, challenge["challenge"].to_s) response = post_json( "#{trim_slash(server_url)}/v1/auth/ssh-keys/login", { "public_key" => public_key, "challenge_id" => challenge["challenge_id"], "signature" => signature } ) persist_login( server_url, response, email, "ssh_key", challenge["fingerprint"], session_root ) end |
.persist_login(server_url, response, email, kind, fingerprint, session_root) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/pray/auth_client.rb', line 55 def persist_login(server_url, response, email, kind, fingerprint, session_root) response_email = response["email"].to_s unless response_email == email raise Error.resolution( "login email mismatch: expected #{email}, got #{response_email}" ) end Session.persist( session_root, SessionFile.new( server_url: server_url, email: response_email, token: response["token"].to_s, kind: kind, signer_fingerprint: fingerprint ) ) end |
.post_json(url, body) ⇒ Object
86 87 88 89 90 91 |
# File 'lib/pray/auth_client.rb', line 86 def post_json(url, body) response = Registry.http_post(url, "application/json", JSON.generate(body)) JSON.parse(response) rescue JSON::ParserError => error raise Error.parse("auth response", error.) end |
.sign_ed25519(seed, message) ⇒ Object
75 76 77 78 79 80 81 82 83 84 |
# File 'lib/pray/auth_client.rb', line 75 def sign_ed25519(seed, ) unless OpenSSL::PKey.respond_to?(:generate_key) raise Error.unsupported("OpenSSL Ed25519 support is required for passkey login") end key = OpenSSL::PKey.new_raw_private_key("ED25519", seed) key.sign(nil, ) rescue OpenSSL::PKey::PKeyError => error raise Error.unsupported("OpenSSL Ed25519 signing failed: #{error.}") end |
.trim_slash(value) ⇒ Object
93 94 95 |
# File 'lib/pray/auth_client.rb', line 93 def trim_slash(value) value.to_s.sub(%r{/+\z}, "") end |