forked from CybersecurityLuxembourg/openxeco-core
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #47 from kenny-niu/two-factor-authentication
Add Simple Two Factor Authentication
Showing
8 changed files
with
273 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
"""empty message | ||
Revision ID: b1327fd4d9d7 | ||
Revises: 8692e9512214 | ||
Create Date: 2022-12-01 06:33:42.361181 | ||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
from sqlalchemy.dialects import mysql | ||
|
||
|
||
# revision identifiers, used by Alembic. | ||
revision = 'b1327fd4d9d7' | ||
down_revision = '8692e9512214' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
op.create_table('UserOtp', | ||
sa.Column('id', mysql.INTEGER(), autoincrement=True, nullable=False), | ||
sa.Column('token', mysql.VARCHAR(charset='utf8mb4', collation='utf8mb4_unicode_ci', length=110), nullable=False), | ||
sa.Column('timestamp', sa.DATETIME(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), | ||
|
||
sa.Column('user_id', mysql.INTEGER(), nullable=False), | ||
sa.ForeignKeyConstraint(['user_id'], ['User.id'], name='otp_relationship_upfk_1', ondelete='CASCADE'), | ||
|
||
sa.PrimaryKeyConstraint('id'), | ||
sa.UniqueConstraint('user_id', name='otp_relationship_type_unique_user'), | ||
mysql_collate='utf8mb4_unicode_ci', | ||
mysql_default_charset='utf8mb4', | ||
mysql_engine='InnoDB' | ||
) | ||
|
||
|
||
def downgrade(): | ||
op.drop_table('UserOtp') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import datetime | ||
from flask import request | ||
from flask_apispec import MethodResource | ||
from flask_apispec import use_kwargs, doc | ||
from flask_restful import Resource | ||
from flask_jwt_extended import create_access_token, create_refresh_token | ||
from webargs import fields | ||
|
||
from decorator.catch_exception import catch_exception | ||
|
||
class VerifyLogin(MethodResource, Resource): | ||
|
||
db = None | ||
mail = None | ||
|
||
def __init__(self, db, mail): | ||
self.db = db | ||
self.mail = mail | ||
|
||
@doc(tags=['account'], | ||
description='Verify login token', | ||
responses={ | ||
"200": {}, | ||
"422.a": {"description": "This one time pin is invalid"}, | ||
"422.b": {"description": "This one time pin has expired"}, | ||
}) | ||
@use_kwargs({ | ||
'email': fields.Str(), | ||
'token': fields.Str(), | ||
}) | ||
@catch_exception | ||
def post(self, **kwargs): | ||
|
||
if 'HTTP_ORIGIN' in request.environ and request.environ['HTTP_ORIGIN']: | ||
origin = request.environ['HTTP_ORIGIN'] | ||
else: | ||
return "", "500 Impossible to find the origin. Please contact the administrator" | ||
|
||
user = self.db.get(self.db.tables["User"], {"email": kwargs["email"]}) | ||
otp = self.db.get(self.db.tables["UserOtp"], {"user_id": user[0].id}) | ||
|
||
if len(otp) < 1: | ||
return "", "422 This one time pin is invalid." | ||
|
||
# Verify token | ||
if otp[0].token != kwargs["token"]: | ||
return "", "422 This one time pin is invalid." | ||
token_timestamp = otp[0].timestamp.timestamp() | ||
now_timestamp = datetime.datetime.now().timestamp() | ||
if now_timestamp - token_timestamp > 600: | ||
return "", "422 This one time pin has expired." | ||
|
||
# delete token if valid | ||
self.db.delete(self.db.tables["UserOtp"], {"id": otp[0].id}) | ||
|
||
access_token_expires = datetime.timedelta(days=1) | ||
refresh_token_expires = datetime.timedelta(days=365) | ||
access_token = create_access_token(identity=str(user[0].id), expires_delta=access_token_expires) | ||
refresh_token = create_refresh_token(identity=str(user[0].id), expires_delta=refresh_token_expires) | ||
|
||
return { | ||
"user": user[0].id, | ||
"access_token": access_token, | ||
"refresh_token": refresh_token, | ||
}, "200 " |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<p>Dear {{ email }},</p> | ||
<p>To complete your login, please enter the following One Time Pin:</p> | ||
|
||
<p style="background: #fefefe; padding: 10px; border-radius: 5px; font-size: 20px;"> | ||
{{ token|safe }} | ||
</p> | ||
|
||
<span style="font-style: italic; font-size: 0.8rem;">This code expires in 10 minutes.</span> | ||
|
||
<p>Sincerely,</p> | ||
<p> | ||
<img src="cid:logo" alt="Logo" style="width:200px;"> | ||
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.