Skip to content

Commit 714dc2a

Browse files
authored
Merge pull request #41 from dmtzs/development
Development to master
2 parents 04c4c85 + 3c78fc1 commit 714dc2a

File tree

5 files changed

+154
-6
lines changed

5 files changed

+154
-6
lines changed

api_example/app/__init__.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
try:
2+
from flask import Flask
3+
import flask_authgen_jwt
4+
except ImportError as eImp:
5+
print(f"The following import ERROR occurred in {__file__}: {eImp}")
6+
7+
app = Flask(__name__)
8+
gen_auth = flask_authgen_jwt.GenJwt()
9+
auth = flask_authgen_jwt.DecJwt()
10+
11+
from app import routes

api_example/app/routes.py

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
try:
2+
import datetime as dt
3+
from app import app, auth, gen_auth
4+
from flask import Response, make_response, jsonify
5+
except ImportError as eImp:
6+
print(f"The following import ERROR occurred in {__file__}: {eImp}")
7+
8+
@gen_auth.enc_dec_jwt_config
9+
@auth.enc_dec_jwt_config
10+
def test_creds() -> dict:
11+
decode_attributes = {
12+
"key": "secret",
13+
"algorithm": "HS256",
14+
}
15+
return decode_attributes
16+
17+
@gen_auth.personal_credentials_field
18+
@auth.personal_credentials_field
19+
def personal_credentials_field() -> tuple[str, str]:
20+
return "per_username", "per_password"
21+
22+
@gen_auth.verify_bauth_credentials
23+
def get_basic_auth_credentials2(username: str, password: str) -> dict:
24+
# Use the username and password to authenticate the user in the way you want-
25+
# and return true if the user is authenticated
26+
if username == "admin2" and password == "passwd2":
27+
return True
28+
else:
29+
return False
30+
31+
@auth.get_user_roles
32+
@gen_auth.get_user_roles
33+
def my_roles(username: str) -> list[str]:
34+
# Use username to get roles from database
35+
print(f"username in roles: {username}")
36+
return ["admin", "user"]
37+
38+
@auth.get_jwt_claims_to_verify
39+
def get_jwt_claims_to_verify() -> list[str]:
40+
# return ["exp", "iat", "nbf"]
41+
return ["exp", "iat"]
42+
43+
@gen_auth.jwt_claims
44+
def jwt_claims() -> dict:
45+
claims = {
46+
"exp": dt.datetime.now(tz=dt.timezone.utc) + dt.timedelta(seconds=30),
47+
"iat": dt.datetime.now(tz=dt.timezone.utc)
48+
}
49+
return claims
50+
51+
@auth.verify_jwt_credentials#TODO: Checar si debe cambiar o no
52+
def creds(username_jwt: str, password_jwt: str) -> bool:
53+
my_dict = {
54+
"username_jwt": username_jwt,
55+
"password_jwt": password_jwt
56+
}
57+
return True
58+
# return False
59+
60+
# -------------Endpoints-------------
61+
@app.route("/")
62+
@auth.login_required(roles=["admin", "eder"])
63+
def index():
64+
return Response("Todo bien"), 200
65+
66+
@app.route("/generate_token", methods=["POST"])
67+
@gen_auth.generate_jwt(roles=["eder", "user"])
68+
def gen_token(token):
69+
response = {
70+
"status": "success",
71+
"token": token
72+
}
73+
return make_response(jsonify(response)), 200
74+
75+
@app.route("/temp")
76+
def temp():
77+
test = (("val1", "hola"), ("val2", "prueba2"))
78+
response = {
79+
"message": "solo prueba",
80+
"test_data": test
81+
}
82+
return make_response(jsonify(response))

api_example/run_app.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
try:
2+
from app import app
3+
from gevent.pywsgi import WSGIServer
4+
except ImportError as eImp:
5+
print(f"The following import ERROR occurred in {__file__}: {eImp}")
6+
7+
if __name__== "__main__":
8+
try:
9+
# -----------------Dev mode-----------------
10+
app.run(host= "127.0.0.1", port= 5000, debug= True)
11+
# debug= True for apply changes made into the files without restarting the flask server
12+
13+
# -----------------Prod mode----------------
14+
#appServer= WSGIServer(("127.0.0.1", 5000), app)
15+
#appServer.serve_forever()
16+
except Exception as eImp:
17+
print(f"The following import ERROR occurred in {__file__}: {eImp}")
18+
finally:
19+
print("Finishing program")

setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = Flask-authgen-jwt
3-
version = 1.2.4
3+
version = 2.0.0
44
author = Diego Martinez and Guillermo Ortega
55
author_email = [email protected]
66
description = JWT authentication and generator for Flask routes

src/flask_authgen_jwt.py

+41-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class Core():
1919
basic_auth_callback: Callable[[str, str], bool] = None
2020
enc_dec_jwt_callback: dict = None
2121
get_user_roles_callback: list = None
22+
personal_credentials: tuple[str, str] = None
2223

2324
def enc_dec_jwt_config(self, func: Callable[[None], dict]) -> Callable[[None], dict]:
2425
"""Decorator to verify the JWT token
@@ -29,6 +30,23 @@ def enc_dec_jwt_config(self, func: Callable[[None], dict]) -> Callable[[None], d
2930
self.enc_dec_jwt_callback = func()
3031
return func
3132

33+
def personal_credentials_field(self, func: Callable[[None], tuple[str, str]]) -> Callable[[None], tuple[str, str]]:
34+
"""
35+
Decorator to set the personal credentials, if youu dont want to use username and password inside the token
36+
then with this you can return a tuple in which the first element is the username and the second is the password
37+
but as you want to name that respective fields so the library will validate using the fields you set
38+
:param func: function to be decorated
39+
:return: the tuple with the username and password with personal names
40+
41+
:Example:
42+
@dec_jwt.personal_credentials_field
43+
44+
def get_personal_credentials():
45+
return "my_username_personal_name_field", "my_password_personal_name_field"
46+
"""
47+
self.personal_credentials = func()
48+
return func
49+
3250
def verify_dict_config(self, config: str) -> None:
3351
"""Method that veryfies the JWT configuration generator and for basic auth
3452
:param config: str to identify which configuration to verify"""
@@ -89,6 +107,11 @@ def __create_jwt_payload(self, bauth_credentials: dict) -> dict:
89107
"""
90108
if not self.jwt_fields_attr:
91109
self.gen_abort_error("jwt_claims decorator and function is not defined", 500)
110+
if self.personal_credentials is not None:
111+
bauth_credentials[self.personal_credentials[0]] = bauth_credentials["username"]
112+
bauth_credentials[self.personal_credentials[1]] = bauth_credentials["password"]
113+
del bauth_credentials["username"]
114+
del bauth_credentials["password"]
92115
payload = bauth_credentials
93116
payload.update(self.jwt_fields_attr)
94117

@@ -226,8 +249,14 @@ def __verify_token(self, token: dict) -> None:
226249
self.gen_abort_error(f"The claim {claim} is not in the token", 400)
227250
if len(token) < 1:
228251
self.gen_abort_error("Invalid token", 401)
229-
if ("username" not in token) or ("password" not in token):
230-
self.gen_abort_error("Invalid token", 401)
252+
if self.personal_credentials is not None:
253+
per_username = self.personal_credentials[0]
254+
per_password = self.personal_credentials[1]
255+
if (per_username not in token) or (per_password not in token):
256+
self.gen_abort_error("Invalid token", 401)
257+
else:
258+
if ("username" not in token) or ("password" not in token):
259+
self.gen_abort_error("Invalid token", 401)
231260
keys_to_validate = self.get_jwt_claims_to_verify_callback
232261
for key in keys_to_validate:
233262
if key not in token:
@@ -240,8 +269,12 @@ def __authenticate_credentials(self, token: dict) -> bool:
240269
"""
241270
if self.credentials_success_callback is None:
242271
self.gen_abort_error("get_credentials_success decorator is not set", 500)
243-
username_jwt = token["username"]
244-
password_jwt = token["password"]
272+
if self.personal_credentials is None:
273+
username_jwt = token["username"]
274+
password_jwt = token["password"]
275+
else:
276+
username_jwt = token[self.personal_credentials[0]]
277+
password_jwt = token[self.personal_credentials[1]]
245278
return self.ensure_sync(self.credentials_success_callback)(username_jwt, password_jwt)
246279

247280
def __set_token_as_attr(self, token: dict) -> None:
@@ -282,11 +315,14 @@ def wrapper(*args, **kwargs):
282315
else:
283316
token = self.__decode_jwt()
284317
self.__verify_token(token)
285-
self.verify_user_roles(roles, token["username"])
286318

287319
grant_access = self.__authenticate_credentials(token)
288320
if not grant_access:
289321
self.gen_abort_error("The credentials are not correct", 401)
322+
if self.personal_credentials is not None:
323+
self.verify_user_roles(roles, token[self.personal_credentials[0]])
324+
else:
325+
self.verify_user_roles(roles, token["username"])
290326
self.__set_token_as_attr(token)
291327

292328
return self.ensure_sync(func)(*args, **kwargs)

0 commit comments

Comments
 (0)