atproto_auth 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +16 -0
  3. data/CHANGELOG.md +5 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +179 -0
  6. data/Rakefile +16 -0
  7. data/examples/confidential_client/Gemfile +12 -0
  8. data/examples/confidential_client/Gemfile.lock +84 -0
  9. data/examples/confidential_client/README.md +110 -0
  10. data/examples/confidential_client/app.rb +136 -0
  11. data/examples/confidential_client/config/client-metadata.json +25 -0
  12. data/examples/confidential_client/config.ru +4 -0
  13. data/examples/confidential_client/public/client-metadata.json +24 -0
  14. data/examples/confidential_client/public/styles.css +70 -0
  15. data/examples/confidential_client/scripts/generate_keys.rb +15 -0
  16. data/examples/confidential_client/views/authorized.erb +29 -0
  17. data/examples/confidential_client/views/index.erb +44 -0
  18. data/examples/confidential_client/views/layout.erb +11 -0
  19. data/lib/atproto_auth/client.rb +410 -0
  20. data/lib/atproto_auth/client_metadata.rb +264 -0
  21. data/lib/atproto_auth/configuration.rb +17 -0
  22. data/lib/atproto_auth/dpop/client.rb +122 -0
  23. data/lib/atproto_auth/dpop/key_manager.rb +235 -0
  24. data/lib/atproto_auth/dpop/nonce_manager.rb +138 -0
  25. data/lib/atproto_auth/dpop/proof_generator.rb +112 -0
  26. data/lib/atproto_auth/errors.rb +47 -0
  27. data/lib/atproto_auth/http_client.rb +227 -0
  28. data/lib/atproto_auth/identity/document.rb +104 -0
  29. data/lib/atproto_auth/identity/resolver.rb +221 -0
  30. data/lib/atproto_auth/identity.rb +24 -0
  31. data/lib/atproto_auth/par/client.rb +203 -0
  32. data/lib/atproto_auth/par/client_assertion.rb +50 -0
  33. data/lib/atproto_auth/par/request.rb +140 -0
  34. data/lib/atproto_auth/par/response.rb +23 -0
  35. data/lib/atproto_auth/par.rb +40 -0
  36. data/lib/atproto_auth/pkce.rb +105 -0
  37. data/lib/atproto_auth/server_metadata/authorization_server.rb +175 -0
  38. data/lib/atproto_auth/server_metadata/origin_url.rb +51 -0
  39. data/lib/atproto_auth/server_metadata/resource_server.rb +71 -0
  40. data/lib/atproto_auth/server_metadata.rb +24 -0
  41. data/lib/atproto_auth/state/session.rb +117 -0
  42. data/lib/atproto_auth/state/session_manager.rb +75 -0
  43. data/lib/atproto_auth/state/token_set.rb +68 -0
  44. data/lib/atproto_auth/state.rb +54 -0
  45. data/lib/atproto_auth/version.rb +5 -0
  46. data/lib/atproto_auth.rb +56 -0
  47. data/sig/atproto_auth/client_metadata.rbs +95 -0
  48. data/sig/atproto_auth/dpop/client.rbs +38 -0
  49. data/sig/atproto_auth/dpop/key_manager.rbs +33 -0
  50. data/sig/atproto_auth/dpop/nonce_manager.rbs +48 -0
  51. data/sig/atproto_auth/dpop/proof_generator.rbs +42 -0
  52. data/sig/atproto_auth/http_client.rbs +58 -0
  53. data/sig/atproto_auth/identity/document.rbs +31 -0
  54. data/sig/atproto_auth/identity/resolver.rbs +41 -0
  55. data/sig/atproto_auth/par/client.rbs +31 -0
  56. data/sig/atproto_auth/par/request.rbs +73 -0
  57. data/sig/atproto_auth/par/response.rbs +17 -0
  58. data/sig/atproto_auth/pkce.rbs +24 -0
  59. data/sig/atproto_auth/server_metadata/authorization_server.rbs +69 -0
  60. data/sig/atproto_auth/server_metadata/origin_url.rbs +21 -0
  61. data/sig/atproto_auth/server_metadata/resource_server.rbs +27 -0
  62. data/sig/atproto_auth/state/session.rbs +50 -0
  63. data/sig/atproto_auth/state/session_manager.rbs +26 -0
  64. data/sig/atproto_auth/state/token_set.rbs +40 -0
  65. data/sig/atproto_auth/version.rbs +3 -0
  66. data/sig/atproto_auth.rbs +39 -0
  67. metadata +142 -0
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AtprotoAuth
4
+ # Manages OAuth state for AT Protocol authorization flows. This module provides thread-safe
5
+ # storage and management of authorization session data, including tokens, PKCE values,
6
+ # and identity information.
7
+ #
8
+ # The module consists of three main components:
9
+ #
10
+ # 1. {TokenSet} - Represents OAuth tokens (access and refresh) with their metadata,
11
+ # including expiration times, scope, and the authenticated user's DID.
12
+ #
13
+ # 2. {Session} - Tracks the complete state of an authorization flow, including:
14
+ # - PKCE verifier/challenge pairs
15
+ # - State tokens for request verification
16
+ # - Authorization server information
17
+ # - Current tokens and user identity (DID)
18
+ #
19
+ # 3. {SessionManager} - Provides thread-safe storage and retrieval of active sessions,
20
+ # with support for lookup by session ID or state token.
21
+ #
22
+ # @example Creating and managing a session
23
+ # manager = AtprotoAuth::State::SessionManager.new
24
+ #
25
+ # # Create a new session
26
+ # session = manager.create_session(
27
+ # client_id: "https://myapp.com/client-metadata.json",
28
+ # scope: "atproto"
29
+ # )
30
+ #
31
+ # # Update session with tokens
32
+ # tokens = TokenSet.new(
33
+ # access_token: "...",
34
+ # token_type: "DPoP",
35
+ # expires_in: 3600,
36
+ # scope: "atproto",
37
+ # sub: "did:plc:abcdef123"
38
+ # )
39
+ # session.tokens = tokens
40
+ #
41
+ # # Lookup session later
42
+ # session = manager.get_session(session_id)
43
+ # if session.authorized?
44
+ # puts "Access token: #{session.tokens.access_token}"
45
+ # end
46
+ #
47
+ # All classes in this module are thread-safe and can be used in concurrent environments.
48
+ # The module handles secure generation and validation of state tokens, and ensures
49
+ # consistency of session data through synchronized access.
50
+ module State
51
+ # Error raised for session-related issues
52
+ class SessionError < AtprotoAuth::Error; end
53
+ end
54
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AtprotoAuth
4
+ VERSION = "0.0.1"
5
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jose"
4
+ require "jwt"
5
+
6
+ require "atproto_auth/version"
7
+
8
+ require "atproto_auth/configuration"
9
+ require "atproto_auth/errors"
10
+ require "atproto_auth/client_metadata"
11
+ require "atproto_auth/http_client"
12
+ require "atproto_auth/pkce"
13
+
14
+ require "atproto_auth/server_metadata"
15
+ require "atproto_auth/server_metadata/origin_url"
16
+ require "atproto_auth/server_metadata/authorization_server"
17
+ require "atproto_auth/server_metadata/resource_server"
18
+
19
+ require "atproto_auth/dpop/key_manager"
20
+ require "atproto_auth/dpop/proof_generator"
21
+ require "atproto_auth/dpop/nonce_manager"
22
+ require "atproto_auth/dpop/client"
23
+
24
+ require "atproto_auth/state"
25
+ require "atproto_auth/state/token_set"
26
+ require "atproto_auth/state/session"
27
+ require "atproto_auth/state/session_manager"
28
+
29
+ require "atproto_auth/identity"
30
+ require "atproto_auth/identity/document"
31
+ require "atproto_auth/identity/resolver"
32
+
33
+ require "atproto_auth/par"
34
+ require "atproto_auth/par/client_assertion"
35
+ require "atproto_auth/par/request"
36
+ require "atproto_auth/par/response"
37
+ require "atproto_auth/par/client"
38
+
39
+ require "atproto_auth/client"
40
+
41
+ # AtprotoAuth is a Ruby library implementing the AT Protocol OAuth specification.
42
+ # It provides functionality for both client and server-side implementations of
43
+ # the AT Protocol OAuth flow, including support for DPoP, PAR, and dynamic client registration.
44
+ module AtprotoAuth
45
+ class << self
46
+ attr_writer :configuration
47
+
48
+ def configuration
49
+ @configuration ||= Configuration.new
50
+ end
51
+
52
+ def configure
53
+ yield(configuration)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,95 @@
1
+ module AtprotoAuth
2
+ # Handles and validates AT Protocol OAuth client metadata.
3
+ class ClientMetadata
4
+ @client_id: String
5
+
6
+ @grant_types: Array[String]
7
+
8
+ @response_types: Array[String]
9
+
10
+ @redirect_uris: Array[String]
11
+
12
+ @scope: String
13
+
14
+ @client_name: String?
15
+
16
+ @application_type: String
17
+
18
+ @client_uri: String?
19
+
20
+ @logo_uri: String?
21
+
22
+ @tos_uri: String?
23
+
24
+ @policy_uri: String?
25
+
26
+ @token_endpoint_auth_method: String?
27
+
28
+ @jwks: Hash[String, untyped]?
29
+
30
+ @jwks_uri: String?
31
+
32
+ attr_reader client_id: String
33
+ attr_reader grant_types: Array[String]
34
+ attr_reader response_types: Array[String]
35
+ attr_reader redirect_uris: Array[String]
36
+ attr_reader scope: String
37
+ attr_reader client_name: String?
38
+ attr_reader client_uri: String?
39
+ attr_reader logo_uri: String?
40
+ attr_reader tos_uri: String?
41
+ attr_reader policy_uri: String?
42
+ attr_reader token_endpoint_auth_method: String?
43
+ attr_reader jwks: Hash[String, untyped]?
44
+ attr_reader jwks_uri: String?
45
+ attr_reader application_type: String
46
+
47
+ def initialize: (Hash[String, untyped] metadata) -> void
48
+
49
+ def self.from_url: (String url) -> ClientMetadata
50
+
51
+ def confidential?: () -> bool
52
+
53
+ private
54
+
55
+ def validate_and_set_metadata!: (Hash[String, untyped] metadata) -> void
56
+
57
+ def validate_client_id!: (String client_id) -> String
58
+
59
+ def validate_grant_types!: (Array[String] grant_types) -> Array[String]
60
+
61
+ def validate_response_types!: (Array[String] response_types) -> Array[String]
62
+
63
+ def validate_redirect_uris!: (Array[String] uris) -> Array[String]
64
+
65
+ def validate_redirect_uri!: (URI uri) -> void
66
+
67
+ def validate_redirect_uri_origin!: (URI uri) -> void
68
+
69
+ def validate_native_redirect_uri!: (URI uri) -> void
70
+
71
+ def validate_custom_scheme!: (URI uri) -> void
72
+
73
+ def validate_scope!: (String scope) -> String
74
+
75
+ def validate_offline_access_scope!: (Array[String] scope_values) -> void
76
+
77
+ def validate_application_type: (String? type) -> String
78
+
79
+ def validate_client_uri: (String? uri) -> String?
80
+
81
+ def validate_https_uri: (String? uri) -> String?
82
+
83
+ def validate_auth_methods!: (Hash[String, untyped] metadata) -> void
84
+
85
+ def validate_dpop!: (Hash[String, untyped] metadata) -> void
86
+
87
+ def self.validate_url!: (String url) -> void
88
+
89
+ def self.fetch_metadata: (String url) -> Hash[Symbol, untyped]
90
+
91
+ def self.parse_metadata: (String body) -> Hash[String, untyped]
92
+
93
+ def self.validate_client_id!: (String metadata_client_id, String url) -> void
94
+ end
95
+ end
@@ -0,0 +1,38 @@
1
+ module AtprotoAuth
2
+ module DPoP
3
+ class Client
4
+ @key_manager: untyped
5
+
6
+ @nonce_manager: untyped
7
+
8
+ @proof_generator: untyped
9
+
10
+ class Error < AtprotoAuth::Error
11
+ end
12
+
13
+ attr_reader key_manager: untyped
14
+
15
+ attr_reader proof_generator: untyped
16
+
17
+ attr_reader nonce_manager: untyped
18
+
19
+ def initialize: (?key_manager: untyped?, ?nonce_ttl: untyped?) -> void
20
+
21
+ def generate_proof: (http_method: untyped, http_uri: untyped, ?access_token: untyped?) -> untyped
22
+
23
+ def process_response: (untyped response_headers, untyped server_url) -> untyped
24
+
25
+ def request_headers: (untyped proof) -> { "DPoP" => untyped }
26
+
27
+ def public_key: () -> untyped
28
+
29
+ def export_key: (?include_private: bool) -> untyped
30
+
31
+ private
32
+
33
+ def extract_nonce: (untyped headers) -> untyped
34
+
35
+ def origin_for_uri: (untyped uri) -> untyped
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ module AtprotoAuth
2
+ module DPoP
3
+ class KeyManager
4
+ @keypair: JOSE::JWK
5
+
6
+ class KeyError < AtprotoAuth::Error
7
+ end
8
+
9
+ CURVE: String
10
+ ALGORITHM: String
11
+
12
+ attr_reader keypair: JOSE::JWK
13
+
14
+ def initialize: (?JOSE::JWK keypair) -> void
15
+
16
+ def generate_keypair: () -> JOSE::JWK
17
+
18
+ def public_jwk: () -> Hash[String, untyped]
19
+
20
+ def sign: (String data) -> String
21
+
22
+ def verify: (String signature, String data) -> bool
23
+
24
+ def to_jwk: (?include_private: bool) -> Hash[String, untyped]
25
+
26
+ def self.from_jwk: (Hash[String, untyped] jwk) -> AtprotoAuth::DPoP::KeyManager
27
+
28
+ private
29
+
30
+ def validate_keypair!: () -> void
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,48 @@
1
+ module AtprotoAuth
2
+ module DPoP
3
+ class NonceManager
4
+ @ttl: Integer
5
+ @nonces: Hash[String, AtprotoAuth::DPoP::NonceManager::StoredNonce]
6
+ @monitor: Monitor
7
+
8
+ class NonceError < AtprotoAuth::Error
9
+ end
10
+
11
+ class StoredNonce
12
+ @value: String
13
+ @server_url: String
14
+ @timestamp: Integer
15
+
16
+ attr_reader value: String
17
+ attr_reader timestamp: Integer
18
+ attr_reader server_url: String
19
+
20
+ def initialize: (String value, String server_url) -> void
21
+
22
+ def expired?: (?Integer ttl) -> bool
23
+ end
24
+
25
+ DEFAULT_TTL: Integer
26
+
27
+ def initialize: (?ttl: Integer) -> void
28
+
29
+ def update: (nonce: String, server_url: String) -> void
30
+
31
+ def get: (String server_url) -> (nil | String)
32
+
33
+ def clear: (String server_url) -> void
34
+
35
+ def clear_all: () -> void
36
+
37
+ def server_urls: () -> Array[String]
38
+
39
+ def valid_nonce?: (String server_url) -> bool
40
+
41
+ private
42
+
43
+ def validate_inputs!: (String nonce, String server_url) -> void
44
+
45
+ def validate_server_url!: (String server_url) -> void
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,42 @@
1
+ module AtprotoAuth
2
+ module DPoP
3
+ class ProofGenerator
4
+ @key_manager: AtprotoAuth::DPoP::KeyManager
5
+
6
+ class ProofError < AtprotoAuth::Error
7
+ end
8
+
9
+ attr_reader key_manager: AtprotoAuth::DPoP::KeyManager
10
+
11
+ def initialize: (AtprotoAuth::DPoP::KeyManager key_manager) -> void
12
+
13
+ def generate: (
14
+ http_method: String,
15
+ http_uri: String,
16
+ ?nonce: String?,
17
+ ?access_token: String?,
18
+ ?ath: bool?
19
+ ) -> String
20
+
21
+ private
22
+
23
+ def validate_inputs!: (String http_method, String http_uri) -> void
24
+
25
+ def build_header: () -> { typ: "dpop+jwt", alg: "ES256", jwk: Hash[String, untyped] }
26
+
27
+ def build_payload: (
28
+ http_method: String,
29
+ http_uri: String,
30
+ nonce: String?,
31
+ access_token: String?,
32
+ include_ath: bool
33
+ ) -> Hash[Symbol, untyped]
34
+
35
+ def normalize_uri: (String uri) -> String
36
+
37
+ def generate_access_token_hash: (String access_token) -> String
38
+
39
+ def encode_jwt_segments: (Hash[Symbol, untyped] header, Hash[Symbol, untyped] payload) -> String
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,58 @@
1
+ module AtprotoAuth
2
+ class HttpClient
3
+ @timeout: Integer
4
+
5
+ @verify_ssl: bool
6
+
7
+ FORBIDDEN_IP_RANGES: ::Array[IPAddr]
8
+
9
+ ALLOWED_SCHEMES: ::Array[String]
10
+
11
+ DEFAULT_TIMEOUT: Integer
12
+
13
+ MAX_REDIRECTS: Integer
14
+
15
+ MAX_RESPONSE_SIZE: Integer
16
+
17
+ class SSRFError < Error
18
+ end
19
+
20
+ class HttpError < Error
21
+ @response: ::Net::HTTPResponse?
22
+
23
+ attr_reader response: ::Net::HTTPResponse?
24
+
25
+ def initialize: (String message, ::Net::HTTPResponse? response) -> void
26
+ end
27
+
28
+ def initialize: (?timeout: Integer, ?verify_ssl: bool) -> void
29
+
30
+ def get: (String url, ?::Hash[String, String] headers) -> { status: Integer, headers: ::Hash[String, String], body: String }
31
+
32
+ private
33
+
34
+ def validate_uri!: (String url) -> URI
35
+
36
+ def validate_ip!: (URI uri) -> nil
37
+
38
+ def resolve_ip: (String hostname) -> IPAddr
39
+
40
+ def forbidden_ip?: (IPAddr ip) -> bool
41
+
42
+ def make_request: (URI uri, ?::Hash[String, String] headers) -> ::Net::HTTPResponse
43
+
44
+ def configure_http_client!: (::Net::HTTP http) -> void
45
+
46
+ def add_security_headers!: (::Net::HTTP::Get request, ::Hash[String, String] headers) -> void
47
+
48
+ def handle_redirect: (URI original_uri, ::Net::HTTPResponse response, ::Hash[String, String] headers, ?::Integer redirect_count) -> ::Net::HTTPResponse
49
+
50
+ def validate_response!: (::Net::HTTPResponse response) -> void
51
+
52
+ def check_success_status!: (::Net::HTTPResponse response) -> nil
53
+
54
+ def check_content_length!: (::Net::HTTPResponse response) -> nil
55
+
56
+ def check_content_type!: (::Net::HTTPResponse response) -> nil
57
+ end
58
+ end
@@ -0,0 +1,31 @@
1
+ module AtprotoAuth
2
+ module Identity
3
+ class Document
4
+ @did: String
5
+ @rotation_keys: Array[String]
6
+ @also_known_as: Array[String]
7
+ @services: Array[Hash[String, untyped]]
8
+ @pds: String
9
+
10
+ attr_reader did: String
11
+ attr_reader rotation_keys: Array[String]
12
+ attr_reader also_known_as: Array[String]
13
+ attr_reader services: Array[Hash[String, untyped]]
14
+ attr_reader pds: String
15
+
16
+ def initialize: (Hash[String, untyped] data) -> void
17
+
18
+ def has_handle?: (String handle) -> bool
19
+
20
+ private
21
+
22
+ def validate_document!: (Hash[String, untyped] data) -> void
23
+
24
+ def validate_did!: (String did) -> void
25
+
26
+ def validate_services!: (Array[Hash[String, untyped]]? services) -> void
27
+
28
+ def extract_pds!: (Hash[String, untyped] data) -> String
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ module AtprotoAuth
2
+ module Identity
3
+ class Resolver
4
+ @plc_directory: String
5
+
6
+ PLC_DIRECTORY_URL: String
7
+ DID_PLC_PREFIX: String
8
+ HANDLE_REGEX: ::Regexp
9
+
10
+ def initialize: (?plc_directory: String?) -> void
11
+
12
+ def resolve_handle: (String handle) -> Hash[Symbol, untyped]
13
+
14
+ def get_did_info: (String did) -> Hash[Symbol, untyped]
15
+
16
+ def verify_pds_binding: (String did, String pds_url) -> bool
17
+
18
+ def verify_issuer_binding: (String did, String issuer) -> bool
19
+
20
+ def verify_handle_binding: (String handle, String did) -> bool
21
+
22
+ private
23
+
24
+ def validate_handle!: (String handle) -> void
25
+
26
+ def validate_did!: (String did) -> void
27
+
28
+ def normalize_handle: (String handle) -> String
29
+
30
+ def resolve_handle_dns: (String _handle) -> nil
31
+
32
+ def resolve_handle_http: (String handle) -> Hash[Symbol, untyped]
33
+
34
+ def fetch_did_document: (String did) -> Hash[String, untyped]
35
+
36
+ def validate_pds_url!: (String url) -> void
37
+
38
+ def normalize_url: (String url) -> String
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ module AtprotoAuth
2
+ module PAR
3
+ class Client
4
+ @endpoint: String
5
+
6
+ attr_reader endpoint: String
7
+
8
+ def initialize: (endpoint: String) -> void
9
+
10
+ def submit: (Request request) -> Response
11
+
12
+ def authorization_url: (
13
+ authorize_endpoint: String,
14
+ request_uri: String,
15
+ client_id: String
16
+ ) -> String
17
+
18
+ private
19
+
20
+ def validate_endpoint!: () -> void
21
+
22
+ def build_headers: (Request request) -> Hash[String, String]
23
+
24
+ def make_request: (Request request, Hash[String, String] headers) -> Hash[Symbol, untyped]
25
+
26
+ def process_response: (Hash[Symbol, untyped] response) -> Response
27
+
28
+ def encode_params: (Hash[String, String]) -> String
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,73 @@
1
+ module AtprotoAuth
2
+ module PAR
3
+ class Request
4
+ @response_type: String
5
+ @client_id: String
6
+ @redirect_uri: String
7
+ @code_challenge: String
8
+ @code_challenge_method: String
9
+ @state: String
10
+ @scope: String
11
+ @login_hint: String?
12
+ @nonce: String?
13
+ @dpop_proof: String?
14
+ @client_assertion_type: String?
15
+ @client_assertion: String?
16
+
17
+ class Configuration
18
+ attr_accessor client_id: String
19
+ attr_accessor redirect_uri: String
20
+ attr_accessor code_challenge: String
21
+ attr_accessor code_challenge_method: String
22
+ attr_accessor state: String
23
+ attr_accessor scope: String
24
+ attr_accessor login_hint: String?
25
+ attr_accessor nonce: String?
26
+ attr_accessor dpop_proof: String?
27
+ attr_accessor client_assertion_type: String?
28
+ attr_accessor client_assertion: String?
29
+ end
30
+
31
+ attr_reader response_type: String
32
+ attr_reader client_id: String
33
+ attr_reader code_challenge: String
34
+ attr_reader code_challenge_method: String
35
+ attr_reader state: String
36
+ attr_reader redirect_uri: String
37
+ attr_reader scope: String
38
+ attr_reader login_hint: String?
39
+ attr_reader nonce: String?
40
+ attr_reader dpop_proof: String?
41
+ attr_reader client_assertion_type: String?
42
+ attr_reader client_assertion: String?
43
+
44
+ def self.build: () { (Configuration) -> void } -> Request
45
+
46
+ def initialize: (Configuration config) -> void
47
+
48
+ def to_form: () -> String
49
+
50
+ private
51
+
52
+ def build_params: () -> Hash[String, String]
53
+
54
+ def add_optional_params: (Hash[String, String] params) -> void
55
+
56
+ def add_client_auth_params: (Hash[String, String] params) -> void
57
+
58
+ def validate!: () -> void
59
+
60
+ def validate_required_params!: () -> void
61
+
62
+ def validate_response_type!: () -> void
63
+
64
+ def validate_code_challenge_method!: () -> void
65
+
66
+ def validate_scope!: () -> void
67
+
68
+ def validate_client_auth!: () -> void
69
+
70
+ def encode_params: (Hash[String, String]) -> String
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,17 @@
1
+ module AtprotoAuth
2
+ module PAR
3
+ class Response
4
+ @request_uri: String
5
+ @expires_in: Integer
6
+
7
+ attr_reader request_uri: String
8
+ attr_reader expires_in: Integer
9
+
10
+ def initialize: (request_uri: String, expires_in: Integer) -> void
11
+
12
+ private
13
+
14
+ def validate!: () -> void
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ module AtprotoAuth
2
+ module PKCE
3
+ class Error < AtprotoAuth::Error
4
+ end
5
+
6
+ MIN_VERIFIER_LENGTH: Integer
7
+ MAX_VERIFIER_LENGTH: Integer
8
+ ALLOWED_VERIFIER_CHARS: ::Regexp
9
+
10
+ def self.generate_verifier: (?Integer length) -> String
11
+
12
+ def self.generate_challenge: (String verifier) -> String
13
+
14
+ def self.verify: (String challenge, String verifier) -> bool
15
+
16
+ private
17
+
18
+ def self.validate_verifier_length!: (Integer length) -> void
19
+
20
+ def self.validate_verifier!: (String verifier) -> void
21
+
22
+ def self.secure_compare: (String str1, String str2) -> bool
23
+ end
24
+ end