Class: Ask::Auth::Providers::OAuth
- Inherits:
-
Object
- Object
- Ask::Auth::Providers::OAuth
- Defined in:
- lib/ask/auth/providers/oauth.rb
Overview
PKCE OAuth flow for interactive credential authorization.
This provider implements the OAuth interface. The full interactive flow can be deferred — the interface is wired for integration and the PKCE utility methods are ready.
provider = Ask::Auth::Providers::OAuth.new(storage: database_provider)
url = provider.(user: current_user)
# redirect user to url, then:
provider.(user: current_user, code: params[:code])
Instance Method Summary collapse
-
#authorize!(user:, code:) ⇒ Object
Exchange an authorization code for tokens.
-
#authorize_url(user:, verifier: nil, state: nil) ⇒ Object
Returns the authorization URL to redirect the user to.
-
#call(name, user: nil) ⇒ Object
Returns nil (no automatic resolution) — OAuth requires interactive flow.
-
#generate_code_challenge(verifier) ⇒ Object
Generate a PKCE code challenge (SHA256 base64 digest of verifier).
-
#generate_code_verifier ⇒ Object
Generate a PKCE code verifier (128-char alphanumeric string).
-
#initialize(storage: nil, client_id: nil, authorize_url: nil, token_url: nil) ⇒ OAuth
constructor
A new instance of OAuth.
Constructor Details
#initialize(storage: nil, client_id: nil, authorize_url: nil, token_url: nil) ⇒ OAuth
Returns a new instance of OAuth.
21 22 23 24 25 26 |
# File 'lib/ask/auth/providers/oauth.rb', line 21 def initialize(storage: nil, client_id: nil, authorize_url: nil, token_url: nil) @storage = storage @client_id = client_id @authorize_url = @token_url = token_url end |
Instance Method Details
#authorize!(user:, code:) ⇒ Object
Exchange an authorization code for tokens.
user-
The user to associate the credential with
code-
The authorization code from the redirect
73 74 75 |
# File 'lib/ask/auth/providers/oauth.rb', line 73 def (user:, code:) raise NotImplementedError, "Token exchange requires a configured token_url and client_id" end |
#authorize_url(user:, verifier: nil, state: nil) ⇒ Object
Returns the authorization URL to redirect the user to.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/ask/auth/providers/oauth.rb', line 47 def (user:, verifier: nil, state: nil) verifier ||= generate_code_verifier state ||= SecureRandom.hex(16) challenge = generate_code_challenge(verifier) # Store state and verifier for this user (requires a storage provider) if @storage && user @storage.call(:oauth_state, user: user) end uri = URI.parse(@authorize_url || "https://example.com/oauth/authorize") uri.query = URI.encode_www_form( response_type: "code", client_id: @client_id || "YOUR_CLIENT_ID", redirect_uri: "urn:ietf:wg:oauth:2.0:oob", scope: "", state: state, code_challenge: challenge, code_challenge_method: "S256" ) uri.to_s end |
#call(name, user: nil) ⇒ Object
Returns nil (no automatic resolution) — OAuth requires interactive flow.
29 30 31 |
# File 'lib/ask/auth/providers/oauth.rb', line 29 def call(name, user: nil) nil end |
#generate_code_challenge(verifier) ⇒ Object
Generate a PKCE code challenge (SHA256 base64 digest of verifier).
39 40 41 42 43 44 |
# File 'lib/ask/auth/providers/oauth.rb', line 39 def generate_code_challenge(verifier) ::Base64.urlsafe_encode64( OpenSSL::Digest.digest("SHA256", verifier), padding: false ) end |
#generate_code_verifier ⇒ Object
Generate a PKCE code verifier (128-char alphanumeric string).
34 35 36 |
# File 'lib/ask/auth/providers/oauth.rb', line 34 def generate_code_verifier SecureRandom.alphanumeric(128) end |