Esempio n. 1
0
def fido2_api_register_begin(request):
    rp = PublicKeyCredentialRpEntity(get_domain(request),
                                     settings.FIDO2_RP_NAME)
    fido2 = Fido2Server(rp)

    all_devices = Fido2Device.objects.filter(user=request.user)

    registration_data, state = fido2.register_begin(
        {
            "id": request.user.email.encode(),
            "name": request.user.email,
            "displayName": request.user.email,
            "icon": "",
        },
        # Pass existing fido2 credentials to prevent duplicate
        credentials=[
            AttestedCredentialData(cbor2.loads(d.authenticator_data))
            for d in all_devices
        ],
        user_verification="discouraged",
        authenticator_attachment="cross-platform",
    )

    request.session[FIDO2_REGISTER_STATE] = state

    return HttpResponse(cbor2.dumps(registration_data),
                        content_type="application/octet-stream")
    def verify_token(self, token):
        data = cbor2.loads(base64.b64decode(token["token"]))
        credential_id = data["credentialId"]
        client_data = ClientData(data["clientDataJSON"])
        auth_data = AuthenticatorData(data["authenticatorData"])
        signature = data["signature"]
        state = token["state"]
        domain = token["domain"]

        credentials_query = Fido2Device.objects.filter(user=self.user)
        credentials = [
            AttestedCredentialData(cbor2.loads(c.authenticator_data))
            for c in credentials_query
        ]

        rp = PublicKeyCredentialRpEntity(domain, settings.FIDO2_RP_NAME)
        fido2 = Fido2Server(rp)

        try:
            fido2.authenticate_complete(
                state,
                credentials,
                credential_id,
                client_data,
                auth_data,
                signature,
            )

            return True
        except ValueError:
            logger.exception("Error in FIDO2 final authentication")
            return False
Esempio n. 3
0
def fido2_api_login_begin(request):
    user = request.user
    credentials_query = Fido2Device.objects.filter(user=user)
    credentials = [
        AttestedCredentialData(cbor2.loads(c.authenticator_data))
        for c in credentials_query
    ]

    rp = PublicKeyCredentialRpEntity(get_domain(request),
                                     settings.FIDO2_RP_NAME)
    fido2 = Fido2Server(rp)
    auth_data, state = fido2.authenticate_begin(
        credentials, user_verification="discouraged")

    request.session["fido2_state"] = state
    request.session["fido2_domain"] = get_domain(request)
    return HttpResponse(cbor2.dumps(auth_data),
                        content_type="application/cbor")
Esempio n. 4
0
def fido2_api_register_finish(request):
    data = cbor2.loads(request.body)
    client_data = ClientData(data["clientDataJSON"])
    att_obj = AttestationObject(data["attestationObject"])

    rp = PublicKeyCredentialRpEntity(get_domain(request),
                                     settings.FIDO2_RP_NAME)
    fido2 = Fido2Server(rp)
    auth_data = fido2.register_complete(request.session[FIDO2_REGISTER_STATE],
                                        client_data, att_obj)

    device = Fido2Device(
        authenticator_data=cbor2.dumps(auth_data.credential_data))
    device.user = request.user
    device.name = data["name"] or "Fido key"
    device.confirmed = True
    device.save()

    return HttpResponse(cbor2.dumps({"status": "OK"}),
                        content_type="application/cbor")
Esempio n. 5
0
def getServer():
    rp = PublicKeyCredentialRpEntity(settings.FIDO_SERVER_ID,
                                     settings.FIDO_SERVER_NAME)
    return Fido2Server(rp)
Esempio n. 6
0
    def do_POST(self):
        origin = self.headers.get('Origin')
        host = origin[len('https://'):]

        rp = PublicKeyCredentialRpEntity(host, 'NGINX Auth Server')
        server = U2FFido2Server(origin, rp)

        if self.path == HTTP_PREFIX + "/get_challenge_for_new_key":
            registration_data, state = server.register_begin({ 'id': b'default', 'name': "Default user", 'displayName': "Default user" })
            registration_data["publicKey"]["challenge"] = str(base64.b64encode(registration_data["publicKey"]["challenge"]), 'utf-8')
            registration_data["publicKey"]["user"]["id"] = str(base64.b64encode(registration_data["publicKey"]["user"]["id"]), 'utf-8')

            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            # Save this challenge to a file so you can kill the host to add the lient via CLI
            with open(LASTCHALLENGE, 'w') as f:
                f.write(json.dumps(state))
            self.wfile.write(bytes(json.dumps(registration_data), 'UTF-8'))
            return

        if self.path == HTTP_PREFIX + "/register":    
            self.send_response(401)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            self.wfile.write(bytes(json.dumps({'error': 'not_configured'}), 'UTF-8'))
            return

        creds = []
        files=glob.glob(CREDENTIALS_DIR + "/*")
        for file in files:
            public_key = ""
            with open(file, 'rb') as f:
                cred, _ = AttestedCredentialData.unpack_from(f.read())
                # TODO add more public-keys which must be stored in AttestedCredentialData
                creds.append(cred)
                auth_data, state =server.authenticate_begin([cred])
                public_key = str(base64.b64encode(auth_data["publicKey"]["allowCredentials"][0]["id"]))[2:-1]
            header_file = HEADERS_DIR + "/" + file.split("/")[-1]
            if os.path.exists(header_file):
                with open(header_file, 'r') as f:
                    HEADER_MANAGER[public_key] = ["Fido-User", "\t".join(f.read().splitlines())]


        if self.path == HTTP_PREFIX + "/get_challenge_for_existing_key":
            auth_data, state = server.authenticate_begin(creds)
            auth_data["publicKey"]["challenge"] = str(base64.b64encode(auth_data["publicKey"]["challenge"]), 'utf-8')
            for el in auth_data["publicKey"]["allowCredentials"]:
                el["id"] = str(base64.b64encode(el["id"]), 'utf-8')
            #auth_data["publicKey"]["allowCredentials"][0]["id"] = str(base64.b64encode(auth_data["publicKey"]["allowCredentials"][0]["id"]), 'utf-8')

            CHALLENGE.update(state)

            self.send_response(200)
            self.send_header('Content-type', 'application/json')
            self.end_headers()
            self.wfile.write(bytes(json.dumps(auth_data), 'UTF-8'))

        if self.path == HTTP_PREFIX + "/complete_challenge_for_existing_key":
            data = json.loads(self.rfile.read(int(self.headers.get('Content-Length'))))

            credential_id = base64.b64decode(data['id'])
            client_data = ClientData(base64.b64decode(data['clientDataJSON']))
            auth_data = AuthenticatorData(base64.b64decode(data['authenticatorData']))
            signature = base64.b64decode(data['signature'])

            with open(LASTCHALLENGE) as f:
                server.authenticate_complete(
                    CHALLENGE,
                    creds,
                    credential_id,
                    client_data,
                    auth_data,
                    signature
                )

            cookie = http.cookies.SimpleCookie()
            header = HEADER_MANAGER.get(data['id'], ["", ""])
            token = TOKEN_MANAGER.generate()
            cookie["token"] = token
            TOKEN_MANAGER.set_header(token, header)
            cookie["token"]["path"] = "/"
            cookie["token"]["secure"] = True

            self.send_response(200)
            self.send_header('Set-Cookie', cookie.output(header=''))
            if header != 0:
                self.send_header(header[0], header[1])
            #self.send_header('Fido-User', "test")
            # TODO sem připsat hlavičku s uživatelem
            self.end_headers()
            self.wfile.write(bytes(json.dumps({'status': 'ok'}), 'UTF-8'))
Esempio n. 7
0
            self.send_response(200)
            self.send_header('Set-Cookie', cookie.output(header=''))
            if header != 0:
                self.send_header(header[0], header[1])
            #self.send_header('Fido-User', "test")
            # TODO sem připsat hlavičku s uživatelem
            self.end_headers()
            self.wfile.write(bytes(json.dumps({'status': 'ok'}), 'UTF-8'))

if len(sys.argv) > 1 and sys.argv[1] == "save-client":
    host = sys.argv[2]
    client_data = ClientData(base64.b64decode(sys.argv[3]))
    attestation_object = AttestationObject(base64.b64decode(sys.argv[4]))

    rp = PublicKeyCredentialRpEntity(host, 'NGINX Auth Server')
    server = U2FFido2Server('https://' + host, rp)

    with open(LASTCHALLENGE) as f:
        auth_data = server.register_complete(json.loads(f.read()), client_data, attestation_object)
        with open(CREDENTIALS_DIR + "/" + sys.argv[5], 'wb') as f:
            f.write(auth_data.credential_data)

    print("Credentials saved successfully")

else:
    socketserver.TCPServer.allow_reuse_address = True
    httpd = socketserver.TCPServer(("", PORT), AuthHandler)
    try:
        print("serving at port", PORT)
        httpd.serve_forever()
Esempio n. 8
0
def getServer():
    """Get Server Info from settings and returns a Fido2Server"""
    rp = PublicKeyCredentialRpEntity(settings.FIDO_SERVER_ID,
                                     settings.FIDO_SERVER_NAME)
    return Fido2Server(rp)
to register and use a credential.

See the file README.adoc in this directory for details.

Navigate to https://localhost:5000 in a supported web browser.
"""

from fido2.client import ClientData
from fido2.server import Fido2Server, PublicKeyCredentialRpEntity
from fido2.ctap2 import AttestationObject, AuthenticatorData
from fido2 import cbor
from flask import Flask, session, request, redirect, abort

import os

rp = PublicKeyCredentialRpEntity("localhost", "Demo server")
server = Fido2Server(rp)

from . import app
from ..database import db_session
from ..models import User


@app.route("/api/register/begin", methods=["POST"])
def register_begin():
    registration_data, state = server.register_begin(
        {
            "id": os.urandom(32),
            "name": "",
            "displayName": "",
        },
Esempio n. 10
0
def get_server():
    rp = PublicKeyCredentialRpEntity(mf_settings['FIDO_SERVER_ID'],
                                     mf_settings['FIDO_SERVER_NAME'],
                                     mf_settings['FIDO_SERVER_ICON'])
    return Fido2Server(rp)