16
16
17
17
from __future__ import annotations
18
18
19
+ from typing import Optional
20
+
19
21
import google .auth
20
22
from google .auth .transport .requests import Request
21
23
from google .oauth2 import service_account
24
+ from typing_extensions import override
22
25
23
- from ..utils .feature_decorator import experimental
24
- from .auth_credential import AuthCredential
25
- from .auth_credential import AuthCredentialTypes
26
- from .auth_credential import HttpAuth
27
- from .auth_credential import HttpCredentials
26
+ from ... utils .feature_decorator import experimental
27
+ from .. auth_credential import AuthCredential
28
+ from .. auth_credential import AuthCredentialTypes
29
+ from .. auth_schemes import AuthScheme
30
+ from .base_credential_exchanger import BaseCredentialExchanger
28
31
29
32
30
33
@experimental
31
- class ServiceAccountCredentialExchanger :
34
+ class ServiceAccountCredentialExchanger ( BaseCredentialExchanger ) :
32
35
"""Exchanges Google Service Account credentials for an access token.
33
36
34
37
Uses the default service credential if `use_default_credential = True`.
35
38
Otherwise, uses the service account credential provided in the auth
36
39
credential.
37
40
"""
38
41
39
- def __init__ ( self , credential : AuthCredential ):
40
- if credential . auth_type != AuthCredentialTypes . SERVICE_ACCOUNT :
41
- raise ValueError ( "Credential is not a service account credential." )
42
- self . _credential = credential
43
-
44
- def exchange ( self ) -> AuthCredential :
42
+ @ override
43
+ async def exchange (
44
+ self ,
45
+ auth_credential : AuthCredential ,
46
+ auth_scheme : Optional [ AuthScheme ] = None ,
47
+ ) -> AuthCredential :
45
48
"""Exchanges the service account auth credential for an access token.
46
49
47
50
If the AuthCredential contains a service account credential, it will be used
48
51
to exchange for an access token. Otherwise, if use_default_credential is True,
49
52
the default application credential will be used for exchanging an access token.
50
53
54
+ Args:
55
+ auth_scheme: The authentication scheme.
56
+ auth_credential: The credential to exchange.
57
+
51
58
Returns:
52
- An AuthCredential in HTTP Bearer format, containing the access token .
59
+ An AuthCredential in OAUTH2 format, containing the exchanged credential JSON .
53
60
54
61
Raises:
55
62
ValueError: If service account credentials are missing or invalid.
56
63
Exception: If credential exchange or refresh fails.
57
64
"""
65
+ if auth_credential is None :
66
+ raise ValueError ("Credential cannot be None." )
67
+
EDBE
div>
68
+ if auth_credential .auth_type != AuthCredentialTypes .SERVICE_ACCOUNT :
69
+ raise ValueError ("Credential is not a service account credential." )
70
+
71
+ if auth_credential .service_account is None :
72
+ raise ValueError (
73
+ "Service account credentials are missing. Please provide them."
74
+ )
75
+
58
76
if (
59
- self ._credential is None
60
- or self ._credential .service_account is None
61
- or (
62
- self ._credential .service_account .service_account_credential is None
63
- and not self ._credential .service_account .use_default_credential
64
- )
77
+ auth_credential .service_account .service_account_credential is None
78
+ and not auth_credential .service_account .use_default_credential
65
79
):
66
80
raise ValueError (
67
- "Service account credentials are missing. Please provide them, or set"
68
- " `use_default_credential = True` to use application default"
69
- " credential in a hosted service like Google Cloud Run."
81
+ "Service account credentials are invalid. Please set the"
82
+ " service_account_credential field or set `use_default_credential ="
83
+ " True` to use application default credential in a hosted service"
84
+ " like Google Cloud Run."
70
85
)
71
86
72
87
try :
73
- if self . _credential .service_account .use_default_credential :
88
+ if auth_credential .service_account .use_default_credential :
74
89
credentials , _ = google .auth .default ()
75
90
else :
76
- config = self . _credential .service_account
91
+ config = auth_credential .service_account
77
92
credentials = service_account .Credentials .from_service_account_info (
78
93
config .service_account_credential .model_dump (), scopes = config .scopes
79
94
)
@@ -82,11 +97,8 @@ def exchange(self) -> AuthCredential:
82
97
credentials .refresh (Request ())
83
98
84
99
return AuthCredential (
85
- auth_type = AuthCredentialTypes .HTTP ,
86
- http = HttpAuth (
87
- scheme = "bearer" ,
88
- credentials = HttpCredentials (token = credentials .token ),
89
- ),
100
+ auth_type = AuthCredentialTypes .OAUTH2 ,
101
+ google_oauth2_json = credentials .to_json (),
90
102
)
91
103
except Exception as e :
92
104
raise ValueError (f"Failed to exchange service account token: { e } " ) from e
0 commit comments