googleauth 1.8.0 → 1.15.0

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +117 -0
  3. data/Credentials.md +106 -0
  4. data/Errors.md +152 -0
  5. data/README.md +49 -1
  6. data/lib/googleauth/api_key.rb +164 -0
  7. data/lib/googleauth/application_default.rb +6 -8
  8. data/lib/googleauth/base_client.rb +21 -4
  9. data/lib/googleauth/bearer_token.rb +162 -0
  10. data/lib/googleauth/client_id.rb +9 -6
  11. data/lib/googleauth/compute_engine.rb +231 -49
  12. data/lib/googleauth/credentials.rb +187 -58
  13. data/lib/googleauth/credentials_loader.rb +11 -20
  14. data/lib/googleauth/default_credentials.rb +29 -8
  15. data/lib/googleauth/errors.rb +117 -0
  16. data/lib/googleauth/external_account/aws_credentials.rb +85 -18
  17. data/lib/googleauth/external_account/base_credentials.rb +67 -6
  18. data/lib/googleauth/external_account/external_account_utils.rb +15 -4
  19. data/lib/googleauth/external_account/identity_pool_credentials.rb +40 -15
  20. data/lib/googleauth/external_account/pluggable_credentials.rb +34 -19
  21. data/lib/googleauth/external_account.rb +32 -7
  22. data/lib/googleauth/helpers/connection.rb +7 -1
  23. data/lib/googleauth/iam.rb +19 -3
  24. data/lib/googleauth/id_tokens/errors.rb +13 -7
  25. data/lib/googleauth/id_tokens/key_sources.rb +13 -7
  26. data/lib/googleauth/id_tokens/verifier.rb +2 -3
  27. data/lib/googleauth/id_tokens.rb +4 -6
  28. data/lib/googleauth/impersonated_service_account.rb +329 -0
  29. data/lib/googleauth/json_key_reader.rb +13 -3
  30. data/lib/googleauth/oauth2/sts_client.rb +9 -4
  31. data/lib/googleauth/scope_util.rb +1 -1
  32. data/lib/googleauth/service_account.rb +84 -104
  33. data/lib/googleauth/service_account_jwt_header.rb +187 -0
  34. data/lib/googleauth/signet.rb +169 -4
  35. data/lib/googleauth/token_store.rb +3 -3
  36. data/lib/googleauth/user_authorizer.rb +89 -11
  37. data/lib/googleauth/user_refresh.rb +72 -9
  38. data/lib/googleauth/version.rb +1 -1
  39. data/lib/googleauth/web_user_authorizer.rb +65 -17
  40. data/lib/googleauth.rb +8 -0
  41. metadata +45 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 888e57705b33e87158d060b7b1569e54e00000428de35f979e7ffc9456cbb7b3
4
- data.tar.gz: ac341b6c481df125091c1465b56642173591f5698baff6f4806b05216eca8802
3
+ metadata.gz: 34a8ff0141f7866d8f253bea4adbdd406c8aab873c7f18be6ac78ee981e16a39
4
+ data.tar.gz: 1191ce29114f13eb0d855ef46502015eb309cf694bd053171614b15d571e15f7
5
5
  SHA512:
6
- metadata.gz: 0e9d2fd50c39bf83e86f9f31bbddb897d28ce908be1214849926c45ce7ad2fa0d8f48d70a01acc84c9fa49ddf1a3a3c0c5a87b9bdf1d3ae1b9430b739e709c67
7
- data.tar.gz: f92483b4971ecc9d48a0b3656a76c694974c6b60153d6ea5ff0f1dd6c544da51b924aedbfa71956db2c1dada98a6cdaa632bb6f38c663e384acc8ebb3af8d1d2
6
+ metadata.gz: 9286311e4de659c8820cdbdfb4ae48f1a3b0c519c66208a3c3f56a3a1079597b10306d6ab8aef05687df347262f26c75af63c4cbeac7570162829d926edf0317
7
+ data.tar.gz: 43954778b73cf95537a29a2317abe5b22eebfc3336e560657ec580542df9a7e9f42513968d27fc2b13621b0da0aa8fb8510ef59c9170bad611b0bd5b86f16888
data/CHANGELOG.md CHANGED
@@ -1,5 +1,122 @@
1
1
  # Release History
2
2
 
3
+ ### 1.15.0 (2025-08-25)
4
+
5
+ #### Features
6
+
7
+ * add typed errors to authentication library ([#533](https://github.com/googleapis/google-auth-library-ruby/issues/533))
8
+ * Support for JWT 3.x ([#542](https://github.com/googleapis/google-auth-library-ruby/issues/542))
9
+ #### Bug Fixes
10
+
11
+ * fix incorrect error and apply some code complexity refactoring ([#529](https://github.com/googleapis/google-auth-library-ruby/issues/529))
12
+ * support Pathname for cred loading ([#537](https://github.com/googleapis/google-auth-library-ruby/issues/537))
13
+ #### Documentation
14
+
15
+ * add summary documentation on credentials types and improve YARD comments
16
+ * add summary documentation on credentials types and improve YARD comments ([#530](https://github.com/googleapis/google-auth-library-ruby/issues/530))
17
+
18
+ ### 1.14.0 (2025-03-14)
19
+
20
+ #### Features
21
+
22
+ * add API key credentials ([#520](https://github.com/googleapis/google-auth-library-ruby/issues/520))
23
+ * Add Bearer token credentials
24
+ * add BearerToken credentials ([#522](https://github.com/googleapis/google-auth-library-ruby/issues/522))
25
+ * Update minimum Ruby version to 3.0 ([#527](https://github.com/googleapis/google-auth-library-ruby/issues/527))
26
+ #### Bug Fixes
27
+
28
+ * Eliminated the "attribute accessor as module_function" warning ([#519](https://github.com/googleapis/google-auth-library-ruby/issues/519))
29
+ * Get the project_id from gcloud ([#479](https://github.com/googleapis/google-auth-library-ruby/issues/479))
30
+ * logger configuration in service account JWT header ([#525](https://github.com/googleapis/google-auth-library-ruby/issues/525))
31
+
32
+ ### 1.13.1 (2025-01-24)
33
+
34
+ #### Bug Fixes
35
+
36
+ * Signet client subclasses no longer make the update! method private ([#516](https://github.com/googleapis/google-auth-library-ruby/issues/516))
37
+
38
+ ### 1.13.0 (2025-01-22)
39
+
40
+ #### Features
41
+
42
+ * create impersonated service credentials ([#499](https://github.com/googleapis/google-auth-library-ruby/issues/499))
43
+ #### Documentation
44
+
45
+ * Include note about validating externally-provided credentials ([#512](https://github.com/googleapis/google-auth-library-ruby/issues/512))
46
+
47
+ ### 1.12.2 (2024-12-19)
48
+
49
+ #### Bug Fixes
50
+
51
+ * GCECredentials lazily fetches from the metadata server to ensure a universe domain is known ([#509](https://github.com/googleapis/google-auth-library-ruby/issues/509))
52
+
53
+ ### 1.12.1 (2024-12-17)
54
+
55
+ #### Bug Fixes
56
+
57
+ * Restored previous behavior where the apply! method returns the auth header ([#506](https://github.com/googleapis/google-auth-library-ruby/issues/506))
58
+
59
+ ### 1.12.0 (2024-12-05)
60
+
61
+ #### Features
62
+
63
+ * provided opt-in debug logging ([#490](https://github.com/googleapis/google-auth-library-ruby/issues/490))
64
+
65
+ ### 1.11.2 (2024-10-23)
66
+
67
+ #### Bug Fixes
68
+
69
+ * Temporarily disable universe domain query from GCE metadata server ([#493](https://github.com/googleapis/google-auth-library-ruby/issues/493))
70
+ * Use updated metadata path for universe-domain ([#496](https://github.com/googleapis/google-auth-library-ruby/issues/496))
71
+
72
+ ### 1.11.1 (2024-10-04)
73
+
74
+ #### Bug Fixes
75
+
76
+ * Fixed parsing of expiration timestamp from ID tokens ([#492](https://github.com/googleapis/google-auth-library-ruby/issues/492))
77
+ * Use NoMethodError instead of NotImplementedError for unimplemented base class methods ([#487](https://github.com/googleapis/google-auth-library-ruby/issues/487))
78
+
79
+ ### 1.11.0 (2024-02-09)
80
+
81
+ #### Features
82
+
83
+ * Deprecate the positional argument for callback_uri, and introduce keyword argument instead ([#475](https://github.com/googleapis/google-auth-library-ruby/issues/475))
84
+
85
+ ### 1.10.0 (2024-02-08)
86
+
87
+ #### Features
88
+
89
+ * add PKCE to 3 Legged OAuth exchange ([#471](https://github.com/googleapis/google-auth-library-ruby/issues/471))
90
+ #### Bug Fixes
91
+
92
+ * Client library credentials provide correct self-signed JWT and external account behavior when loading from a file path or JSON data ([#474](https://github.com/googleapis/google-auth-library-ruby/issues/474))
93
+ * Prioritize universe domain specified in GCECredentials arguments over metadata-fetched value ([#472](https://github.com/googleapis/google-auth-library-ruby/issues/472))
94
+
95
+ ### 1.9.2 (2024-01-25)
96
+
97
+ #### Bug Fixes
98
+
99
+ * Prevent access tokens from being fetched at service account construction in the self-signed-jwt case ([#467](https://github.com/googleapis/google-auth-library-ruby/issues/467))
100
+
101
+ ### 1.9.1 (2023-12-12)
102
+
103
+ #### Bug Fixes
104
+
105
+ * update expires_in for cached metadata-retrieved tokens ([#464](https://github.com/googleapis/google-auth-library-ruby/issues/464))
106
+
107
+ ### 1.9.0 (2023-12-07)
108
+
109
+ #### Features
110
+
111
+ * Include universe_domain in credentials ([#460](https://github.com/googleapis/google-auth-library-ruby/issues/460))
112
+ * Use google-cloud-env for more robust Metadata Service access ([#459](https://github.com/googleapis/google-auth-library-ruby/issues/459))
113
+
114
+ ### 1.8.1 (2023-09-19)
115
+
116
+ #### Documentation
117
+
118
+ * improve ADC related error and warning messages ([#452](https://github.com/googleapis/google-auth-library-ruby/issues/452))
119
+
3
120
  ### 1.8.0 (2023-09-07)
4
121
 
5
122
  #### Features
data/Credentials.md ADDED
@@ -0,0 +1,106 @@
1
+ # Introduction
2
+
3
+ The closest thing to a base credentials class is the `BaseClient` module.
4
+ It includes functionality common to most credentials, such as applying authentication tokens to request headers, managing token expiration and refresh, handling logging, and providing updater procs for API clients.
5
+
6
+ Many credentials classes inherit from `Signet::OAuth2::Client` (`lib/googleauth/signet.rb`) class which provides OAuth-based authentication.
7
+ The `Signet::OAuth2::Client` includes the `BaseClient` functionality.
8
+
9
+ Most credential types either inherit from `Signet::OAuth2::Client` or include the `BaseClient` module directly.
10
+
11
+ Notably, `Google::Auth::Credentials` (`lib/googleauth/credentials.rb`) is not a base type or a credentials type per se. It is a wrapper for other credential classes
12
+ that exposes common initialization functionality, such as creating credentials from environment variables, default paths, or application defaults. It is used and subclassed by Google's API client libraries.
13
+
14
+ # List of credentials types
15
+
16
+ ## Simple Authentication (non-OAuth)
17
+
18
+ **Google::Auth::APIKeyCredentials** - `lib/googleauth/api_key.rb`
19
+ - Includes `Google::Auth::BaseClient` module
20
+ - Implements Google API Key authentication
21
+ - API Keys are text strings that don't have an associated JSON file
22
+ - API Keys provide project information but don't reference an IAM principal
23
+ - They do not expire and cannot be refreshed
24
+ - Can be loaded from the `GOOGLE_API_KEY` environment variable
25
+
26
+ 2. **Google::Auth::BearerTokenCredentials** - `lib/googleauth/bearer_token.rb`
27
+ - Includes `Google::Auth::BaseClient` module
28
+ - Implements Bearer Token authentication
29
+ - Bearer tokens are strings representing an authorization grant
30
+ - Can be OAuth2 tokens, JWTs, ID tokens, or any token sent as a `Bearer` in an `Authorization` header
31
+ - Used when the end-user is managing the token separately (e.g., with another service)
32
+ - Token lifetime tracking and refresh are outside this class's scope
33
+ - No JSON representation for this type of credentials
34
+
35
+ ## GCP-Specialized authentication
36
+
37
+ 3. **Google::Auth::GCECredentials < Signet::OAuth2::Client** - `lib/googleauth/compute_engine.rb`
38
+ - For obtaining authentication tokens from GCE metadata server
39
+ - Used automatically when code is running on Google Compute Engine
40
+ - Fetches tokens from the metadata server with no additional configuration needed
41
+
42
+ 4. **Google::Auth::IAMCredentials < Signet::OAuth2::Client** - `lib/googleauth/iam.rb`
43
+ - For IAM-based authentication (e.g. service-to-service)
44
+ - Implements authentication-as-a-service for systems already authenticated
45
+ - Exchanges existing credentials for a short-lived access token
46
+
47
+ ## Service Account Authentication
48
+
49
+ 5. **Google::Auth::ServiceAccountCredentials < Signet::OAuth2::Client** - `lib/googleauth/service_account.rb`
50
+ - Authenticates requests using Service Account credentials via an OAuth access token
51
+ - Created from JSON key file downloaded from Google Cloud Console
52
+ - Supports both OAuth access tokens and self-signed JWT authentication
53
+ - Can specify scopes for access token requests
54
+
55
+ 6. **Google::Auth::ServiceAccountJwtHeaderCredentials** - `lib/googleauth/service_account_jwt_header.rb`
56
+ - Authenticates using Service Account credentials with JWT headers
57
+ - Typically used via `ServiceAccountCredentials` and not by itself
58
+ - Creates JWT directly for making authenticated calls
59
+ - Does not require a round trip to the authorization server
60
+ - Doesn't support OAuth scopes - uses audience (target API) instead
61
+
62
+ 7. **Google::Auth::ImpersonatedServiceAccountCredentials < Signet::OAuth2::Client** - `lib/googleauth/impersonated_service_account.rb`
63
+ - For service account impersonation
64
+ - Allows a GCP principal identified by a set of source credentials to impersonate a service account
65
+ - Useful for delegation of authority and managing permissions across service accounts
66
+ - Source credentials must have the Service Account Token Creator role on the target
67
+
68
+ ## User Authentication
69
+
70
+ 8. **Google::Auth::UserRefreshCredentials < Signet::OAuth2::Client** - `lib/googleauth/user_refresh.rb`
71
+ - For user refresh token authentication (from 3-legged OAuth flow)
72
+ - Authenticates on behalf of a user who has authorized the application
73
+ - Handles token refresh when original access token expires
74
+ - Typically obtained through web or installed application flow
75
+
76
+ `Google::Auth::UserAuthorizer` (`lib/googleauth/user_authorizer.rb`) and `Google::Auth::WebUserAuthorizer` (`lib/googleauth/web_user_authorizer.rb`)
77
+ are used to facilitate user authentication. The `UserAuthorizer` handles interactive 3-Legged-OAuth2 (3LO) user consent authorization for command-line applications.
78
+ The `WebUserAuthorizer` is a variation of UserAuthorizer adapted for Rack-based web applications that manages OAuth state and provides callback handling.
79
+
80
+ ## External Account Authentication
81
+ `Google::Auth::ExternalAccount::Credentials` (`lib/googleauth/external_account.rb`) is not a credentials type, it is a module
82
+ that procides an entry point for External Account credentials. It also serves as a factory that creates appropriate credential
83
+ types based on credential source (similar to `Google::Auth::get_application_default`).
84
+ It is included in all External Account credentials types, and it itself includes `Google::Auth::BaseClient` module so all External
85
+ Account credentials types include `Google::Auth::BaseClient`.
86
+
87
+ 9. **Google::Auth::ExternalAccount::AwsCredentials** - `lib/googleauth/external_account/aws_credentials.rb`
88
+ - Includes `Google::Auth::BaseClient` module
89
+ - Includes `ExternalAccount::BaseCredentials` module
90
+ - Uses AWS credentials to authenticate to Google Cloud
91
+ - Exchanges temporary AWS credentials for Google access tokens
92
+ - Used for workloads running on AWS that need to access Google Cloud
93
+
94
+ 10. **Google::Auth::ExternalAccount::IdentityPoolCredentials** - `lib/googleauth/external_account/identity_pool_credentials.rb`
95
+ - Includes `Google::Auth::BaseClient` module
96
+ - Includes `ExternalAccount::BaseCredentials` module
97
+ - Authenticates using external identity pool
98
+ - Exchanges external identity tokens for Google access tokens
99
+ - Supports file-based and URL-based credential sources
100
+
101
+ 11. **Google::Auth::ExternalAccount::PluggableCredentials** - `lib/googleauth/external_account/pluggable_credentials.rb`
102
+ - Includes `Google::Auth::BaseClient` module
103
+ - Includes `ExternalAccount::BaseCredentials` module
104
+ - Supports executable-based credential sources
105
+ - Executes external programs to retrieve credentials
106
+ - Allows for custom authentication mechanisms via external executables
data/Errors.md ADDED
@@ -0,0 +1,152 @@
1
+ # Error Handling in Google Auth Library for Ruby
2
+
3
+ ## Overview
4
+
5
+ The Google Auth Library for Ruby provides a structured approach to error handling. This document explains the error hierarchy, how to access detailed error information, and provides examples of handling errors effectively.
6
+
7
+ ## Error Hierarchy
8
+
9
+ The Google Auth Library has two main error hierarchies: the core authentication errors and the specialized ID token flow errors.
10
+
11
+ ### Core Authentication Errors
12
+
13
+ These errors are used throughout the main library for general authentication and credential operations:
14
+
15
+ ```
16
+ Google::Auth::Error (module)
17
+ ├── Google::Auth::InitializationError (class)
18
+ └── Google::Auth::DetailedError (module)
19
+ ├── Google::Auth::CredentialsError (class)
20
+ ├── Google::Auth::AuthorizationError (class)
21
+ ├── Google::Auth::UnexpectedStatusError (class)
22
+ └── Google::Auth::ParseError (class)
23
+ ```
24
+
25
+ ### ID Token Errors
26
+
27
+ These specialized errors are used specifically for ID token flow. They also include the `Google::Auth::Error` module, allowing them to be caught with the same error handling as the core authentication errors:
28
+
29
+ ```
30
+ Google::Auth::Error (module)
31
+ ├── Google::Auth::IDTokens::KeySourceError (class)
32
+ └── Google::Auth::IDTokens::VerificationError (class)
33
+ ├── ExpiredTokenError (class)
34
+ ├── SignatureError (class)
35
+ ├── IssuerMismatchError (class)
36
+ ├── AudienceMismatchError (class)
37
+ └── AuthorizedPartyMismatchError (class)
38
+ ```
39
+
40
+ ### Error Module Types
41
+
42
+ - **`Google::Auth::Error`**: Base module that all Google Auth errors include. Use this to catch any error from the library.
43
+
44
+ - **`Google::Auth::DetailedError`**: Extends `Error` to include detailed information about the credential that caused the error, including the credential type and principal.
45
+
46
+ ## Core Authentication Error Classes
47
+
48
+ - **`InitializationError`**: Raised during credential initialization when required parameters are missing or invalid.
49
+
50
+ - **`CredentialsError`**: Generic error raised during authentication flows.
51
+
52
+ - **`AuthorizationError`**: Raised when a remote server refuses to authorize the client. Inherits from `Signet::AuthorizationError`. Is being raised where `Signet::AuthorizationError` was raised previously.
53
+
54
+ - **`UnexpectedStatusError`**: Raised when a server returns an unexpected HTTP status code. Inherits from `Signet::UnexpectedStatusError`. Is being raised where `Signet::UnexpectedStatusError` was raised previously.
55
+
56
+ - **`ParseError`**: Raised when the client fails to parse a value from a response. Inherits from `Signet::ParseError`. Is being raised where `Signet::ParseError` was raised previously.
57
+
58
+ ## Detailed Error Information
59
+
60
+ Errors that include the `DetailedError` module provide additional context about what went wrong:
61
+
62
+ - **`credential_type_name`**: The class name of the credential that raised the error (e.g., `"Google::Auth::ServiceAccountCredentials"`)
63
+
64
+ - **`principal`**: The identity associated with the credentials (e.g., an email address for service accounts, `:api_key` for API key credentials)
65
+
66
+ ### Example: Catching and Handling Core Errors
67
+
68
+ ```ruby
69
+ begin
70
+ credentials = Google::Auth::ServiceAccountCredentials.make_creds(
71
+ json_key_io: File.open("your-key.json")
72
+ )
73
+ # Use credentials...
74
+ rescue Google::Auth::InitializationError => e
75
+ puts "Failed to initialize credentials: #{e.message}"
76
+ # e.g., Missing required fields in the service account key file
77
+ rescue Google::Auth::DetailedError => e
78
+ puts "Authorization failed: #{e.message}"
79
+ puts "Credential type: #{e.credential_type_name}"
80
+ puts "Principal: #{e.principal}"
81
+ # e.g., Invalid or revoked service account
82
+ rescue Google::Auth::Error => e
83
+ puts "Unknown Google Auth error: #{e.message}"
84
+ end
85
+ ```
86
+
87
+ ## Backwards compatibility
88
+
89
+ Some classes in the Google Auth Library raise standard Ruby `ArgumentError` and `TypeError`. These errors are preserved for backward compatibility, however the new code will raise `Google::Auth::InitializationError` instead.
90
+
91
+ ## ID Token Verification
92
+
93
+ The Google Auth Library includes functionality for verifying ID tokens through the `Google::Auth::IDTokens` namespace. These operations have their own specialized error classes that also include the `Google::Auth::Error` module, allowing them to be caught with the same error handling as other errors in the library.
94
+
95
+ ### ID Token Error Classes
96
+
97
+ - **`KeySourceError`**: Raised when the library fails to obtain the keys needed to verify a token, typically from a JWKS (JSON Web Key Set) endpoint.
98
+
99
+ - **`VerificationError`**: Base class for all errors related to token verification failures.
100
+
101
+ - **`ExpiredTokenError`**: Raised when a token has expired according to its expiration time claim (`exp`).
102
+
103
+ - **`SignatureError`**: Raised when a token's signature cannot be verified, indicating it might be tampered with or corrupted.
104
+
105
+ - **`IssuerMismatchError`**: Raised when a token's issuer (`iss` claim) doesn't match the expected issuer.
106
+
107
+ - **`AudienceMismatchError`**: Raised when a token's audience (`aud` claim) doesn't match the expected audience.
108
+
109
+ - **`AuthorizedPartyMismatchError`**: Raised when a token's authorized party (`azp` claim) doesn't match the expected client ID.
110
+
111
+ ### Example: Handling ID Token Verification Errors
112
+
113
+ ```ruby
114
+ require "googleauth/id_tokens"
115
+
116
+ begin
117
+ # Verify the provided ID token
118
+ payload = Google::Auth::IDTokens.verify_oidc(
119
+ id_token,
120
+ audience: "expected-audience-12345.apps.googleusercontent.com"
121
+ )
122
+
123
+ # Use the verified token payload
124
+ user_email = payload["email"]
125
+
126
+ rescue Google::Auth::IDTokens::ExpiredTokenError => e
127
+ puts "The token has expired. Please obtain a new one."
128
+
129
+ rescue Google::Auth::IDTokens::SignatureError => e
130
+ puts "Invalid token signature."
131
+
132
+ rescue Google::Auth::IDTokens::IssuerMismatchError => e
133
+ puts "Invalid token issuer."
134
+
135
+ rescue Google::Auth::IDTokens::AudienceMismatchError => e
136
+ puts "This token is not intended for this application (invalid audience)."
137
+
138
+ rescue Google::Auth::IDTokens::AuthorizedPartyMismatchError => e
139
+ puts "Invalid token authorized party."
140
+
141
+ rescue Google::Auth::IDTokens::VerificationError => e
142
+ puts "Token verification failed: #{e.message}"
143
+ # Generic verification error handling
144
+
145
+ rescue Google::Auth::IDTokens::KeySourceError => e
146
+ puts "Unable to retrieve verification keys: #{e.message}"
147
+
148
+ rescue Google::Auth::Error => e
149
+ puts "Unknown Google Auth error: #{e.message}"
150
+ # This will catch any Google Auth error
151
+ end
152
+ ```
data/README.md CHANGED
@@ -64,6 +64,15 @@ well as a web variant tailored toward Rack-based applications.
64
64
  The authorizers are intended for authorization use cases. For sign-on,
65
65
  see [Google Identity Platform](https://developers.google.com/identity/)
66
66
 
67
+ ## Important notes
68
+
69
+ If you accept a credential configuration (credential JSON/File/Stream) from an
70
+ external source for authentication to Google Cloud, you must validate it before
71
+ providing it to any Google API or library. Providing an unvalidated credential
72
+ configuration to Google APIs can compromise the security of your systems and data.
73
+ For more information, refer to [Validate credential configurations from external
74
+ sources](https://cloud.google.com/docs/authentication/external/externally-sourced-credentials).
75
+
67
76
  ### Example (Web)
68
77
 
69
78
  ```ruby
@@ -97,6 +106,45 @@ get('/oauth2callback') do
97
106
  end
98
107
  ```
99
108
 
109
+ ### Example (Web with PKCE)
110
+
111
+ Proof Key for Code Exchange (PKCE) is an [RFC](https://www.rfc-editor.org/rfc/rfc7636) that aims to prevent malicious operating system processes from hijacking an OAUTH 2.0 exchange. PKCE mitigates the above vulnerability by including `code_challenge` and `code_challenge_method` parameters in the Authorization Request and a `code_verifier` parameter in the Access Token Request.
112
+
113
+ ```ruby
114
+ require 'googleauth'
115
+ require 'googleauth/web_user_authorizer'
116
+ require 'googleauth/stores/redis_token_store'
117
+ require 'redis'
118
+
119
+ client_id = Google::Auth::ClientId.from_file('/path/to/client_secrets.json')
120
+ scope = ['https://www.googleapis.com/auth/drive']
121
+ token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
122
+ authorizer = Google::Auth::WebUserAuthorizer.new(
123
+ client_id, scope, token_store, '/oauth2callback')
124
+
125
+
126
+ get('/authorize') do
127
+ # NOTE: Assumes the user is already authenticated to the app
128
+ user_id = request.session['user_id']
129
+ # User needs to take care of generating the code_verifier and storing it in
130
+ # the session.
131
+ request.session['code_verifier'] ||= Google::Auth::WebUserAuthorizer.generate_code_verifier
132
+ authorizer.code_verifier = request.session['code_verifier']
133
+ credentials = authorizer.get_credentials(user_id, request)
134
+ if credentials.nil?
135
+ redirect authorizer.get_authorization_url(login_hint: user_id, request: request)
136
+ end
137
+ # Credentials are valid, can call APIs
138
+ # ...
139
+ end
140
+
141
+ get('/oauth2callback') do
142
+ target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(
143
+ request)
144
+ redirect target_url
145
+ end
146
+ ```
147
+
100
148
  ### Example (Command Line) [Deprecated]
101
149
 
102
150
  The Google Auth OOB flow has been discontiued on January 31, 2023. The OOB flow is a legacy flow that is no longer considered secure. To continue using Google Auth, please migrate your applications to a more secure flow. For more information on how to do this, please refer to this [OOB Migration](https://developers.google.com/identity/protocols/oauth2/resources/oob-migration) guide.
@@ -217,7 +265,7 @@ Custom storage implementations can also be used. See
217
265
 
218
266
  ## Supported Ruby Versions
219
267
 
220
- This library is supported on Ruby 2.6+.
268
+ This library is supported on Ruby 3.0+.
221
269
 
222
270
  Google provides official support for Ruby versions that are actively supported
223
271
  by Ruby Core—that is, Ruby versions that are either in normal maintenance or
@@ -0,0 +1,164 @@
1
+ # Copyright 2025 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "googleauth/base_client"
16
+ require "googleauth/credentials_loader"
17
+
18
+ module Google
19
+ module Auth
20
+ ##
21
+ # Implementation of Google API Key authentication.
22
+ #
23
+ # API Keys are text strings. They don't have an associated JSON file.
24
+ #
25
+ # The end-user is managing their API Keys directly, not via
26
+ # an authentication library.
27
+ #
28
+ # API Keys provide project information for an API request.
29
+ # API Keys don't reference an IAM principal, they do not expire,
30
+ # and cannot be refreshed.
31
+ #
32
+ class APIKeyCredentials
33
+ include Google::Auth::BaseClient
34
+
35
+ # @private Authorization header key
36
+ API_KEY_HEADER = "x-goog-api-key".freeze
37
+
38
+ # @private Environment variable containing API key
39
+ API_KEY_VAR = "GOOGLE_API_KEY".freeze
40
+
41
+ # @return [String] The API key
42
+ attr_reader :api_key
43
+
44
+ # @return [String] The universe domain of the universe
45
+ # this API key is for
46
+ attr_accessor :universe_domain
47
+
48
+ class << self
49
+ # Creates an APIKeyCredentials from the environment.
50
+ # Checks the ENV['GOOGLE_API_KEY'] variable.
51
+ #
52
+ # @param [String] _scope
53
+ # The scope to use for OAuth. Not used by API key auth.
54
+ # @param [Hash] options
55
+ # The options to pass to the credentials instance
56
+ #
57
+ # @return [Google::Auth::APIKeyCredentials, nil]
58
+ # Credentials if the API key environment variable is present,
59
+ # nil otherwise
60
+ def from_env _scope = nil, options = {}
61
+ api_key = ENV[API_KEY_VAR]
62
+ return nil if api_key.nil? || api_key.empty?
63
+ new options.merge(api_key: api_key)
64
+ end
65
+
66
+ # Create the APIKeyCredentials.
67
+ #
68
+ # @param [Hash] options The credentials options
69
+ # @option options [String] :api_key
70
+ # The API key to use for authentication
71
+ # @option options [String] :universe_domain
72
+ # The universe domain of the universe this API key
73
+ # belongs to (defaults to googleapis.com)
74
+ # @return [Google::Auth::APIKeyCredentials]
75
+ def make_creds options = {}
76
+ new options
77
+ end
78
+ end
79
+
80
+ # Initialize the APIKeyCredentials.
81
+ #
82
+ # @param [Hash] options The credentials options
83
+ # @option options [String] :api_key
84
+ # The API key to use for authentication
85
+ # @option options [String] :universe_domain
86
+ # The universe domain of the universe this API key
87
+ # belongs to (defaults to googleapis.com)
88
+ # @raise [ArgumentError] If the API key is nil or empty
89
+ def initialize options = {}
90
+ raise ArgumentError, "API key must be provided" if options[:api_key].nil? || options[:api_key].empty?
91
+ @api_key = options[:api_key]
92
+ @universe_domain = options[:universe_domain] || "googleapis.com"
93
+ end
94
+
95
+ # Determines if the credentials object has expired.
96
+ # Since API keys don't expire, this always returns false.
97
+ #
98
+ # @param [Fixnum] _seconds
99
+ # The optional timeout in seconds since the last refresh
100
+ # @return [Boolean]
101
+ # True if the token has expired, false otherwise.
102
+ def expires_within? _seconds
103
+ false
104
+ end
105
+
106
+ # Creates a duplicate of these credentials.
107
+ #
108
+ # @param [Hash] options Additional options for configuring the credentials
109
+ # @return [Google::Auth::APIKeyCredentials]
110
+ def duplicate options = {}
111
+ self.class.new(
112
+ api_key: options[:api_key] || @api_key,
113
+ universe_domain: options[:universe_domain] || @universe_domain
114
+ )
115
+ end
116
+
117
+ # Updates the provided hash with the API Key header.
118
+ #
119
+ # The `apply!` method modifies the provided hash in place, adding the
120
+ # `x-goog-api-key` header with the API Key value.
121
+ #
122
+ # The API Key is hashed before being logged for security purposes.
123
+ #
124
+ # NB: this method typically would be called through `updater_proc`.
125
+ # Some older clients call it directly though, so it has to be public.
126
+ #
127
+ # @param [Hash] a_hash The hash to which the API Key header should be added.
128
+ # This is typically a hash representing the request headers. This hash
129
+ # will be modified in place.
130
+ # @param [Hash] _opts Additional options (currently not used). Included
131
+ # for consistency with the `BaseClient` interface.
132
+ # @return [Hash] The modified hash (the same hash passed as the `a_hash`
133
+ # argument).
134
+ def apply! a_hash, _opts = {}
135
+ a_hash[API_KEY_HEADER] = @api_key
136
+ logger&.debug do
137
+ hash = Digest::SHA256.hexdigest @api_key
138
+ Google::Logging::Message.from message: "Sending API key auth token. (sha256:#{hash})"
139
+ end
140
+ a_hash
141
+ end
142
+
143
+ # For credentials that are initialized with a token without a principal,
144
+ # the type of that token should be returned as a principal instead
145
+ # @private
146
+ # @return [Symbol] the token type in lieu of the principal
147
+ def principal
148
+ token_type
149
+ end
150
+
151
+ protected
152
+
153
+ # The token type should be :api_key
154
+ def token_type
155
+ :api_key
156
+ end
157
+
158
+ # We don't need to fetch access tokens for API key auth
159
+ def fetch_access_token! _options = {}
160
+ nil
161
+ end
162
+ end
163
+ end
164
+ end
@@ -14,15 +14,16 @@
14
14
 
15
15
  require "googleauth/compute_engine"
16
16
  require "googleauth/default_credentials"
17
+ require "googleauth/errors"
17
18
 
18
19
  module Google
19
20
  # Module Auth provides classes that provide Google-specific authorization
20
21
  # used to access Google APIs.
21
22
  module Auth
22
23
  NOT_FOUND_ERROR = <<~ERROR_MESSAGE.freeze
23
- Could not load the default credentials. Browse to
24
- https://cloud.google.com/docs/authentication/provide-credentials-adc
25
- for more information
24
+ Your credentials were not found. To set up Application Default
25
+ Credentials for your environment, see
26
+ https://cloud.google.com/docs/authentication/external/set-up-adc
26
27
  ERROR_MESSAGE
27
28
 
28
29
  module_function
@@ -50,16 +51,13 @@ module Google
50
51
  # connection to use for token refresh requests.
51
52
  # * `:connection` The connection to use to determine whether GCE
52
53
  # metadata credentials are available.
54
+ # @raise [Google::Auth::InitializationError] If the credentials cannot be found
53
55
  def get_application_default scope = nil, options = {}
54
56
  creds = DefaultCredentials.from_env(scope, options) ||
55
57
  DefaultCredentials.from_well_known_path(scope, options) ||
56
58
  DefaultCredentials.from_system_default_path(scope, options)
57
59
  return creds unless creds.nil?
58
- unless GCECredentials.on_gce? options
59
- # Clear cache of the result of GCECredentials.on_gce?
60
- GCECredentials.reset_cache
61
- raise NOT_FOUND_ERROR
62
- end
60
+ raise InitializationError, NOT_FOUND_ERROR unless GCECredentials.on_gce? options
63
61
  GCECredentials.new options.merge(scope: scope)
64
62
  end
65
63
  end