@@ -766,8 +766,8 @@ def get_oauth2_credentials(username, password, reload_remote_accounts=True):
766
766
try :
767
767
client_secret = cryptographer .decrypt (client_secret_encrypted )
768
768
except InvalidToken as e : # needed to avoid looping (we don't remove secrets on decryption failure)
769
- Log .error ('Invalid password to decrypt' , username , 'secret - aborting login:' ,
770
- Log .error_string (e ))
769
+ Log .error ('Invalid password to decrypt `client_secret_encrypted` for account' , username ,
770
+ '- aborting login:' , Log .error_string (e ))
771
771
return False , '%s: Login failed - the password for account %s is incorrect' % (
772
772
APP_NAME , username )
773
773
else :
@@ -778,6 +778,7 @@ def get_oauth2_credentials(username, password, reload_remote_accounts=True):
778
778
if not access_token or access_token_expiry - current_time < TOKEN_EXPIRY_MARGIN :
779
779
if refresh_token :
780
780
response = OAuth2Helper .refresh_oauth2_access_token (token_url , client_id , client_secret ,
781
+ username ,
781
782
cryptographer .decrypt (refresh_token ))
782
783
783
784
access_token = response ['access_token' ]
@@ -811,11 +812,11 @@ def get_oauth2_credentials(username, password, reload_remote_accounts=True):
811
812
redirect_listen_address , username )
812
813
813
814
if not success :
814
- Log .info ('Authorisation result error for' , username , '- aborting login.' , auth_result )
815
+ Log .info ('Authorisation result error for account ' , username , '- aborting login.' , auth_result )
815
816
return False , '%s: Login failed for account %s: %s' % (APP_NAME , username , auth_result )
816
817
817
818
if not oauth2_flow :
818
- Log .error ('No `oauth2_flow` value specified for' , username , '- aborting login' )
819
+ Log .error ('No `oauth2_flow` value specified for account ' , username , '- aborting login' )
819
820
return (False , '%s: Incomplete config file entry found for account %s - please make sure an '
820
821
'`oauth2_flow` value is specified when using a method that does not require a '
821
822
'`permission_url`' % (APP_NAME , username ))
@@ -843,8 +844,9 @@ def get_oauth2_credentials(username, password, reload_remote_accounts=True):
843
844
if 'refresh_token' in response :
844
845
config .set (username , 'refresh_token' , cryptographer .encrypt (response ['refresh_token' ]))
845
846
elif permission_url : # ignore this situation with CCG/ROPCG/service account flows - it is expected
846
- Log .info ('Warning: no refresh token returned for' , username , '- you will need to re-authenticate' ,
847
- 'each time the access token expires (does your `oauth2_scope` value allow `offline` use?)' )
847
+ Log .info ('Warning: no refresh token returned for account' , username , '- you will need to' ,
848
+ 're-authenticate each time the access token expires (does your `oauth2_scope` value allow' ,
849
+ '`offline` use?)' )
848
850
849
851
AppConfig .save ()
850
852
@@ -867,7 +869,7 @@ def get_oauth2_credentials(username, password, reload_remote_accounts=True):
867
869
868
870
AppConfig .save ()
869
871
870
- Log .info ('Retrying login due to exception while refreshing OAuth 2.0 tokens for' , username ,
872
+ Log .info ('Retrying login due to exception while refreshing access token for account ' , username ,
871
873
'(attempt %d):' % (1 if has_access_token else 2 ), Log .error_string (e ))
872
874
return OAuth2Helper .get_oauth2_credentials (username , password , reload_remote_accounts = False )
873
875
@@ -884,11 +886,12 @@ def get_oauth2_credentials(username, password, reload_remote_accounts=True):
884
886
config .remove_option (username , 'refresh_token' )
885
887
AppConfig .save ()
886
888
887
- Log .info ('Retrying login due to exception while decrypting OAuth 2.0 credentials for' , username ,
889
+ Log .info ('Retrying login due to exception while decrypting OAuth 2.0 credentials for account ' , username ,
888
890
'(invalid password):' , Log .error_string (e ))
889
891
return OAuth2Helper .get_oauth2_credentials (username , password , reload_remote_accounts = False )
890
892
891
- Log .error ('Invalid password to decrypt' , username , 'credentials - aborting login:' , Log .error_string (e ))
893
+ Log .error ('Invalid password to decrypt credentials for account' , username , '- aborting login:' ,
894
+ Log .error_string (e ))
892
895
return False , '%s: Login failed - the password for account %s is incorrect' % (APP_NAME , username )
893
896
894
897
except Exception as e :
@@ -897,7 +900,8 @@ def get_oauth2_credentials(username, password, reload_remote_accounts=True):
897
900
# errors: URLError(OSError(50, 'Network is down'))) - access token 400 Bad Request HTTPErrors with messages
898
901
# such as 'authorisation code was already redeemed' are caused by our support for simultaneous requests,
899
902
# and will work from the next request; however, please report an issue if you encounter problems here
900
- Log .info ('Caught exception while requesting OAuth 2.0 credentials for %s:' % username , Log .error_string (e ))
903
+ Log .info ('Caught exception while requesting OAuth 2.0 credentials for account %s:' % username ,
904
+ Log .error_string (e ))
901
905
return False , '%s: Login failed for account %s - please check your internet connection and retry' % (
902
906
APP_NAME , username )
903
907
@@ -1014,7 +1018,7 @@ def get_oauth2_authorisation_code(permission_url, redirect_uri, redirect_listen_
1014
1018
# to improve no-GUI mode we also support the use of a local redirection receiver server or terminal
1015
1019
# entry to authenticate; this result is a timeout, wsgi request error/failure, or terminal auth ctrl+c
1016
1020
if 'expired' in data and data ['expired' ]:
1017
- return False , 'No-GUI authorisation request failed or timed out'
1021
+ return False , 'No-GUI authorisation request failed or timed out for account %s' % data [ 'username' ]
1018
1022
1019
1023
if 'local_server_auth' in data :
1020
1024
threading .Thread (target = OAuth2Helper .start_redirection_receiver_server , args = (data ,),
@@ -1031,13 +1035,16 @@ def get_oauth2_authorisation_code(permission_url, redirect_uri, redirect_listen_
1031
1035
authorisation_code = OAuth2Helper .oauth2_url_unescape (response ['code' ])
1032
1036
if authorisation_code :
1033
1037
return True , authorisation_code
1034
- return False , 'No OAuth 2.0 authorisation code returned'
1038
+ return False , 'No OAuth 2.0 authorisation code returned for account %s' % data [ 'username' ]
1035
1039
if 'error' in response :
1036
- message = 'OAuth 2.0 authorisation error: %s' % response ['error' ]
1040
+ message = 'OAuth 2.0 authorisation error for account %s: ' % data ['username' ]
1041
+ message += response ['error' ]
1037
1042
message += '; %s' % response ['error_description' ] if 'error_description' in response else ''
1038
1043
return False , message
1039
- return False , 'OAuth 2.0 authorisation response has no code or error message'
1040
- return False , 'OAuth 2.0 authorisation response is missing or does not match `redirect_uri`'
1044
+ return (False , 'OAuth 2.0 authorisation response for account %s has neither code nor error '
1045
+ 'message' % data ['username' ])
1046
+ return (False , 'OAuth 2.0 authorisation response for account %s is missing or does not match'
1047
+ '`redirect_uri`' % data ['username' ])
1041
1048
1042
1049
else : # not for this thread - put back into queue
1043
1050
response_queue_reference .put (data )
@@ -1070,7 +1077,7 @@ def get_oauth2_authorisation_tokens(token_url, redirect_uri, client_id, client_s
1070
1077
return json .loads (response )
1071
1078
except urllib .error .HTTPError as e :
1072
1079
e .message = json .loads (e .read ())
1073
- Log .debug ('Error requesting access token - received invalid response:' , e .message )
1080
+ Log .debug ('Error requesting access token for account' , username , ' - received invalid response:' , e .message )
1074
1081
raise e
1075
1082
1076
1083
# noinspection PyUnresolvedReferences
@@ -1087,12 +1094,17 @@ def get_service_account_authorisation_token(key_type, key_path_or_contents, oaut
1087
1094
'`python -m pip install requests google-auth`' )
1088
1095
1089
1096
if key_type == 'file' :
1090
- with open (key_path_or_contents ) as key_file :
1091
- service_account = json .load (key_file )
1097
+ try :
1098
+ with open (key_path_or_contents ) as key_file :
1099
+ service_account = json .load (key_file )
1100
+ except IOError as e :
1101
+ raise FileNotFoundError ('Unable to open service account key file %s for account %s' ,
1102
+ (key_path_or_contents , username )) from e
1092
1103
elif key_type == 'key' :
1093
1104
service_account = json .loads (key_path_or_contents )
1094
1105
else :
1095
- raise Exception ('Service account key type not specified - `client_id` must be set to `file` or `key`' )
1106
+ raise Exception ('Service account key type not specified for account %s - `client_id` must be set to '
1107
+ '`file` or `key`' % username )
1096
1108
1097
1109
credentials = google .oauth2 .service_account .Credentials .from_service_account_info (service_account )
1098
1110
credentials = credentials .with_scopes (oauth2_scope .split (' ' ))
@@ -1103,7 +1115,7 @@ def get_service_account_authorisation_token(key_type, key_path_or_contents, oaut
1103
1115
return {'access_token' : credentials .token , 'expires_in' : int (credentials .expiry .timestamp () - time .time ())}
1104
1116
1105
1117
@staticmethod
1106
- def refresh_oauth2_access_token (token_url , client_id , client_secret , refresh_token ):
1118
+ def refresh_oauth2_access_token (token_url , client_id , client_secret , username , refresh_token ):
1107
1119
"""Obtains a new access token from token_url using the given client_id, client_secret and refresh token,
1108
1120
returning a dict with 'access_token', 'expires_in', and 'refresh_token' on success; exception on failure"""
1109
1121
params = {'client_id' : client_id , 'client_secret' : client_secret , 'refresh_token' : refresh_token ,
@@ -1121,7 +1133,7 @@ def refresh_oauth2_access_token(token_url, client_id, client_secret, refresh_tok
1121
1133
1122
1134
except urllib .error .HTTPError as e :
1123
1135
e .message = json .loads (e .read ())
1124
- Log .debug ('Error refreshing access token - received invalid response:' , e .message )
1136
+ Log .debug ('Error refreshing access token for account' , username , ' - received invalid response:' , e .message )
1125
1137
if e .code == 400 : # 400 Bad Request typically means re-authentication is required (token expired)
1126
1138
raise OAuth2Helper .TokenRefreshError from e
1127
1139
raise e
0 commit comments