Module: Legate::Auth
- Defined in:
- lib/legate/auth.rb,
lib/legate/auth/error.rb,
lib/legate/auth/config.rb,
lib/legate/auth/runner.rb,
lib/legate/auth/scheme.rb,
lib/legate/auth/manager.rb,
lib/legate/auth/schemes.rb,
lib/legate/auth/url_guard.rb,
lib/legate/auth/credential.rb,
lib/legate/auth/encryption.rb,
lib/legate/auth/coordinator.rb,
lib/legate/auth/token_store.rb,
lib/legate/auth/manager_store.rb,
lib/legate/auth/token_manager.rb,
lib/legate/auth/schemes/oauth2.rb,
lib/legate/auth/schemes/api_key.rb,
lib/legate/auth/excon_middleware.rb,
lib/legate/auth/tool_integration.rb,
lib/legate/auth/http_client_utils.rb,
lib/legate/auth/middleware_factory.rb,
lib/legate/auth/schemes/http_bearer.rb,
lib/legate/auth/exchanged_credential.rb,
lib/legate/auth/schemes/openid_connect.rb,
lib/legate/auth/tool_context_extension.rb,
lib/legate/auth/schemes/service_account.rb,
lib/legate/auth/coordinators/oidc_coordinator.rb,
lib/legate/auth/schemes/google_service_account.rb,
lib/legate/auth/coordinators/oauth2_coordinator.rb,
lib/legate/auth/coordinators/service_account_coordinator.rb
Overview
The Auth module provides authentication capabilities for Legate tools. It supports various authentication schemes such as API Key, Bearer Token, OAuth2, OpenID Connect, and Service Accounts.
Defined Under Namespace
Modules: Coordinators, Encryption, HttpClientUtils, ManagerStore, Schemes, ToolContextExtension, ToolIntegration, UrlGuard Classes: Config, ConfigurationError, Coordinator, Credential, CredentialError, EnvironmentVariableNotFoundError, Error, ExchangedCredential, ExconMiddleware, Manager, MiddlewareFactory, ProviderError, Runner, Scheme, SchemeValidationError, TokenExchangeError, TokenManager, TokenRefreshError, TokenRevocationError, TokenStore
Constant Summary collapse
- VERSION =
Version of the authentication module
'0.1.0'
Class Attribute Summary collapse
-
.token_store ⇒ Legate::Auth::TokenStore
Get the global token store instance.
Class Method Summary collapse
-
.apply_authentication(request, credential, scheme = nil) ⇒ Hash
Apply authentication to a request.
-
.authenticate_with_coordinator(coordinator) ⇒ Legate::Auth::ExchangedCredential
Authenticate using a coordinator.
-
.complete_oauth_flow(provider_id, response_uri = nil) ⇒ Legate::Auth::ExchangedCredential
Complete the OAuth2 flow with a callback URI.
-
.configure_connection(connection, scheme:, credential:, **options) ⇒ Excon::Connection
Configure an existing Excon connection with authentication.
-
.create_api_key_connection(url, api_key:, location: 'header', name: 'X-API-Key', **options) ⇒ Excon::Connection
Create a new Excon connection with API key authentication.
-
.create_basic_auth_connection(url, username:, password:, **options) ⇒ Excon::Connection
Create a new Excon connection with Basic authentication.
-
.create_bearer_connection(url, token:, **options) ⇒ Excon::Connection
Create a new Excon connection with bearer token authentication.
-
.create_connection(url, scheme:, credential:, **options) ⇒ Excon::Connection
Create a new Excon connection with authentication.
-
.create_connection_from_provider(url, provider_id, **options) ⇒ Excon::Connection
Create a new Excon connection using a previously configured provider.
-
.create_middleware(scheme:, credential:, **options) ⇒ Legate::Auth::ExconMiddleware
Create an authentication middleware for the specified scheme and credential.
-
.create_oauth2_connection(url, client_id:, client_secret:, authorization_url:, token_url:, scopes: nil, **options) ⇒ Excon::Connection
Create a new Excon connection with OAuth2 authentication.
-
.create_oidc_connection(url, client_id:, client_secret:, discovery_url:, **options) ⇒ Excon::Connection
Create a new Excon connection with OpenID Connect authentication.
-
.create_service_account_connection(url, service_account_key:, scopes: nil, audience: nil, **options) ⇒ Excon::Connection
Create a new Excon connection with service account authentication.
-
.exchange_oauth_code(provider_id, response_uri) ⇒ Legate::Auth::ExchangedCredential
Exchange an authorization code for tokens.
-
.generate_request_id ⇒ String
Generate a unique request ID.
-
.get_exchanged_credential(provider_id) ⇒ Legate::Auth::ExchangedCredential?
Get a stored exchanged credential for a provider.
-
.handle_oauth_callback(response_uri) ⇒ Boolean
Handle an OAuth callback.
-
.refresh_token(provider_id) ⇒ Legate::Auth::ExchangedCredential
Refresh an access token.
-
.start_oauth_flow(provider_id, scheme, credential, redirect_uri = nil, options = {}) ⇒ String
Start the OAuth2 authentication flow.
-
.wait_for_oauth_callback(timeout = nil) ⇒ String?
Wait for the OAuth callback to be received.
Class Attribute Details
.token_store ⇒ Legate::Auth::TokenStore
Get the global token store instance
270 271 272 |
# File 'lib/legate/auth.rb', line 270 def token_store @token_store end |
Class Method Details
.apply_authentication(request, credential, scheme = nil) ⇒ Hash
Apply authentication to a request
77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/legate/auth.rb', line 77 def apply_authentication(request, credential, scheme = nil) if credential.is_a?(ExchangedCredential) && credential.provider_id # Look up the scheme from the stored config scheme ||= get_scheme_for_provider(credential.provider_id) end raise Legate::Auth::CredentialError, 'Authentication scheme is required' unless scheme # Apply the authentication to the request scheme.apply_to_request(request, credential) end |
.authenticate_with_coordinator(coordinator) ⇒ Legate::Auth::ExchangedCredential
Authenticate using a coordinator
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/legate/auth.rb', line 93 def authenticate_with_coordinator(coordinator) # Start the authentication flow auth_request = coordinator.start # For non-interactive coordinators, the result might be available immediately if coordinator.complete? return coordinator.result if coordinator.success? raise coordinator.error || Legate::Auth::Error.new('Authentication failed') end # For interactive coordinators, we need to wait for user interaction # This method should only be used with non-interactive coordinators # or in testing scenarios where we can directly resume the coordinator raise Legate::Auth::Error.new('Coordinator requires interaction but no handler provided') rescue StandardError => e # Wrap any errors that aren't already Legate::Auth::Error raise e.is_a?(Legate::Auth::Error) ? e : Legate::Auth::Error.new(e.) end |
.complete_oauth_flow(provider_id, response_uri = nil) ⇒ Legate::Auth::ExchangedCredential
Complete the OAuth2 flow with a callback URI
218 219 220 221 222 223 224 225 226 |
# File 'lib/legate/auth.rb', line 218 def complete_oauth_flow(provider_id, response_uri = nil) # If no response URI is provided, wait for the callback response_uri ||= wait_for_oauth_callback raise Legate::Auth::ConfigurationError, 'No response URI provided or received' unless response_uri # Exchange the code for tokens exchange_oauth_code(provider_id, response_uri) end |
.configure_connection(connection, scheme:, credential:, **options) ⇒ Excon::Connection
Configure an existing Excon connection with authentication
297 298 299 300 301 302 303 304 305 306 |
# File 'lib/legate/auth.rb', line 297 def configure_connection(connection, scheme:, credential:, **) Legate::Auth::HttpClientUtils.configure_connection( connection, scheme: scheme, credential: credential, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.create_api_key_connection(url, api_key:, location: 'header', name: 'X-API-Key', **options) ⇒ Excon::Connection
Create a new Excon connection with API key authentication
332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/legate/auth.rb', line 332 def create_api_key_connection(url, api_key:, location: 'header', name: 'X-API-Key', **) Legate::Auth::HttpClientUtils.create_api_key_connection( url, api_key: api_key, location: location, name: name, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.create_basic_auth_connection(url, username:, password:, **options) ⇒ Excon::Connection
Create a new Excon connection with Basic authentication
426 427 428 429 430 431 432 433 434 435 |
# File 'lib/legate/auth.rb', line 426 def create_basic_auth_connection(url, username:, password:, **) Legate::Auth::HttpClientUtils.create_basic_auth_connection( url, username: username, password: password, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.create_bearer_connection(url, token:, **options) ⇒ Excon::Connection
Create a new Excon connection with bearer token authentication
349 350 351 352 353 354 355 356 357 |
# File 'lib/legate/auth.rb', line 349 def create_bearer_connection(url, token:, **) Legate::Auth::HttpClientUtils.create_bearer_connection( url, token: token, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.create_connection(url, scheme:, credential:, **options) ⇒ Excon::Connection
Create a new Excon connection with authentication
314 315 316 317 318 319 320 321 322 323 |
# File 'lib/legate/auth.rb', line 314 def create_connection(url, scheme:, credential:, **) Legate::Auth::HttpClientUtils.create_connection( url, scheme: scheme, credential: credential, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.create_connection_from_provider(url, provider_id, **options) ⇒ Excon::Connection
Create a new Excon connection using a previously configured provider
442 443 444 445 446 447 448 449 450 |
# File 'lib/legate/auth.rb', line 442 def create_connection_from_provider(url, provider_id, **) Legate::Auth::HttpClientUtils.create_connection_from_provider( url, provider_id, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.create_middleware(scheme:, credential:, **options) ⇒ Legate::Auth::ExconMiddleware
Create an authentication middleware for the specified scheme and credential
281 282 283 284 285 286 287 288 289 |
# File 'lib/legate/auth.rb', line 281 def create_middleware(scheme:, credential:, **) Legate::Auth::MiddlewareFactory.create( scheme: scheme, credential: credential, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.create_oauth2_connection(url, client_id:, client_secret:, authorization_url:, token_url:, scopes: nil, **options) ⇒ Excon::Connection
Create a new Excon connection with OAuth2 authentication
368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'lib/legate/auth.rb', line 368 def create_oauth2_connection(url, client_id:, client_secret:, authorization_url:, token_url:, scopes: nil, **) Legate::Auth::HttpClientUtils.create_oauth2_connection( url, client_id: client_id, client_secret: client_secret, authorization_url: , token_url: token_url, scopes: scopes, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.create_oidc_connection(url, client_id:, client_secret:, discovery_url:, **options) ⇒ Excon::Connection
Create a new Excon connection with OpenID Connect authentication
389 390 391 392 393 394 395 396 397 398 399 |
# File 'lib/legate/auth.rb', line 389 def create_oidc_connection(url, client_id:, client_secret:, discovery_url:, **) Legate::Auth::HttpClientUtils.create_oidc_connection( url, client_id: client_id, client_secret: client_secret, discovery_url: discovery_url, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.create_service_account_connection(url, service_account_key:, scopes: nil, audience: nil, **options) ⇒ Excon::Connection
Create a new Excon connection with service account authentication
408 409 410 411 412 413 414 415 416 417 418 |
# File 'lib/legate/auth.rb', line 408 def create_service_account_connection(url, service_account_key:, scopes: nil, audience: nil, **) Legate::Auth::HttpClientUtils.create_service_account_connection( url, service_account_key: service_account_key, scopes: scopes, audience: audience, token_store: [:token_store] || token_store, token_manager: [:token_manager], ** ) end |
.exchange_oauth_code(provider_id, response_uri) ⇒ Legate::Auth::ExchangedCredential
Exchange an authorization code for tokens
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/legate/auth.rb', line 176 def exchange_oauth_code(provider_id, response_uri) config = @config_store[provider_id] raise Legate::Auth::ConfigurationError, "No stored configuration for provider #{provider_id}" unless config # Create a response config with the response URI response_config = Config.new( scheme: config.scheme, credential: config.credential, auth_request_id: config.auth_request_id ) response_config.response_uri = response_uri response_config.state = config.state # Validate the response config.validate_response!(response_config) # Exchange the code for tokens exchanged_credential = config.scheme.exchange_token(response_config, config.credential) # Add the provider ID to the credential exchanged_credential.provider_id = provider_id # Store the credential in the token store @token_store.store(provider_id, exchanged_credential) exchanged_credential end |
.generate_request_id ⇒ String
Generate a unique request ID
66 67 68 69 |
# File 'lib/legate/auth.rb', line 66 def generate_request_id require 'securerandom' SecureRandom.uuid end |
.get_exchanged_credential(provider_id) ⇒ Legate::Auth::ExchangedCredential?
Get a stored exchanged credential for a provider
208 209 210 |
# File 'lib/legate/auth.rb', line 208 def get_exchanged_credential(provider_id) @token_store.retrieve(provider_id) end |
.handle_oauth_callback(response_uri) ⇒ Boolean
Handle an OAuth callback
139 140 141 142 143 144 145 146 |
# File 'lib/legate/auth.rb', line 139 def handle_oauth_callback(response_uri) @oauth_mutex.synchronize do @oauth_response_uri = response_uri @oauth_condition.signal end true end |
.refresh_token(provider_id) ⇒ Legate::Auth::ExchangedCredential
Refresh an access token
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/legate/auth.rb', line 232 def refresh_token(provider_id) # Get the stored credential exchanged_credential = get_exchanged_credential(provider_id) raise Legate::Auth::TokenRefreshError, "No stored credential for provider #{provider_id}" unless exchanged_credential # Get the scheme scheme = get_scheme_for_provider(provider_id) raise Legate::Auth::TokenRefreshError, "Scheme for provider #{provider_id} does not support token refresh" unless scheme && scheme.supports_refresh? # Get the original credential config = @config_store[provider_id] raise Legate::Auth::TokenRefreshError, "No stored configuration for provider #{provider_id}" unless config # Refresh the token refreshed_credential = scheme.refresh_token(exchanged_credential, config.credential) # Add the provider ID to the credential refreshed_credential.provider_id = provider_id # Store the refreshed credential @token_store.store(provider_id, refreshed_credential) refreshed_credential end |
.start_oauth_flow(provider_id, scheme, credential, redirect_uri = nil, options = {}) ⇒ String
Start the OAuth2 authentication flow
122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/legate/auth.rb', line 122 def start_oauth_flow(provider_id, scheme, credential, redirect_uri = nil, = {}) # Create a new config config = Config.new(scheme: scheme, credential: credential, options: ) # Build the authorization URI auth_uri = config.(redirect_uri) # Store the config @config_store[provider_id] = config auth_uri end |
.wait_for_oauth_callback(timeout = nil) ⇒ String?
Wait for the OAuth callback to be received
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/legate/auth.rb', line 151 def wait_for_oauth_callback(timeout = nil) response_uri = nil @oauth_mutex.synchronize do if timeout # Wait with timeout @oauth_condition.wait(@oauth_mutex, timeout) if @oauth_response_uri.nil? else # Wait indefinitely @oauth_condition.wait(@oauth_mutex) while @oauth_response_uri.nil? end response_uri = @oauth_response_uri @oauth_response_uri = nil end response_uri end |