Class: A2A::Client::Auth::OAuth2

Inherits:
Object
  • Object
show all
Defined in:
lib/a2a/client/auth/oauth2.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client_id:, client_secret:, token_url:, scope: nil) ⇒ OAuth2

Initialize OAuth2 authentication

Parameters:

  • OAuth2 client ID

  • OAuth2 client secret

  • OAuth2 token endpoint URL

  • (defaults to: nil)

    Optional scope for the token



26
27
28
29
30
31
32
33
34
# File 'lib/a2a/client/auth/oauth2.rb', line 26

def initialize(client_id:, client_secret:, token_url:, scope: nil)
  @client_id = client_id
  @client_secret = client_secret
  @token_url = token_url
  @scope = scope
  @access_token = nil
  @expires_at = nil
  @token_mutex = Mutex.new
end

Instance Attribute Details

#access_tokenObject (readonly)

Returns the value of attribute access_token.



17
18
19
# File 'lib/a2a/client/auth/oauth2.rb', line 17

def access_token
  @access_token
end

#client_idObject (readonly)

Returns the value of attribute client_id.



17
18
19
# File 'lib/a2a/client/auth/oauth2.rb', line 17

def client_id
  @client_id
end

#client_secretObject (readonly)

Returns the value of attribute client_secret.



17
18
19
# File 'lib/a2a/client/auth/oauth2.rb', line 17

def client_secret
  @client_secret
end

#expires_atObject (readonly)

Returns the value of attribute expires_at.



17
18
19
# File 'lib/a2a/client/auth/oauth2.rb', line 17

def expires_at
  @expires_at
end

#scopeObject (readonly)

Returns the value of attribute scope.



17
18
19
# File 'lib/a2a/client/auth/oauth2.rb', line 17

def scope
  @scope
end

#token_urlObject (readonly)

Returns the value of attribute token_url.



17
18
19
# File 'lib/a2a/client/auth/oauth2.rb', line 17

def token_url
  @token_url
end

Instance Method Details

#apply_to_request(request) ⇒ Object

Apply authentication to a Faraday request

Parameters:

  • The request to authenticate



59
60
61
# File 'lib/a2a/client/auth/oauth2.rb', line 59

def apply_to_request(request)
  request.headers["Authorization"] = authorization_header
end

#authorization_headerString

Get authorization header value

Returns:

  • The authorization header value



51
52
53
# File 'lib/a2a/client/auth/oauth2.rb', line 51

def authorization_header
  "Bearer #{token}"
end

#clear_token!Object

Clear the current token (force re-authentication)



83
84
85
86
87
88
# File 'lib/a2a/client/auth/oauth2.rb', line 83

def clear_token!
  @token_mutex.synchronize do
    @access_token = nil
    @expires_at = nil
  end
end

#refresh_tokenObject (private)

Refresh the access token using client credentials flow



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/a2a/client/auth/oauth2.rb', line 105

def refresh_token
  connection = Faraday.new do |conn|
    conn.request :url_encoded
    conn.response :json
    conn.adapter Faraday.default_adapter
  end

  # Prepare request parameters
  params = {
    grant_type: "client_credentials",
    client_id: @client_id,
    client_secret: @client_secret
  }
  params[:scope] = @scope if @scope

  # Make token request
  response = connection.post(@token_url, params)

  unless response.success?
    raise A2A::Errors::AuthenticationError, "OAuth2 token request failed: #{response.status} - #{response.body}"
  end

  token_data = response.body

  unless token_data["access_token"]
    raise A2A::Errors::AuthenticationError, "OAuth2 response missing access_token: #{token_data}"
  end

  @access_token = token_data["access_token"]

  # Calculate expiration time
  expires_in = token_data["expires_in"]&.to_i || 3600 # Default to 1 hour
  @expires_at = Time.now + expires_in

  @access_token
rescue Faraday::Error => e
  raise A2A::Errors::AuthenticationError, "OAuth2 token request failed: #{e.message}"
end

#refresh_token!String

Force refresh the access token

Returns:

  • The new access token



75
76
77
78
79
# File 'lib/a2a/client/auth/oauth2.rb', line 75

def refresh_token!
  @token_mutex.synchronize do
    refresh_token
  end
end

#tokenString

Get a valid access token, refreshing if necessary

Returns:

  • The access token



40
41
42
43
44
45
# File 'lib/a2a/client/auth/oauth2.rb', line 40

def token
  @token_mutex.synchronize do
    refresh_token if token_expired?
    @access_token
  end
end

#token_expired?Boolean (private)

Check if the token is expired

Returns:

  • True if token is expired or will expire soon



96
97
98
99
100
101
# File 'lib/a2a/client/auth/oauth2.rb', line 96

def token_expired?
  return true unless @expires_at

  # Consider token expired if it expires within 30 seconds
  Time.now >= (@expires_at - 30)
end

#token_valid?Boolean

Check if the current token is valid

Returns:

  • True if token is valid and not expired



67
68
69
# File 'lib/a2a/client/auth/oauth2.rb', line 67

def token_valid?
  @access_token && !token_expired?
end