@@ -58,19 +58,57 @@ def load_centml_cred():
58
58
59
59
60
60
def get_centml_token ():
61
+ # Always use fresh client credentials if available
62
+ if settings .CENTML_SERVICE_ACCOUNT_ID and settings .CENTML_SERVICE_ACCOUNT_SECRET :
63
+ access_token = authenticate_with_client_credentials ()
64
+ if access_token is not None :
65
+ return access_token
66
+ else :
67
+ sys .exit (
68
+ "Could not authenticate with client credentials. Please check your service account configuration..."
69
+ )
70
+
71
+ # Fall back to stored credentials for interactive flows
61
72
cred = load_centml_cred ()
62
73
if not cred :
63
74
sys .exit ("CentML credentials not found. Please login..." )
64
75
exp_time = int (jwt .decode (cred ["access_token" ], options = {"verify_signature" : False })["exp" ])
65
76
66
77
if time .time () >= exp_time - 100 :
67
- cred = refresh_centml_token (cred ["refresh_token" ])
68
- if cred is None :
78
+ # Check if we have a refresh token (interactive flow)
79
+ refresh_token = cred .get ("refresh_token" )
80
+ if refresh_token is not None :
81
+ # Use refresh token for interactive authentication
82
+ cred = refresh_centml_token (cred ["refresh_token" ])
83
+ if cred is None :
84
+ sys .exit ("Could not refresh credentials. Please login and try again..." )
85
+ else :
69
86
sys .exit ("Could not refresh credentials. Please login and try again..." )
70
87
71
88
return cred ["access_token" ]
72
89
73
90
91
+ def authenticate_with_client_credentials ():
92
+ """
93
+ Authenticate using client credentials flow for service-to-service authentication.
94
+ Returns access token if successful, None otherwise.
95
+ """
96
+ if not settings .CENTML_SERVICE_ACCOUNT_ID or not settings .CENTML_SERVICE_ACCOUNT_SECRET :
97
+ return None
98
+
99
+ params = {
100
+ 'grant_type' : 'client_credentials' ,
101
+ 'client_id' : settings .CENTML_SERVICE_ACCOUNT_ID ,
102
+ 'client_secret' : settings .CENTML_SERVICE_ACCOUNT_SECRET ,
103
+ 'scope' : 'openid profile email' ,
104
+ }
105
+ response = requests .post (settings .CENTML_SERVICE_ACCOUNT_TOKEN_URL , data = params , timeout = 10 )
106
+ response .raise_for_status ()
107
+ response_data = response .json ()
108
+ access_token = response_data .get ('access_token' )
109
+ return access_token
110
+
111
+
74
112
def remove_centml_cred ():
75
113
if os .path .exists (settings .CENTML_CRED_FILE_PATH ):
76
114
os .remove (settings .CENTML_CRED_FILE_PATH )
0 commit comments