You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
2.7 KiB
Python

import json
from secrets import token_urlsafe
from quart import Blueprint, jsonify, request
from flask_login import current_user
from flipbook.helpers import verify_signature
from flipbook.models import Wallet, rand_id
bp = Blueprint('api', 'api', url_prefix='/api/v1')
@bp.route('/user_authenticated')
async def user_authenticated():
"""
Check to see if sender is authenticated.
Useful for AJAX calls to "check" we're still authenticated
instead of assuming (especially with old, loaded forms/pages).
"""
return jsonify(current_user.is_authenticated)
@bp.route('/user_exists/<wallet_address>')
async def user_exists(wallet_address):
"""
Check to see if a given wallet exists in the database.
This logic will help the login/connect MetaMask flow.
"""
nonce = rand_id()
wallet = Wallet.select().where(
Wallet.address == wallet_address.lower()
).first()
if wallet:
nonce = wallet.nonce
return jsonify({
'user_exists': wallet is not None,
'nonce': nonce,
'success': True
})
@bp.route('/authenticate/metamask', methods=['POST'])
async def authenticate_metamask():
"""
This is the login/authenticate route for this dApp.
Users POST a `signedData` blob, a message signed by the user with MetaMask
(`personal_sign` method).
This route will verify the signed data against the user's public ETH
address. If no user exists, they get an entry in the database.
If user does exist, they get logged in.
"""
data = await request.get_data()
data = json.loads(data)
if current_user.is_authenticated:
return jsonify({
'success': False,
'message': 'Already registered and authenticated.'
})
_u = Wallet.select().where(
Wallet.address == data['public_address']
).first()
if _u:
if data['message'].endswith(_u.nonce):
if verify_signature(data['message'], data['signed_data'], data['public_address']):
_u.login()
return jsonify({
'success': True,
'message': 'Logged in'
})
else:
return jsonify({
'success': False,
'message': 'Invalid signature'
})
else:
return jsonify({
'success': False,
'message': 'Invalid nonce in signed message'
})
else:
w = Wallet(
address=data['public_address'].lower()
)
w.save()
w.login()
return jsonify({
'success': True,
'message': 'Registered'
})