Skip to content

Commit 56947ac

Browse files
Merge pull request #6 from pratapaprasanna/feature/logoutsession
[Feature] add logout and session abilities
2 parents 0e9e202 + c12a790 commit 56947ac

File tree

9 files changed

+383
-50
lines changed

9 files changed

+383
-50
lines changed

authenticator/adapters/db/api.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ def get_all_users(self):
1414
output.append({"name": user["name"], "email": user["email"]})
1515
return jsonify({"result": output})
1616

17-
def add_users(self, name, email, creation_time, provider=None, user_type="user"):
17+
def add_users(
18+
self,
19+
name,
20+
email,
21+
creation_time,
22+
user_type="user",
23+
provider=None,
24+
provider_id=None,
25+
):
1826
try:
1927
collection = self.client.db["users"]
2028
count = collection.count_documents({"email": email})
@@ -24,6 +32,7 @@ def add_users(self, name, email, creation_time, provider=None, user_type="user")
2432
"name": name,
2533
"email": email,
2634
"provider": provider,
35+
"provider_id": provider_id,
2736
"creation_time": creation_time,
2837
"user_type": user_type,
2938
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import requests
2+
import google.auth.transport.requests
3+
4+
from google.oauth2 import id_token
5+
from google_auth_oauthlib.flow import Flow
6+
from cachecontrol import CacheControl
7+
8+
from authenticator.utils import utils
9+
10+
11+
class GoogleLoginAdapter(object):
12+
def __init__(self):
13+
self.google_obj = utils.read_config()["auth"]["google"]
14+
self.flow = Flow.from_client_secrets_file(
15+
client_secrets_file=self.google_obj["secrets_file"],
16+
scopes=self.google_obj["scopes"],
17+
redirect_uri="http://127.0.0.1:5000/callback",
18+
)
19+
20+
def get_basic_info(self, request, session):
21+
self.flow.fetch_token(authorization_response=request.url)
22+
if not session["state"] == request.args["state"]:
23+
abort(500) # State does not match!
24+
25+
credentials = self.flow.credentials
26+
request_session = requests.session()
27+
cached_session = CacheControl(request_session)
28+
token_request = google.auth.transport.requests.Request(session=cached_session)
29+
id_info = id_token.verify_oauth2_token(
30+
id_token=credentials._id_token,
31+
request=token_request,
32+
audience=self.google_obj["google_client_id"],
33+
)
34+
return id_info

authenticator/adapters/login/loginmanager.py

Lines changed: 0 additions & 6 deletions
This file was deleted.

authenticator/app.py

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import os
2+
import requests
23

3-
from flask import Flask
4-
from flask import jsonify
5-
from flask import request, url_for, redirect, session
6-
from flask_login import logout_user
4+
from flask import Flask, session, url_for, abort, redirect, request
75

86
from authenticator.adapters.db import api as db_api
9-
from authenticator.adapters.login import loginmanager
7+
from authenticator.adapters.login import google_adapter
108
from authenticator.utils import utils
119

1210
database = os.environ.get("db", "authenticator")
@@ -16,69 +14,81 @@
1614
app = Flask(__name__)
1715
app.config["MONGO_URI"] = f"mongodb://{host}:{port}/{database}"
1816
app.config["SECRET_KEY"] = "b9dd1b2f"
17+
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
1918
app.config["GOOGLE_CLIENT_ID"] = os.environ.get("GOOGLE_CLIENT_ID", None)
2019
app.config["GOOGLE_CLIENT_SECRET"] = os.environ.get("GOOGLE_CLIENT_SECRET", None)
2120

2221

2322
db_obj = db_api.MongoAdapters(app)
24-
login_obj = loginmanager.loginManager(app)
23+
google_adapter_obj = google_adapter.GoogleLoginAdapter()
24+
25+
26+
def login_is_required(function):
27+
def wrapper(*args, **kwargs):
28+
if "google_id" not in session:
29+
return abort(401) # Authorization required
30+
else:
31+
return function()
32+
33+
return wrapper
2534

2635

2736
@app.route("/users", methods=["GET"])
2837
def get_users():
2938
return db_obj.get_all_users()
3039

3140

32-
@app.route("/", methods=["GET"])
41+
@app.route("/")
3342
def index():
34-
return "Welcome to nomad Authenticator."
43+
return "Hello World <a href='/googlelogin'><button>Sign Up with google</button></a>"
3544

3645

37-
def add_users(name, email, provider):
46+
def add_users(name, email, provider=None, provider_id=None):
3847
if email == "[email protected]":
39-
print("HELOO")
4048
return db_obj.add_users(
41-
name, email, utils.get_current_time(), provider, "admin"
49+
name, email, utils.get_current_time(), "admin", provider, provider_id
4250
)
43-
return db_obj.add_users(name, email, utils.get_current_time(), provider, "user")
44-
45-
46-
@app.route("/login/google")
47-
def google_login():
48-
login_obj.auth.register(
49-
name="google",
50-
client_id=app.config["GOOGLE_CLIENT_ID"],
51-
client_secret=app.config["GOOGLE_CLIENT_SECRET"],
52-
access_token_url="https://accounts.google.com/o/oauth2/token",
53-
access_token_params=None,
54-
authorize_url="https://accounts.google.com/o/oauth2/auth",
55-
authorize_params=None,
56-
api_base_url="https://www.googleapis.com/oauth2/v1/",
57-
userinfo_endpoint="https://openidconnect.googleapis.com/v1/userinfo",
58-
client_kwargs={"scope": "openid email profile"},
51+
return db_obj.add_users(
52+
name, email, utils.get_current_time(), "user", provider=None, provider_id=None
5953
)
60-
google = login_obj.auth.create_client("google")
61-
redirect_uri = url_for("google_authorize", _external=True)
62-
return google.authorize_redirect(redirect_uri)
6354

6455

65-
@app.route("/login/google/authorize")
66-
def google_authorize():
67-
google = login_obj.auth.create_client("google")
68-
try:
69-
token = google.authorize_access_token()
70-
resp = google.get("userinfo").json()
71-
return add_users(resp["name"], resp["email"], "google")
72-
except Exception:
73-
return redirect("/login/google")
56+
@app.route("/googlelogin")
57+
def login():
58+
authorization_url, state = google_adapter_obj.flow.authorization_url()
59+
session["state"] = state
60+
return redirect(authorization_url)
61+
62+
63+
@app.route("/callback")
64+
def callback():
65+
id_info = google_adapter_obj.get_basic_info(request, session)
66+
if not session["state"] == request.args["state"]:
67+
abort(500) # State does not match!
68+
69+
name = id_info.get("name")
70+
email = id_info.get("email")
71+
google_id = id_info.get("sub")
72+
session["google_id"] = google_id
73+
session["name"] = name
74+
session["email"] = email
75+
add_users(name, email, "google", google_id)
76+
return redirect("/protected_area")
7477

7578

7679
@app.route("/logout")
77-
def user_logout():
78-
for key in list(session.keys()):
79-
session.pop(key)
80+
def logout():
81+
session.clear()
8082
return redirect("/")
8183

8284

85+
@app.route("/protected_area")
86+
@login_is_required
87+
def protected_area():
88+
return (
89+
f"Hello {session['name']}! <br/> <a href='/logout'><button>Logout</button></a>"
90+
)
91+
92+
8393
if __name__ == "__main__":
8494
app.run(debug=True, host="0.0.0.0", port=5000)

authenticator/utils/utils.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1+
import json
12
import time
23

34

45
def get_current_time():
56
return int(time.time()) * 1000
7+
8+
9+
def read_config():
10+
with open("config.json") as fp:
11+
data = json.load(fp)
12+
return data

client_secret.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +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"]}}

config.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"auth":{
3+
"google": {
4+
"access_token_url": "https://accounts.google.com/o/oauth2/token",
5+
"authorize_url": "https://accounts.google.com/o/oauth2/auth",
6+
"api_base_url":"https://www.googleapis.com/oauth2/v1/",
7+
"userinfo_endpoint":"https://openidconnect.googleapis.com/v1/userinfo",
8+
"secrets_file": "client_secret.json",
9+
"redirect_uri": "http://127.0.0.1:5000/callback",
10+
"google_client_id": "1034883885605-gvj78f1cg3urngprb0jjfr3p0olqh8tr.apps.googleusercontent.com",
11+
"scopes": [
12+
"https://www.googleapis.com/auth/userinfo.profile",
13+
"https://www.googleapis.com/auth/userinfo.email",
14+
"openid"
15+
]
16+
}
17+
}
18+
}

0 commit comments

Comments
 (0)