Exemplo n.º 1
0
def forwards_func(apps, schema_editor):
    # We get the model from the versioned app registry;
    U2FDevice = apps.get_model("sso_auth", "U2FDevice")
    db_alias = schema_editor.connection.alias
    for d in U2FDevice.objects.using(db_alias).all():
        credential_data = AttestedCredentialData.from_ctap1(websafe_decode(d.key_handle), websafe_decode(d.public_key_old))

        d.public_key = websafe_encode(cbor.encode(credential_data.public_key))
        d.aaguid = websafe_encode(credential_data.aaguid)
        d.credential_id = websafe_encode(credential_data.credential_id)
        d.save()
Exemplo n.º 2
0
def complete_reg(request):
    try:
        data = cbor.loads(request.body)[0]

        client_data = ClientData(data['clientDataJSON'])
        att_obj = AttestationObject((data['attestationObject']))
        server = getServer()
        auth_data = server.register_complete(request.session['fido_state'],
                                             client_data, att_obj)
        encoded = websafe_encode(auth_data.credential_data)
        uk = User_Keys()
        uk.username = request.user.username
        uk.properties = {
            "device": encoded,
            "type": att_obj.fmt,
        }
        uk.key_type = "FIDO2"
        uk.save()
        return HttpResponse(simplejson.dumps({'status': 'OK'}))
    except Exception as exp:
        from raven.contrib.django.raven_compat.models import client
        import traceback
        client.captureException()
        return HttpResponse(
            simplejson.dumps({
                'status':
                'ERR',
                "message":
                "Error on server, please try again later"
            }))
Exemplo n.º 3
0
def register_complete(name, **kwargs):
    """
    Complete registration of the new key and save it under a given name

    Variables:
    name    => Name of the token

    Arguments:
    data    => Response to the enroll challenge

    Data Block:
    None

    Result example:
    {
     "success": True
    }
    """
    uname = kwargs['user']['uname']
    user = STORAGE.user.get(uname, as_obj=False)
    data = cbor.decode(bytes(request.json))

    client_data = ClientData(data['clientDataJSON'])
    att_obj = AttestationObject(data['attestationObject'])

    auth_data = server.register_complete(session.pop('state', None), client_data, att_obj)

    security_tokens = user.get('security_tokens', {})
    if name in security_tokens:
        return make_api_response({'success': False}, err="A token with this name already exist", status_code=400)

    security_tokens[name] = websafe_encode(auth_data.credential_data)
    user['security_tokens'] = security_tokens

    return make_api_response({"success": STORAGE.user.save(uname, user)})
Exemplo n.º 4
0
def complete_reg(request):
    """Completes the registeration, called by API"""
    try:
        data = cbor.decode(request.body)

        client_data = ClientData(data['clientDataJSON'])
        att_obj = AttestationObject((data['attestationObject']))
        server = getServer()
        auth_data = server.register_complete(request.session['fido_state'],
                                             client_data, att_obj)
        encoded = websafe_encode(auth_data.credential_data)
        uk = User_Keys()
        uk.username = request.user.username
        uk.properties = {
            "device": encoded,
            "type": att_obj.fmt,
        }
        uk.owned_by_enterprise = getattr(settings, "MFA_OWNED_BY_ENTERPRISE",
                                         False)
        uk.key_type = "FIDO2"
        uk.save()
        return HttpResponse(simplejson.dumps({'status': 'OK'}))
    except Exception as exp:
        try:
            from raven.contrib.django.raven_compat.models import client
            client.captureException()
        except:
            pass
        return HttpResponse(
            simplejson.dumps({
                'status':
                'ERR',
                "message":
                "Error on server, please try again later"
            }))
Exemplo n.º 5
0
def attest(rp, user, credset, attset):
    credset_dict = credset_decode(credset)
    attset_dict = attset_decode(attset)

    server = cred_server(rp)
    challenge = cred_challenge(rp, user)

    create_options, state = server.register_begin(user, challenge=challenge)

    client_data = ClientData.build(
        type=WEBAUTHN_TYPE.MAKE_CREDENTIAL,
        origin=fidosig_origin(rp['id']),
        challenge=websafe_encode(challenge),
        clientExtensions={},
    )

    for credential_id, public_key in credset_dict.items():
        if credential_id not in attset_dict:
            raise Exception('Missing attestation')
        attestation_object = attset_dict[credential_id]
        auth_data = server.register_complete(state, client_data,
                                             attestation_object)
        if auth_data.credential_data.credential_id != credential_id:
            raise Exception('Wrong credential id')
        if auth_data.credential_data.public_key != public_key:
            raise Exception('Wrong public key')
Exemplo n.º 6
0
def complete_reg(request):
    try:
        data = cbor.decode(request.body)

        client_data = ClientData(data['clientDataJSON'])
        att_obj = AttestationObject((data['attestationObject']))
        server = get_server()
        auth_data = server.register_complete(request.session['fido_state'],
                                             client_data, att_obj)
        encoded = websafe_encode(auth_data.credential_data)
        key = UserKey.objects.create(
            user=request.user,
            properties={
                "device": encoded,
                "type": att_obj.fmt,
                "domain": request.get_host(),
            },
            key_type=KEY_TYPE_FIDO2,
        )
        write_session(request, key)
        messages.success(request, 'FIDO2 Token added!')
        return JsonResponse({'status': 'OK'})

    except Exception:
        logger.exception("Error completing FIDO2 registration.")
        return JsonResponse({
            'status':
            'ERR',
            "message":
            "Error on server, please try again later",
        })
    def _get_assertion_request(
        rp_id: str = 'pasten.com',
        client_data: Optional[ClientData] = None,
        allowed_cred_ids: Optional[List[bytes]] = None,
        user_verification_required=False,
    ) -> dict:

        client_data = client_data or ClientData.build(
            typ=WEBAUTHN_TYPE.GET_ASSERTION,
            origin=rp_id,
            challenge=websafe_encode(b'pasten-challenge'),
        )
        req = {
            CtapGetAssertionRequest.RP_ID_KEY: rp_id,
            CtapGetAssertionRequest.CLIENT_DATA_HASH_KEY: client_data.hash,
        }

        if user_verification_required:
            req[CtapGetAssertionRequest.OPTIONS_KEY] = {
                CtapOptions.USER_VERIFICATION: True
            }

        if allowed_cred_ids:
            req[CtapGetAssertionRequest.ALLOW_LIST_KEY] = [
                PublicKeyCredentialDescriptor(
                    PublicKeyCredentialType.PUBLIC_KEY, cred_id
                )
                for cred_id in allowed_cred_ids
            ]

        return req
Exemplo n.º 8
0
Arquivo: models.py Projeto: g10f/sso
    def authenticate_complete(cls, response_data, state_data, user):
        response = cbor.decode(b64decode(response_data))
        state = signing.loads(state_data, salt=U2FDevice.WEB_AUTHN_SALT)
        credential_id = response["credentialId"]
        client_data = ClientData(response["clientDataJSON"])
        auth_data = AuthenticatorData(response["authenticatorData"])
        signature = response["signature"]

        credentials = U2FDevice.credentials(user)
        cred = cls.server.authenticate_complete(
            state,
            credentials,
            credential_id,
            client_data,
            auth_data,
            signature,
        )
        credential_id = websafe_encode(cred.credential_id)
        device = U2FDevice.objects.get(user=user, credential_id=credential_id)
        if auth_data.counter <= device.counter:
            # verify counter is increasing
            raise ValueError(
                f"login counter is not increasing. {auth_data.counter} <= {device.counter} "
            )
        device.last_used = timezone.now()
        device.counter = auth_data.counter
        device.save(update_fields=["last_used", "counter"])
        return device
Exemplo n.º 9
0
def complete_reg(request):
    try:
        data = cbor.decode(request.body)

        client_data = ClientData(data['clientDataJSON'])
        att_obj = AttestationObject((data['attestationObject']))
        server = get_server()
        auth_data = server.register_complete(request.session['fido_state'],
                                             client_data, att_obj)
        encoded = websafe_encode(auth_data.credential_data)
        UserKey.objects.create(
            username=request.user.get_username(),
            properties={
                "device": encoded,
                "type": att_obj.fmt
            },
            key_type="FIDO2",
        )
        return JsonResponse({'status': 'OK'})

    except:
        return JsonResponse({
            'status':
            'ERR',
            "message":
            "Error on server, please try again later",
        })
Exemplo n.º 10
0
 def test_websafe_encode(self):
     self.assertEqual(websafe_encode(b""), "")
     self.assertEqual(websafe_encode(b"f"), "Zg")
     self.assertEqual(websafe_encode(b"fo"), "Zm8")
     self.assertEqual(websafe_encode(b"foo"), "Zm9v")
     self.assertEqual(websafe_encode(b"foob"), "Zm9vYg")
     self.assertEqual(websafe_encode(b"fooba"), "Zm9vYmE")
     self.assertEqual(websafe_encode(b"foobar"), "Zm9vYmFy")
Exemplo n.º 11
0
 def test_websafe_encode(self):
     self.assertEqual(websafe_encode(b''), u'')
     self.assertEqual(websafe_encode(b'f'), u'Zg')
     self.assertEqual(websafe_encode(b'fo'), u'Zm8')
     self.assertEqual(websafe_encode(b'foo'), u'Zm9v')
     self.assertEqual(websafe_encode(b'foob'), u'Zm9vYg')
     self.assertEqual(websafe_encode(b'fooba'), u'Zm9vYmE')
     self.assertEqual(websafe_encode(b'foobar'), u'Zm9vYmFy')
Exemplo n.º 12
0
def _get_assertions(seed, rp, options):
    client_data = ClientData.build(
        type=WEBAUTHN_TYPE.GET_ASSERTION,
        origin=fidosig_origin(rp['id']),
        challenge=websafe_encode(options.challenge),
        clientExtensions={},
    )
    client_data_hash = client_data.hash
    rp_id_hash = sha256(rp['id'].encode('utf8')).digest()
    assertions = [
        _get_assertion_1(seed, rp_id_hash, descriptor, client_data_hash)
        for descriptor in options.allow_credentials
    ]
    return assertions, client_data
Exemplo n.º 13
0
def do_register_user(user, rp_id, resident_key=False):
    """
    FIDO2 registration process
    :param user: The user to register
    :param rp_id: Relying Party identifier
    :param resident_key: Boolean indicating whether or not to store a
    resident key
    :return: Newly created credentials
    """
    # begin registration
    relying_part = RelyingParty(rp_id)
    server = Fido2Server(relying_part)

    registration_data, state = server.register_begin(user)

    # make credential
    dev = next(CtapHidDevice.list_devices(), None)
    if not dev:
        print('No FIDO device found')
        sys.exit(1)

    client = Fido2Client(dev, 'https://' + rp_id)
    rp = {'id': rp_id, 'name': rp_id}
    challenge = websafe_encode(registration_data['publicKey']['challenge'])

    if resident_key:
        user['name'] = "."
        user_string = "(id: {0})".format(user['id'].hex())
    else:
        user_string = "(name: {0}, display name: {1})".format(
            user['name'], user['displayName'])

    print("\nRegistration request for user: "******"From service: (Address: {0}, Name: {1})".format(rp['id'],
                                                           rp['name']))
    print('Touch your authenticator device now to consent to registration...\n')
    try:
        attestation_object, client_data = client.make_credential(
            rp, user, challenge, rk=resident_key)
    except Exception as e:
        print("Registration failed")
        raise e

    # complete registration
    registration_data = server.register_complete(state, client_data,
                                                 attestation_object)
    credential = registration_data.credential_data
    print("Registration complete")

    return credential
Exemplo n.º 14
0
Arquivo: models.py Projeto: g10f/sso
    def register_complete(cls, name, response_data, state_data, user):
        data = cbor.decode(b64decode(response_data))
        state = signing.loads(state_data, salt=U2FDevice.WEB_AUTHN_SALT)
        client_data = ClientData(data["clientDataJSON"])
        att_obj = AttestationObject(data["attestationObject"])
        logger.debug("clientData", client_data)
        logger.debug("AttestationObject:", att_obj)

        auth_data = cls.server.register_complete(state, client_data, att_obj)
        logger.debug(auth_data)
        public_key = websafe_encode(
            cbor.encode(auth_data.credential_data.public_key))
        aaguid = websafe_encode(auth_data.credential_data.aaguid)
        credential_id = websafe_encode(auth_data.credential_data.credential_id)

        device = U2FDevice.objects.create(name=name,
                                          user=user,
                                          public_key=public_key,
                                          credential_id=credential_id,
                                          aaguid=aaguid,
                                          confirmed=True,
                                          version="fido2")
        return device
Exemplo n.º 15
0
def get_access_key(rpi_username, verify=True, uv=False):
    auth_begin_response = requests.request(
        'GET', AUTHENTICATE_BEGIN_URI.format(rpi_username), verify=verify)
    assert auth_begin_response.status_code == 200
    cookies = auth_begin_response.cookies
    auth_begin_response_dict = cbor.decode(auth_begin_response.content)
    urlparse_result = urlparse(AUTHENTICATE_BEGIN_URI)
    scheme = urlparse_result.scheme
    origin = urlparse_result.hostname
    rp_id = auth_begin_response_dict['publicKey']['rpId']
    challenge = websafe_encode(
        auth_begin_response_dict['publicKey']['challenge'])
    allow_list = auth_begin_response_dict['publicKey']['allowCredentials']
    fido2_client = create_fido2_client('{}://{}'.format(scheme, origin))
    assertions, client_data = fido2_client.get_assertion(rp_id,
                                                         challenge,
                                                         allow_list,
                                                         uv=uv)
    access_key = websafe_encode(assertions[0].signature)
    auth_complete_payload = dict(
        credentialId=assertions[0].credential['id'],
        clientDataJSON=client_data,
        authenticatorData=assertions[0].auth_data,
        signature=assertions[0].signature,
    )
    auth_complete_payload_encoded = cbor.encode(auth_complete_payload)
    auth_complete_response = requests.post(
        AUTHENTICATE_COMPLETE_URI.format(rpi_username),
        data=auth_complete_payload_encoded,
        verify=verify,
        cookies=cookies,
    )
    auth_complete_response_decoded = cbor.decode(
        auth_complete_response.content)
    assert auth_complete_response_decoded.get('status') == 'OK'
    return access_key
Exemplo n.º 16
0
def u2f_begin():
    registration_data, state = server.register_begin(
        {
            'id': b'user_id',
            'name': 'a_user',
            'displayName': 'A. User',
            'icon': 'https://example.com/image.png'
        }, credentials)

    session['state'] = state
    print('\n\n\n\n')
    print(registration_data)
    print('\n\n\n\n')
    return cbor.dumps(
        websafe_encode(registration_data['publicKey']['challenge']))
Exemplo n.º 17
0
def u2f_begin():
    registration_data, state = server.register_begin(
        {
            "id": b"user_id",
            "name": "a_user",
            "displayName": "A. User",
        },
        credentials,
    )

    session["state"] = state
    print("\n\n\n\n")
    print(registration_data)
    print("\n\n\n\n")
    return cbor.encode(
        websafe_encode(registration_data["publicKey"]["challenge"]))
Exemplo n.º 18
0
def register_complete():
    data = cbor.decode(flask.request.get_data())
    client_data = ClientData(data["clientDataJSON"])
    att_obj = AttestationObject(data["attestationObject"])
    # print("clientData", client_data)
    # print("AttestationObject:", att_obj)

    auth_data = server.register_complete(flask.session["state"], client_data,
                                         att_obj)

    flask.session["credentials"].append(auth_data.credential_data)
    encoded = websafe_encode(auth_data.credential_data)
    users = cube.load_file("users")
    users[flask.session["account"]]["yubi"] = encoded
    cube.dump_file(users, "users")

    # print("REGISTERED CREDENTIAL:", auth_data.credential_data)
    return cbor.encode({"status": "OK"})
Exemplo n.º 19
0
    def generate_assertion_request(self, user_id=None):
        """
        Generate an assertion request
        :param user_id: The user id
        :return: The FIDO2AssertionRequest message
        """
        user_credentials = self._get_user_credentials(user_id)
        request_options, self._auth_state = \
            self._server.authenticate_begin(user_credentials)

        # check request options
        request_options = request_options['publicKey']
        challenge = websafe_encode(request_options['challenge'])
        timeout = None
        rp_id = None
        allow_credentials = None
        user_verification = None
        extensions = None
        eph_user_name_server_share = None

        # fill optional information
        if 'timeout' in request_options:
            timeout = request_options['timeout']
        if 'rpId' in request_options:
            rp_id = request_options['rpId']
        if 'allowCredentials' in request_options:
            allow_credentials = request_options['allowCredentials']
            self._allow_credentials = allow_credentials
        if 'userVerification' in request_options:
            user_verification = request_options['userVerification'].value
        if 'extensions' in request_options:
            extensions = request_options['extensions']
        if self.mode == FIDO2Mode.fido2_with_name and \
                self.pre_share_eph_user_name:
            eph_user_name_server_share = bytearray(urandom(32))
            self._eph_user_name_server_share = \
                eph_user_name_server_share

        fido2_assertion_request = FIDO2AssertionRequest().create(
            challenge, timeout, rp_id, allow_credentials, user_verification,
            extensions, eph_user_name_server_share)

        return fido2_assertion_request
    def _get_make_credential_request(
        algorithm: int = cose.RS256.ALGORITHM,
        user_id: str = '*****@*****.**',
        user_name: str = 'pasten',
        rp_id: str = 'pasten.com',
        rp_name: str = 'Pasten LTD',
        client_data: Optional[ClientData] = None,
        excluded_cred_ids: Optional[List[bytes]] = None,
    ) -> dict:

        client_data = client_data or ClientData.build(
            typ=WEBAUTHN_TYPE.MAKE_CREDENTIAL,
            origin=rp_id,
            challenge=websafe_encode(b'pasten-challenge'),
        )

        req = {
            CtapMakeCredentialRequest.CLIENT_DATA_HASH_KEY: hashlib.sha256(
                client_data
            ).digest(),
            CtapMakeCredentialRequest.RP_KEY: PublicKeyCredentialRpEntity(
                rp_id, rp_name
            ),
            CtapMakeCredentialRequest.USER_KEY: PublicKeyCredentialUserEntity(
                user_id, user_name
            ),
            CtapMakeCredentialRequest.PUBLIC_KEY_CREDENTIAL_PARAMS_KEY: [
                PublicKeyCredentialParameters(
                    PublicKeyCredentialType.PUBLIC_KEY, algorithm
                )
            ],
        }

        if excluded_cred_ids:
            req[CtapMakeCredentialRequest.EXCLUDE_LIST_KEY] = [
                PublicKeyCredentialDescriptor(
                    PublicKeyCredentialType.PUBLIC_KEY, cred_id
                )
                for cred_id in excluded_cred_ids
            ]

        return req
Exemplo n.º 21
0
def _verify_1(rp, header, msg, credential_id, public_key, sig):
    randomization = sig[SIGENTRY.RANDOMIZATION]
    auth_data = AuthenticatorData(sig[SIGENTRY.AUTH_DATA])
    signature = sig[SIGENTRY.SIGNATURE]

    server = sign_server(rp)
    challenge = sign_challenge(randomization, header, msg)

    request_options, state = server.authenticate_begin(
        user_verification=UserVerificationRequirement.DISCOURAGED,
        challenge=challenge,
    )

    client_data = ClientData.build(
        type=WEBAUTHN_TYPE.GET_ASSERTION,
        origin=fidosig_origin(rp['id']),
        challenge=websafe_encode(challenge),
        clientExtensions={},
    )

    credentials = [AttestedCredentialData.create(
        b'\0' * 16, credential_id, public_key
    )]

    try:
        server.authenticate_complete(
            state,
            credentials,
            credential_id,
            client_data,
            auth_data,
            signature,
        )
    except InvalidSignature:
        return False
    return True
Exemplo n.º 22
0
 def test_websafe_encode_unicode(self):
     self.assertEqual(websafe_encode(u''), u'')
     self.assertEqual(websafe_encode(u'foobar'), u'Zm9vYmFy')
Exemplo n.º 23
0
# id stored in DB, queried via user name
user = {"id": b"user_id", "name": "A. User"}

# Prepare parameters for makeCredential
create_options, state = server.register_begin(
    user, user_verification=uv, authenticator_attachment="cross-platform")

# Create a credential
if use_prompt:
    print("\nTouch your authenticator device now...\n")

attestation_object, client_data = client.make_credential(
    create_options["publicKey"], pin=pin)

# Complete registration
auth_data = server.register_complete(state, client_data, attestation_object)
credentials = [auth_data.credential_data]
# Credentials is what needs to be stored

print("New credential created!")

# https://github.com/Yubico/python-fido2/issues/31
encoded = websafe_encode(auth_data.credential_data)  # Store this value

print("Credentials: ")
print(auth_data.credential_data)
print()
print("Encoded: ")
print(encoded)
#credential_data = AttestedCredentialData(websafe_decode(encoded))  # Restored from serialized value
Exemplo n.º 24
0
 def credential(self, cred):
     self.cred_data = websafe_encode(cred)
     self.cred_id = websafe_encode(cred.credential_id)
Exemplo n.º 25
0

for dev in enumerate_devices():
    client = Fido2Client(dev, "https://secrez.io")
    if HmacSecretExtension.NAME in client.info.extensions:
        break
else:
    print("No Authenticator with the HmacSecret extension found!")
    sys.exit(1)

rp = {"id": "secrez.io", "name": "secrez"}
user = {"id": bytes(user_id, encoding='utf-8'), "name": user_name}
challenge = bytes(randomString(12), encoding='utf-8')
hmac_ext = HmacSecretExtension(client.ctap2)
attestation_object, client_data = client.make_credential({
    "rp":
    rp,
    "user":
    user,
    "challenge":
    challenge,
    "pubKeyCredParams": [{
        "type": "public-key",
        "alg": -7
    }],
    "extensions":
    hmac_ext.create_dict(),
})
credential = attestation_object.auth_data.credential_data
print(websafe_encode(credential))
Exemplo n.º 26
0
attestation_object, client_data = client.make_credential(
    create_options["publicKey"], pin=pin)

# Complete registration
auth_data = server.register_complete(state, client_data, attestation_object)
credentials = [auth_data.credential_data]
# Credentials is what needs to be stored

print("New credential created!")

print("CLIENT DATA:", client_data)
print("ATTESTATION OBJECT:", attestation_object)
print()
print("CREDENTIAL DATA:", auth_data.credential_data)

encoded = websafe_encode(auth_data.credential_data)

creds2 = [AttestedCredentialData(websafe_decode(encoded))]

# Prepare parameters for getAssertion
#request_options, state = server.authenticate_begin(credentials, user_verification=uv)
request_options, state = server.authenticate_begin(creds2,
                                                   user_verification=uv)

# Authenticate the credential
if use_prompt:
    print("\nTouch your authenticator device now...\n")

assertions, client_data = client.get_assertion(request_options["publicKey"],
                                               pin=pin)
assertion = assertions[
Exemplo n.º 27
0
                "login": "******",
                "firstName": "Bob",
                "timeZone": "America/Los_Angeles",
            },
            "id": "XXXIDXXX",
        }
    },
    "sessionToken": "XXXTOKENXXX",
}

CREDENTIAL_ID_STR = b"ababababababa"
CREDENTIAL_ID_ENC = "YWJhYmFiYWJhYmFiYQ=="
CREDENTIAL_ID_DEC = base64.urlsafe_b64decode(CREDENTIAL_ID_ENC)

NONCE_STR = b"anonce"
NONCE_ENC = websafe_encode(NONCE_STR)

CHALLENGE_RESPONSE = {
    "status": "MFA_CHALLENGE",
    "_embedded": {
        "factor": {
            "profile": {
                "credentialId": CREDENTIAL_ID_ENC,
                "authenticatorName": "yekibuy",
            },
            "_embedded": {
                "challenge": {
                    "challenge": NONCE_ENC,
                    "extensions": {}
                }
            },