This repository was archived by the owner on Jul 14, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.py
More file actions
163 lines (142 loc) · 6.07 KB
/
auth.py
File metadata and controls
163 lines (142 loc) · 6.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import json
import requests
from credential_loader import Credentials
import re
class FirebaseAuthenticator(Credentials):
"""
Class to manage user authentication using Firebase.
Attributes:
firebase_config (str): Firebase configuration.
Methods:
sign_in_with_email_and_password: Signs in a user with the provided email and password.
get_account_info: Retrieves the account information associated with the given ID token.
raise_detailed_error: Raises a detailed error if the HTTP request returns an error status code.
sign_in: Signs in a user with the provided email and password.
"""
def __init__(self) -> None:
super().__init__()
self.firebase_config = self.get_firebase_config().get("apiKey")
self.current_user = (
None # Add this line to keep track of the currently signed-in user
)
def sign_in_with_email_and_password(self, email: str, password: str) -> dict:
"""
Signs in a user with the provided email and password.
Args:
email (str): The user's email address.
password (str): The user's password.
Returns:
dict: A dictionary containing the response data from the API.
Raises:
DetailedError: If there is an error during the API request.
"""
request_ref = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key={0}".format(
self.firebase_config
)
headers = {"content-type": "application/json; charset=UTF-8"}
data = json.dumps(
{"email": email, "password": password, "returnSecureToken": True}
)
request_object = requests.post(request_ref, headers=headers, data=data)
self.raise_detailed_error(request_object)
return request_object.json()
def get_account_info(self, id_token: str) -> dict:
"""
Retrieves the account information associated with the given ID token.
Args:
id_token (str): The ID token to authenticate the request.
Returns:
dict: The account information as a dictionary.
Raises:
DetailedError: If there is an error in the request.
"""
request_ref = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key={0}".format(
self.firebase_config
)
headers = {"content-type": "application/json; charset=UTF-8"}
data = json.dumps({"idToken": id_token})
request_object = requests.post(request_ref, headers=headers, data=data)
self.raise_detailed_error(request_object)
return request_object.json()
def raise_detailed_error(self, request_object: requests.models.Response) -> None:
"""
Raises a detailed error if the HTTP request returns an error status code.
Args:
request_object (requests.models.Response): The response object from the HTTP request.
Raises:
requests.exceptions.HTTPError: If the HTTP request returns an error status code.
"""
try:
request_object.raise_for_status()
except requests.exceptions.HTTPError as error:
raise requests.exceptions.HTTPError(error, request_object.text)
def sign_in(self, email: str, password: str) -> None:
"""
Signs in a user with the provided email and password.
Args:
email (str): The user's email address.
password (str): The user's password.
Raises:
requests.exceptions.HTTPError: If there is an HTTP error during the sign-in process.
Exception: If there is an error during the sign-in process.
Returns:
None
"""
try:
id_token = self.sign_in_with_email_and_password(email, password)["idToken"]
account_info = self.get_account_info(id_token)
user_info = account_info["users"][0]
if not user_info["emailVerified"]:
self.send_email_verification(id_token)
print(
"""
##### Email not verified.
- Check your inbox to verify your email.
- Please check your spam folder if you don't see it in your inbox.
"""
)
else:
user_info["idToken"] = id_token
user_info["fullUserInfo"] = account_info
print("User signed in successfully.")
except requests.exceptions.HTTPError as error:
error_message = json.loads(error.args[1])["error"]["message"]
if error_message in {
"INVALID_EMAIL",
"EMAIL_NOT_FOUND",
"INVALID_PASSWORD",
"MISSING_PASSWORD",
"INVALID_LOGIN_CREDENTIALS",
}:
print(
"""
##### Error: Invalid login credentials.
- Please check your email and password.
- Forgot your password?
- Click the 'Forgot Password' button to reset it.
"""
)
elif any(
re.search(pattern, error_message, re.IGNORECASE)
for pattern in {
"TOO_MANY_ATTEMPTS_TRY_LATER",
"USER_DISABLED",
"OPERATION_NOT_ALLOWED",
"USER_NOT_FOUND",
"TOO_MANY_ATTEMPTS_TRY_LATER : Too many unsuccessful login attempts. Please try again later.",
}
):
print(
"""
##### Error: Too many attempts.
- Please try again later.
- You are temporarily blocked from signing in.
- Be sure to verify your email.
- Get access instantly by resetting your password.
- Or, wait for a while and try again.
"""
)
else:
print(f"Error: {error_message}")
except Exception as error:
print(f"Error: {error}")