Merge pull request #162 from simple-login/fido-beta

Add Fido as a beta feature
This commit is contained in:
Son Nguyen Kim 2020-05-07 19:28:54 +02:00 committed by GitHub
commit f5efab940c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 93 additions and 28 deletions

View File

@ -1160,18 +1160,7 @@ Whenever the model changes, a new migration has to be created.
If you have Docker installed, you can create the migration by the following script:
```bash
# create a postgres database for SimpleLogin
docker rm -f sl-db
docker run -p 5432:5432 --name sl-db -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=sl -d postgres
# run run `flask db upgrade` to upgrade the DB to the latest stage and
env DB_URI=postgresql://postgres:postgres@127.0.0.1:5432/sl flask db upgrade
# finally `flask db migrate` to generate the migration script.
env DB_URI=postgresql://postgres:postgres@127.0.0.1:5432/sl flask db migrate
# remove the db
docker rm -f sl-db
sh new_migration.sh
```
Make sure to review the migration script before committing it.

View File

@ -31,7 +31,7 @@ def fido():
user = User.get(user_id)
if not (user and (user.fido_enabled())):
if not (user and user.fido_enabled()):
flash("Only user with security key linked should go to this page", "warning")
return redirect(url_for("auth.login"))

View File

@ -85,22 +85,25 @@
</div>
<!-- END change name & profile picture -->
<div class="card">
<div class="card-body">
<div class="card-title">Security Key (WebAuthn)</div>
<div class="mb-3">
You can secure your account by linking either your FIDO-supported physical key such as Yubikey, Google Titan,
or a device with appropriate hardware to your account.
{% if current_user.can_use_fido %}
<div class="card">
<div class="card-body">
<div class="card-title">Security Key (WebAuthn)</div>
<div class="mb-3">
You can secure your account by linking either your FIDO-supported physical key such as Yubikey, Google
Titan,
or a device with appropriate hardware to your account.
</div>
{% if current_user.fido_uuid is none %}
<a href="{{ url_for('dashboard.fido_setup') }}" class="btn btn-outline-primary">Setup WebAuthn</a>
{% else %}
<a href="{{ url_for('dashboard.fido_cancel') }}" class="btn btn-outline-danger">Disable WebAuthn</a>
{% endif %}
</div>
{% if current_user.fido_uuid is none %}
<a href="{{ url_for('dashboard.fido_setup') }}" class="btn btn-outline-primary">Setup WebAuthn</a>
{% else %}
<a href="{{ url_for('dashboard.fido_cancel') }}" class="btn btn-outline-danger">Disable WebAuthn</a>
{% endif %}
</div>
</div>
{% endif %}
<div class="card">
<div class="card" id="totp">
<div class="card-body">
<div class="card-title">One-Time Password (TOTP)</div>
<div class="mb-3">

View File

@ -25,6 +25,13 @@ def fido_setup():
flash("You have already registered your security key", "warning")
return redirect(url_for("dashboard.index"))
if not current_user.can_use_fido:
flash(
"This feature is currently in invitation-only beta. Please send us an email if you want to try",
"warning",
)
return redirect(url_for("dashboard.index"))
fido_token_form = FidoTokenForm()
# Handling POST requests

View File

@ -140,8 +140,13 @@ class User(db.Model, ModelMixin, UserMixin):
fido_pk = db.Column(db.String(), nullable=True, unique=True)
fido_sign_count = db.Column(db.Integer(), nullable=True)
# whether user can use Fido
can_use_fido = db.Column(
db.Boolean, default=False, nullable=False, server_default="0"
)
def fido_enabled(self) -> bool:
if self.fido_uuid is not None:
if self.can_use_fido and self.fido_uuid is not None:
return True
return False

View File

@ -10,11 +10,13 @@ import collections
import phpserialize
import requests
from Crypto.Hash import SHA1
# Crypto can be found at https://pypi.org/project/pycryptodome/
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from app.config import PADDLE_PUBLIC_KEY_PATH, PADDLE_VENDOR_ID, PADDLE_AUTH_CODE
# Your Paddle public key.
from app.log import LOG

View File

@ -0,0 +1,43 @@
"""empty message
Revision ID: 026e7a782ed6
Revises: ae94fe5c4e9f
Create Date: 2020-05-07 17:51:48.440962
"""
import sqlalchemy_utils
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '026e7a782ed6'
down_revision = 'ae94fe5c4e9f'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('users', sa.Column('can_use_fido', sa.Boolean(), server_default='0', nullable=False))
op.add_column('users', sa.Column('fido_credential_id', sa.String(), nullable=True))
op.add_column('users', sa.Column('fido_pk', sa.String(), nullable=True))
op.add_column('users', sa.Column('fido_sign_count', sa.Integer(), nullable=True))
op.add_column('users', sa.Column('fido_uuid', sa.String(), nullable=True))
op.create_unique_constraint(None, 'users', ['fido_credential_id'])
op.create_unique_constraint(None, 'users', ['fido_pk'])
op.create_unique_constraint(None, 'users', ['fido_uuid'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'users', type_='unique')
op.drop_constraint(None, 'users', type_='unique')
op.drop_constraint(None, 'users', type_='unique')
op.drop_column('users', 'fido_uuid')
op.drop_column('users', 'fido_sign_count')
op.drop_column('users', 'fido_pk')
op.drop_column('users', 'fido_credential_id')
op.drop_column('users', 'can_use_fido')
# ### end Alembic commands ###

16
new_migration.sh Normal file
View File

@ -0,0 +1,16 @@
# Generate a new migration script using Docker
# To run it:
# sh new_migration.sh
# create a postgres database for SimpleLogin
docker rm -f sl-db
docker run -p 5432:5432 --name sl-db -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=sl -d postgres
# run run `flask db upgrade` to upgrade the DB to the latest stage and
env DB_URI=postgresql://postgres:postgres@127.0.0.1:5432/sl flask db upgrade
# finally `flask db migrate` to generate the migration script.
env DB_URI=postgresql://postgres:postgres@127.0.0.1:5432/sl flask db migrate
# remove the db
docker rm -f sl-db

View File

@ -13,7 +13,7 @@
{% block content %}
{{ render_text("My name is Son. Im the founder of SimpleLogin and I wanted to be the first to welcome you on board.") }}
{{ render_text('To better secure your account, I recommend enabling Multi-Factor Authentication (MFA) on your <a href="https://app.simplelogin.io/dashboard/setting">Setting page</a>.') }}
{{ render_text('To better secure your account, I recommend enabling Multi-Factor Authentication (MFA) on your <a href="https://app.simplelogin.io/dashboard/setting/#totp">Setting page</a>.') }}
{{ render_text('If you have any feedback or improvement ideas please let me know by simply replying to this email. Yes, this email is not sent from a no-reply address.
') }}