Skip to content

Commit 90abdd1

Browse files
[Feature] add token and expiration capabilities
1 parent d7410cf commit 90abdd1

File tree

10 files changed

+449
-51
lines changed

10 files changed

+449
-51
lines changed

README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## UseCase
2-
- Any idea or application a developer wants to develop. He has to put-in efforts to develop an authenticator using which a user signs up to the app.
2+
- Any idea or application a developer wants to develop. He has to put-in efforts to develop an authenticator using which a user signs up to the app.
33
- Authenticator is just that component which adds user to a db and validates if any request is coming from a person belonging to the application.
44

55
In signup you have multiple ways of doing it
@@ -15,20 +15,26 @@ Some other day we want to work on some idea we should be able to use this authen
1515
![image](https://user-images.githubusercontent.com/15846947/128825120-878b0e01-3bcf-4004-9add-4c4d50c60d0d.png)
1616

1717

18-
19-
2018
### Setup Requisites
2119
- Mongo
2220
- docker
2321
- python
2422
- Kubernetes (Soon once the working prototype is ready)
2523

26-
### ENV setup
24+
### ENV setup
2725
- docker-compose up
2826

2927
Post this start making changes to the code they should be reflected and you should be able to see them running.
3028

31-
### Current-state:
29+
### Local Setup
30+
31+
##### Run
32+
33+
- ```pip install poetry```
34+
- ```poetry install```
35+
- ```poetry run python authenticator/app.py``
36+
37+
### Current-state:
3238
In the repo you see signup with google until now. Moving forward we should add the ability to signup with facebook/twitter
3339

3440
## User Journey
@@ -45,6 +51,6 @@ In the repo you see signup with google until now. Moving forward we should add t
4551

4652
- Behaviour post logging out from google/gmail or from the session
4753
cannot show logging out from gmail for personal reasons obviously :D
48-
54+
4955
-![logout](https://user-images.githubusercontent.com/15846947/128707098-0c98a932-0bb9-4a51-ab6d-9d372677dc67.png)
5056
-![5](https://user-images.githubusercontent.com/15846947/127329414-3f56d681-28b2-47a4-9277-eba437d419d5.jpeg)

authenticator/adapters/db/api.py

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
from flask_pymongo import PyMongo
1+
from pymongo import MongoClient
22
from flask import jsonify
33

4+
from authenticator.utils import utils
5+
46

57
class MongoAdapters(object):
6-
def __init__(self, app):
7-
self.client = PyMongo(app)
8-
self.db = self.client.db["authenticator"]
8+
def __init__(self, host, port):
9+
self.client = MongoClient(host, int(port))
10+
self.db = self.client["authenticator"]
911

1012
def get_all_users(self):
1113
collection = self.client.db["users"]
@@ -14,6 +16,15 @@ def get_all_users(self):
1416
output.append({"name": user["name"], "email": user["email"]})
1517
return jsonify({"result": output})
1618

19+
def is_valid_user(self, token):
20+
if self.db["users"].count_documents({"auth_token": token}) == 1:
21+
data = self.db["users"].find_one({"auth_token": token})
22+
if utils.check_user_longevity(data["expiration_time"]):
23+
response = {"name": data["name"], "email": data["email"]}
24+
return response
25+
else:
26+
return False
27+
1728
def add_users(
1829
self,
1930
name,
@@ -23,21 +34,22 @@ def add_users(
2334
provider=None,
2435
provider_id=None,
2536
):
26-
try:
27-
collection = self.client.db["users"]
28-
count = collection.count_documents({"email": email})
29-
if count == 0:
30-
collection_id = collection.insert(
31-
{
32-
"name": name,
33-
"email": email,
34-
"provider": provider,
35-
"provider_id": provider_id,
36-
"creation_time": creation_time,
37-
"user_type": user_type,
38-
}
39-
)
40-
return jsonify({"result": str(collection_id)})
41-
return jsonify({"token": "User already signed up"})
42-
except Exception:
43-
print("ISSUE")
37+
collection = self.db["users"]
38+
auth_token = utils.generate_auth_token()
39+
count = collection.count_documents({"email": email})
40+
if count == 0:
41+
collection_id = collection.insert(
42+
{
43+
"name": name,
44+
"email": email,
45+
"provider": provider,
46+
"provider_id": provider_id,
47+
"creation_time": creation_time,
48+
"user_type": user_type,
49+
"expiration_time": utils.get_expiration_time(creation_time),
50+
"auth_token": auth_token,
51+
}
52+
)
53+
return jsonify({"result": str(auth_token)})
54+
else:
55+
return jsonify({"result": "User already signed up"})

authenticator/adapters/login/google_adapter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def __init__(self):
1414
self.flow = Flow.from_client_secrets_file(
1515
client_secrets_file=self.google_obj["secrets_file"],
1616
scopes=self.google_obj["scopes"],
17-
redirect_uri="http://127.0.0.1:5000/callback",
17+
redirect_uri=self.google_obj["redirect_uri"],
1818
)
1919

2020
def get_basic_info(self, request, session):

authenticator/app.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
import os
2-
import requests
2+
import oauthlib
33

44
from flask import Flask, session, url_for, abort, redirect, request
55

66
from authenticator.adapters.db import api as db_api
77
from authenticator.adapters.login import google_adapter
88
from authenticator.utils import utils
99

10-
database = os.environ.get("db", "authenticator")
10+
11+
app = Flask(__name__)
12+
1113
host = os.environ.get("db_host", "mongo")
1214
port = os.environ.get("db_port", "27017")
1315

14-
app = Flask(__name__)
15-
app.config["MONGO_URI"] = f"mongodb://{host}:{port}/{database}"
1616
app.config["SECRET_KEY"] = "b9dd1b2f"
1717
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
1818
app.config["GOOGLE_CLIENT_ID"] = os.environ.get("GOOGLE_CLIENT_ID", None)
1919
app.config["GOOGLE_CLIENT_SECRET"] = os.environ.get("GOOGLE_CLIENT_SECRET", None)
2020

2121

22-
db_obj = db_api.MongoAdapters(app)
22+
db_obj = db_api.MongoAdapters(host, port)
2323
google_adapter_obj = google_adapter.GoogleLoginAdapter()
2424

2525

@@ -33,11 +33,6 @@ def wrapper(*args, **kwargs):
3333
return wrapper
3434

3535

36-
@app.route("/users", methods=["GET"])
37-
def get_users():
38-
return db_obj.get_all_users()
39-
40-
4136
@app.route("/")
4237
def index():
4338
return "Hello World <a href='/googlelogin'><button>Sign Up with google</button></a>"
@@ -46,10 +41,20 @@ def index():
4641
def add_users(name, email, provider=None, provider_id=None):
4742
if email == "[email protected]":
4843
return db_obj.add_users(
49-
name, email, utils.get_current_time(), "admin", provider, provider_id
44+
name,
45+
email,
46+
utils.get_current_time(),
47+
"admin",
48+
provider,
49+
provider_id,
5050
)
5151
return db_obj.add_users(
52-
name, email, utils.get_current_time(), "user", provider=None, provider_id=None
52+
name,
53+
email,
54+
utils.get_current_time(),
55+
"user",
56+
provider,
57+
provider_id,
5358
)
5459

5560

@@ -60,20 +65,34 @@ def login():
6065
return redirect(authorization_url)
6166

6267

63-
@app.route("/callback")
64-
def callback():
65-
id_info = google_adapter_obj.get_basic_info(request, session)
68+
@app.route("/googlecallback")
69+
def googlecallback():
70+
try:
71+
id_info = google_adapter_obj.get_basic_info(request, session)
72+
except oauthlib.oauth2.rfc6749.errors.InvalidGrantError:
73+
return redirect("/")
74+
6675
if not session["state"] == request.args["state"]:
6776
abort(500) # State does not match!
6877

6978
name = id_info.get("name")
7079
email = id_info.get("email")
7180
google_id = id_info.get("sub")
81+
7282
session["google_id"] = google_id
7383
session["name"] = name
7484
session["email"] = email
75-
add_users(name, email, "google", google_id)
76-
return redirect("/protected_area")
85+
return add_users(name, email, "google", google_id)
86+
87+
88+
@app.route("/fetch", methods=["GET"])
89+
def validate_users():
90+
token = request.args.get("token")
91+
result = db_obj.is_valid_user(token)
92+
if isinstance(result, dict):
93+
return result
94+
else:
95+
abort(401, "unauthorized")
7796

7897

7998
@app.route("/logout")

authenticator/utils/utils.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
11
import json
22
import time
3+
import uuid
34

45

56
def get_current_time():
67
return int(time.time()) * 1000
78

89

10+
def generate_auth_token():
11+
return str(uuid.uuid4()).split("-")[0]
12+
13+
914
def read_config():
1015
with open("config.json") as fp:
1116
data = json.load(fp)
1217
return data
18+
19+
20+
def get_expiration_time(creation_time):
21+
with open("config.json") as fp:
22+
data = json.load(fp)
23+
expiration_time = int(data["default"]["expiration_time"])
24+
return creation_time + expiration_time
25+
26+
27+
def check_user_longevity(expiration_time):
28+
if expiration_time <= int(time.time()) * 1000:
29+
return False
30+
else:
31+
return True

client_secret.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"web":{"client_id":"1034883885605-gvj78f1cg3urngprb0jjfr3p0olqh8tr.apps.googleusercontent.com","project_id":"horizontal-cab-234208","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"jPbO8Hxm20DkefDqmD4EyhCs","redirect_uris":["http://127.0.0.1:5000/login/google/authorize","http://127.0.0.1:7000/token", "http://127.0.0.1:5000/callback"],"javascript_origins":["http://127.0.0.1:5000","http://127.0.0.1:7000"]}}
1+
{"web":{"client_id":"1034883885605-gvj78f1cg3urngprb0jjfr3p0olqh8tr.apps.googleusercontent.com","project_id":"horizontal-cab-234208","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"jPbO8Hxm20DkefDqmD4EyhCs","redirect_uris":["http://127.0.0.1:5000/login/google/authorize","http://127.0.0.1:7000/token","http://127.0.0.1:5000/googlecallback"],"javascript_origins":["http://127.0.0.1:5000","http://127.0.0.1:7000"]}}

config.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@
66
"api_base_url":"https://www.googleapis.com/oauth2/v1/",
77
"userinfo_endpoint":"https://openidconnect.googleapis.com/v1/userinfo",
88
"secrets_file": "client_secret.json",
9-
"redirect_uri": "http://127.0.0.1:5000/callback",
9+
"redirect_uri": "http://127.0.0.1:5000/googlecallback",
1010
"google_client_id": "1034883885605-gvj78f1cg3urngprb0jjfr3p0olqh8tr.apps.googleusercontent.com",
1111
"scopes": [
1212
"https://www.googleapis.com/auth/userinfo.profile",
1313
"https://www.googleapis.com/auth/userinfo.email",
1414
"openid"
1515
]
1616
}
17+
},
18+
"default":{
19+
"expiration_time":"15768000000"
1720
}
1821
}

docker-compose.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ version: "3.7"
33
services:
44
authenticator:
55
image: authenticator_service_dev
6+
restart: always
67
volumes:
78
- ./:/app
89
build: .

0 commit comments

Comments
 (0)