Esempio n. 1
0
    def authenticate(self, request: HttpRequest, user: Optional[AbstractBaseUser], fido2_server: Fido2Server,
                     fido2_state: Dict[str, bytes], fido2_response: Dict[str, Any]) -> Optional[AbstractBaseUser]:
        """Authenticate using FIDO 2."""
        user_handle = fido2_response['user_handle']

        try:
            device = Authenticator.objects.get(user_handle=user_handle)
            user = device.user
            credentials = [device.credential]
            fido2_server.authenticate_complete(
                fido2_state, credentials, fido2_response['credential_id'], fido2_response['client_data'],
                fido2_response['authenticator_data'], fido2_response['signature'])
        except ValueError as error:
            _LOGGER.info("FIDO 2 authentication failed with error: %r", error)
            return None
        except Authenticator.DoesNotExist:
            _LOGGER.info("FIDO 2 authentication could not find user handle: %s", user_handle)
            return None

        try:
            self.mark_device_used(device, fido2_response['authenticator_data'].counter)
        except ValueError:
            # Raise `PermissionDenied` to stop the authentication process and skip remaining backends.
            messages.error(request, self.counter_error_message)
            raise PermissionDenied("Counter didn't increase.")
        return user
Esempio n. 2
0
 def server(self) -> Fido2Server:
     """Return FIDO 2 server instance."""
     rp = PublicKeyCredentialRpEntity(self.get_rp_id(), self.get_rp_name())
     if AttestationVerifier is None:
         return Fido2Server(rp, attestation=self.attestation, attestation_types=self.attestation_types)
     elif self.verify_attestation is None:
         if self.attestation_types is not None:
             warnings.warn('You have defined `attestation_types` but not `verify_attestation`, this means that the '
                           '`attestation_types` setting is being iognored.', DeprecationWarning)
         return Fido2Server(rp, attestation=self.attestation)
     else:
         return Fido2Server(rp, attestation=self.attestation,
                            verify_attestation=self.verify_attestation(self.attestation_types))
Esempio n. 3
0
    def test_authenticate_complete_invalid_signature(self):
        rp = PublicKeyCredentialRpEntity("Example", "example.com")
        server = Fido2Server(rp)

        state = {
            "challenge": "GAZPACHO!",
            "user_verification": UserVerificationRequirement.PREFERRED,
        }
        client_data = CollectedClientData.create(
            CollectedClientData.TYPE.GET,
            "GAZPACHO!",
            "https://example.com",
        )
        _AUTH_DATA = bytes.fromhex(
            "A379A6F6EEAFB9A55E378C118034E2751E682FAB9F2D30AB13D2125586CE1947010000001D"
        )
        with self.assertRaisesRegex(ValueError, "Invalid signature."):
            server.authenticate_complete(
                state,
                [AttestedCredentialData(_ATT_CRED_DATA)],
                _CRED_ID,
                client_data,
                AuthenticatorData(_AUTH_DATA),
                b"INVALID",
            )
Esempio n. 4
0
    def test_register_begin_custom_challenge_too_short(self):
        rp = PublicKeyCredentialRpEntity("Example", "example.com")
        server = Fido2Server(rp)

        challenge = b"123456789012345"
        with self.assertRaises(ValueError):
            request, state = server.register_begin(USER, challenge=challenge)
Esempio n. 5
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. 7
0
    def authenticate(
            self, request: HttpRequest, user: AbstractBaseUser,
            fido2_server: Fido2Server, fido2_state: Dict[str, bytes],
            fido2_response: Dict[str, Any]) -> Optional[AbstractBaseUser]:
        """Authenticate using FIDO 2."""
        credentials = [a.credential for a in user.authenticators.all()]
        try:
            credential = fido2_server.authenticate_complete(
                fido2_state, credentials, fido2_response['credential_id'],
                fido2_response['client_data'],
                fido2_response['authenticator_data'],
                fido2_response['signature'])
        except ValueError as error:
            _LOGGER.info("FIDO 2 authentication failed with error: %r", error)
            return None

        device = user.authenticators.get(credential_id_data=base64.b64encode(
            credential.credential_id).decode('utf-8'))
        try:
            self.mark_device_used(device,
                                  fido2_response['authenticator_data'].counter)
        except ValueError:
            # Raise `PermissionDenied` to stop the authentication process and skip remaining backends.
            messages.error(request, self.counter_error_message)
            raise PermissionDenied("Counter didn't increase.")
        return user
Esempio n. 8
0
    def test_register_begin_custom_challenge_too_short(self):
        rp = RelyingParty("example.com", "Example")
        server = Fido2Server(rp)

        challenge = b"123456789012345"
        with self.assertRaises(ValueError):
            request, state = server.register_begin({}, challenge=challenge)
Esempio n. 9
0
    def test_authenticate_complete_invalid_signature(self):
        rp = RelyingParty("example.com", "Example")
        server = Fido2Server(rp)

        state = {
            "challenge": "GAZPACHO!",
            "user_verification": USER_VERIFICATION.PREFERRED,
        }
        client_data_dict = {
            "challenge": "GAZPACHO!",
            "origin": "https://example.com",
            "type": WEBAUTHN_TYPE.GET_ASSERTION,
        }
        client_data = ClientData(json.dumps(client_data_dict).encode("utf-8"))
        _AUTH_DATA = a2b_hex(
            "A379A6F6EEAFB9A55E378C118034E2751E682FAB9F2D30AB13D2125586CE1947010000001D"
        )
        with six.assertRaisesRegex(self, ValueError, "Invalid signature."):
            server.authenticate_complete(
                state,
                [AttestedCredentialData(_ATT_CRED_DATA)],
                _CRED_ID,
                client_data,
                AuthenticatorData(_AUTH_DATA),
                b"INVALID",
            )
Esempio n. 10
0
    def test_register_begin_custom_challenge(self):
        rp = RelyingParty("example.com", "Example")
        server = Fido2Server(rp)

        challenge = b"1234567890123456"
        request, state = server.register_begin({}, challenge=challenge)

        self.assertEqual(request["publicKey"]["challenge"], challenge)
Esempio n. 11
0
    def test_register_begin_rp_no_icon(self):
        rp = RelyingParty('example.com', 'Example')
        server = Fido2Server(rp)

        request, state = server.register_begin({})

        self.assertEqual(request['publicKey']['rp'],
                         {'id': 'example.com', 'name': 'Example'})
Esempio n. 12
0
    def test_register_begin_custom_challenge(self):
        rp = PublicKeyCredentialRpEntity("Example", "example.com")
        server = Fido2Server(rp)

        challenge = b"1234567890123456"
        request, state = server.register_begin(USER, challenge=challenge)

        self.assertEqual(request["publicKey"]["challenge"], challenge)
Esempio n. 13
0
def main():
    server = Fido2Server({
        "id": "example.com",
        "name": "Example RP"
    },
                         attestation="direct")
    client = get_client()
    # add_credentials(server, client)
    authenticate_device(server, client)
Esempio n. 14
0
    def test_register_begin_rp_no_icon(self):
        rp = RelyingParty("example.com", "Example")
        server = Fido2Server(rp)

        request, state = server.register_begin({})

        self.assertEqual(
            request["publicKey"]["rp"], {"id": "example.com", "name": "Example"}
        )
Esempio n. 15
0
    def __init__(self, params):
        """
        Create an instance of the class.
        :param params: Dictionary containing the following parameters
        db_path: Path to the user database
        rp_id: Relying Party identifier of the server.
        pre_share_eph_username: Indicates whether or not the server
                tries to establish an ephemeral user name for the next handshake
        db_encryption_key: The key the database is encrypted with.
        modes: List of allowed FIDO2 operation modes
            during authentication.
        force_fido2: Flag indicating whether or not to accept only FIDO2
            authenticated users.
        """
        # check arguments
        self._valid = False
        db_path = rp_id = encryption_key = None
        pre_share_eph_username = force_fido2 = False
        modes = FIDO2Mode.all
        if 'db_path' in params and isinstance(params['db_path'], str):
            db_path = params['db_path']
        if 'rp_id' in params and isinstance(params['rp_id'], str):
            rp_id = params['rp_id'].lower()
            if not is_valid_hostname(rp_id):
                rp_id = None
        if 'db_encryption_key' in params and \
                isinstance(params['db_encryption_key'], RSAKey):
            encryption_key = params['db_encryption_key']
        if 'pre_share_eph_user_name' in params and \
                isinstance(params['pre_share_eph_user_name'], bool):
            pre_share_eph_username = params['pre_share_eph_user_name']
        if 'modes' in params and \
                isinstance(params['modes'], list):
            modes = params['modes']
        if 'force_fido2' in params and isinstance(params['force_fido2'], bool):
            force_fido2 = params['force_fido2']

        # check if mandatory arguments are set
        if not db_path or not rp_id:
            return

        self.state = ServerState.init
        self.mode = None
        self.allowed_modes = modes

        self._db_connection = self._get_db_connection(db_path, encryption_key)
        relying_party = RelyingParty(rp_id)
        self._server = Fido2Server(relying_party)
        self.pre_share_eph_user_name = pre_share_eph_username
        self.force_fido2 = force_fido2

        self._auth_state = None
        self._user_id = None
        self._eph_user_name_server_share = None
        self._allow_credentials = []

        self._valid = bool(self._db_connection is not None)
Esempio n. 16
0
 def setUp(self):
     self.u2f = U2fInterface()
     self.login_as(user=self.user)
     rp = PublicKeyCredentialRpEntity("richardmasentry.ngrok.io", "Sentry")
     self.test_registration_server = Fido2Server(rp, verify_origin=verifiy_origin)
     self.test_authentication_server = U2FFido2Server(
         app_id="http://richardmasentry.ngrok.io/auth/2fa/u2fappid.json",
         rp={"id": "richardmasentry.ngrok.io", "name": "Sentry"},
         verify_u2f_origin=verifiy_origin,
     )
Esempio n. 17
0
    def test_register_begin_rp(self):
        rp = PublicKeyCredentialRpEntity("Example", "example.com")
        server = Fido2Server(rp)

        request, state = server.register_begin(USER)

        self.assertEqual(request["publicKey"]["rp"], {
            "id": "example.com",
            "name": "Example"
        })
Esempio n. 18
0
    def test_register_begin_rp_icon(self):
        rp = RelyingParty('example.com', 'Example',
                          'http://example.com/icon.svg')
        server = Fido2Server(rp)

        request, state = server.register_begin({})

        data = {'id': 'example.com', 'name': 'Example',
                'icon': 'http://example.com/icon.svg'}
        self.assertEqual(request['publicKey']['rp'], data)
Esempio n. 19
0
    def test_register_begin_rp_icon(self):
        rp = RelyingParty("example.com", "Example", "http://example.com/icon.svg")
        server = Fido2Server(rp)

        request, state = server.register_begin({})

        data = {
            "id": "example.com",
            "name": "Example",
            "icon": "http://example.com/icon.svg",
        }
        self.assertEqual(request["publicKey"]["rp"], data)
Esempio n. 20
0
def _get_fido2server(credentials, fido2rp):
    # See if any of the credentials is a legacy U2F credential with an app-id
    # (assume all app-ids are the same - authenticating with a mix of different
    # app-ids isn't supported in current Webauthn)
    app_id = None
    for k, v in credentials.items():
        if v['app_id']:
            app_id = v['app_id']
            break
    if app_id:
        return U2FFido2Server(app_id, fido2rp)
    return Fido2Server(fido2rp)
Esempio n. 21
0
def begin(request):
    rp_host = urlparse(request.build_absolute_uri()).hostname
    rp = RelyingParty(rp_host, 'Demo server')
    server = Fido2Server(rp)

    existing_credentials = AttestedCredentialData.objects.filter(
        user=request.user).all()
    auth_data, state = server.authenticate_begin(existing_credentials)
    request.session['state'] = {
        'challenge': state['challenge'],
        'user_verification': state['user_verification'].value,
    }
    return Response(auth_data, content_type="application/cbor")
Esempio n. 22
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
class TestFido2GeneralAuthenticationBackend(TestCase):
    """Test `Fido2GeneralAuthenticationBackend` class."""

    backend = Fido2GeneralAuthenticationBackend()

    server = Fido2Server(PublicKeyCredentialRpEntity(HOSTNAME, HOSTNAME))

    state = {
        'challenge': AUTHENTICATION_CHALLENGE,
        'user_verification': UserVerificationRequirement.PREFERRED
    }
    fido2_response = {
        'client_data':
        ClientData(base64.b64decode(AUTHENTICATION_CLIENT_DATA)),
        'credential_id':
        base64.b64decode(CREDENTIAL_ID),
        'authenticator_data':
        AuthenticatorData(base64.b64decode(AUTHENTICATOR_DATA)),
        'signature':
        base64.b64decode(SIGNATURE)
    }

    def setUp(self):
        self.user = User.objects.create_user(USERNAME, password=PASSWORD)
        self.device = Authenticator.objects.create(
            user=self.user,
            credential_id_data=CREDENTIAL_ID,
            attestation_data=ATTESTATION_OBJECT)

    def test_authenticate(self):
        authenticated_user = self.backend.authenticate(sentinel.request,
                                                       USERNAME, PASSWORD,
                                                       self.server, self.state,
                                                       self.fido2_response)
        self.assertEqual(authenticated_user, self.user)
        self.assertQuerysetEqual(Authenticator.objects.values_list(
            'user', 'counter'), [(self.user.pk, 152)],
                                 transform=tuple)

    def test_authenticate_wrong_password(self):
        authenticated_user = self.backend.authenticate(sentinel.request,
                                                       USERNAME,
                                                       'wrong_password',
                                                       self.server, self.state,
                                                       self.fido2_response)
        self.assertEqual(authenticated_user, None)
        self.assertQuerysetEqual(Authenticator.objects.values_list(
            'user', 'counter'), [(self.user.pk, 0)],
                                 transform=tuple)
Esempio n. 24
0
    def test_authenticate_complete_invalid_signature(self):
        rp = RelyingParty('example.com', 'Example')
        server = Fido2Server(rp)

        state = {'challenge': 'GAZPACHO!',
                 'user_verification': USER_VERIFICATION.PREFERRED}
        client_data_dict = {'challenge': 'GAZPACHO!',
                            'origin': 'https://example.com',
                            'type': WEBAUTHN_TYPE.GET_ASSERTION}
        client_data = ClientData(json.dumps(client_data_dict).encode('utf-8'))
        _AUTH_DATA = a2b_hex('A379A6F6EEAFB9A55E378C118034E2751E682FAB9F2D30AB13D2125586CE1947010000001D')  # noqa
        with six.assertRaisesRegex(self, ValueError, 'Invalid signature.'):
            server.authenticate_complete(
                state, [AttestedCredentialData(_ATT_CRED_DATA)], _CRED_ID,
                client_data, AuthenticatorData(_AUTH_DATA), b'INVALID')
Esempio n. 25
0
def test_authenticate():
    """test authentication"""

    device = SoftWebauthnDevice()
    device.cred_init('example.org', b'randomhandle')
    registered_credential = device.cred_as_attested()

    server = Fido2Server(
        PublicKeyCredentialRpEntity('example.org', 'test server'))
    options, state = server.authenticate_begin([registered_credential])
    assertion = device.get(options, 'https://example.org')
    server.authenticate_complete(
        state, [registered_credential], assertion['rawId'],
        ClientData(assertion['response']['clientDataJSON']),
        AuthenticatorData(assertion['response']['authenticatorData']),
        assertion['response']['signature'])
Esempio n. 26
0
    def test_action_webauthn_legacy_token(self, mock_complete_authn):
        # mock_complete_authn.return_value = ({'keyHandle': 'test_key_handle'},
        #        'dummy-touch', 'dummy-counter')
        #
        # Add a working U2F credential for this test
        u2f = U2F.from_dict(
            dict(
                version='U2F_V2',
                keyhandle=
                'V1vXqZcwBJD2RMIH2udd2F7R9NoSNlP7ZSPOtKHzS7n_rHFXcXbSpOoX__aUKyTR6jEC8Xv678WjXC5KEkvziA',
                public_key=
                'BHVTWuo3_D7ruRBe2Tw-m2atT2IOm_qQWSDreWShu3t21ne9c-DPSUdym-H-t7FcjV7rj1dSc3WSwaOJpFmkKxQ',
                app_id='https://dev.eduid.se/u2f-app-id.json',
                attest_cert='',
                description='unit test U2F token',
            ))
        self.user.credentials.add(u2f)
        self.app.central_userdb.save(self.user, check_sync=False)

        fido2_state = json.dumps(
            Fido2Server._make_internal_state(
                base64.b64decode(
                    '3h/EAZpY25xDdSJCOMx1ABZEA5Odz3yejUI3AUNTQWc='),
                'preferred'))
        self.app.config.fido2_rp_id = 'idp.dev.eduid.se'

        data1 = {
            'authenticatorData':
            'mZ9k6EPHoJxJZNA+UuvM0JVoutZHmqelg9kXe/DSefgBAAAA/w==',
            'clientDataJSON':
            ('eyJjaGFsbGVuZ2UiOiIzaF9FQVpwWTI1eERkU0pDT014MUFCWkVBNU9k'
             'ejN5ZWpVSTNBVU5UUVdjIiwib3JpZ2luIjoiaHR0cHM6Ly9pZHAuZGV2LmVkdWlkLnNlIiwidH'
             'lwZSI6IndlYmF1dGhuLmdldCJ9'),
            'credentialId':
            ('V1vXqZcwBJD2RMIH2udd2F7R9NoSNlP7ZSPOtKHzS7n/rHFXcXbSpOoX//aUKyTR6jEC8Xv678WjXC5KEkvziA=='
             ),
            'signature':
            ('MEYCIQC5gM8inamJGUFKu3bNo4fT0jmJQuw33OSSXc242NCuiwIhAIWnVw2Spow72j6J92KaY2rLR6qSXEbLam09ZXbSkBnQ'
             ),
        }

        response = self._action(data1=data1, fido2_state=fido2_state)

        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            len(self.app.actions_db.get_actions(self.user.eppn,
                                                'mock-session')), 1)
Esempio n. 27
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. 28
0
def authenticate(request):
    rp_host = urlparse(request.build_absolute_uri()).hostname
    rp = RelyingParty(rp_host, 'Demo server')
    server = Fido2Server(rp)

    data = request.data[0]
    credential_id = data['credentialId']
    credentials = AttestedCredentialData.objects.filter(
        user=request.user, ).all()
    client_data = ClientData(data['clientDataJSON'])
    auth_data = AuthenticatorData(data['authenticatorData'])
    signature = data['signature']

    state = request.session['state']

    cred = server.authenticate_complete(state, credentials, credential_id,
                                        client_data, auth_data, signature)
    return cred
Esempio n. 29
0
    def test_action_webauthn_legacy_token(self, mock_complete_authn):
        #mock_complete_authn.return_value = ({'keyHandle': 'test_key_handle'},
        #        'dummy-touch', 'dummy-counter')
        #
        # Add a working U2F credential for this test
        u2f = U2F(version='U2F_V2',
                  keyhandle='V1vXqZcwBJD2RMIH2udd2F7R9NoSNlP7ZSPOtKHzS7n_rHFXcXbSpOoX__aUKyTR6jEC8Xv678WjXC5KEkvziA',
                  public_key='BHVTWuo3_D7ruRBe2Tw-m2atT2IOm_qQWSDreWShu3t21ne9c-DPSUdym-H-t7FcjV7rj1dSc3WSwaOJpFmkKxQ',
                  app_id='https://dev.eduid.se/u2f-app-id.json',
                  attest_cert='',
                  description='unit test U2F token'
                  )
        self.user.credentials.add(u2f)
        self.app.central_userdb.save(self.user, check_sync=False)

        with self.session_cookie(self.browser) as client:
            self.prepare(client, Plugin, 'mfa', action_dict=MFA_ACTION)
            with self.app.test_request_context():
                with client.session_transaction() as sess:
                    fido2_state = Fido2Server._make_internal_state(
                        base64.b64decode('3h/EAZpY25xDdSJCOMx1ABZEA5Odz3yejUI3AUNTQWc='), 'preferred')
                    sess['eduid_action.mfa.webauthn.state'] = json.dumps(fido2_state)
                    csrf_token = sess.get_csrf_token()

                data = json.dumps({'csrf_token': csrf_token,
                                   'authenticatorData': 'mZ9k6EPHoJxJZNA+UuvM0JVoutZHmqelg9kXe/DSefgBAAAA/w==',
                                   'clientDataJSON': 'eyJjaGFsbGVuZ2UiOiIzaF9FQVpwWTI1eERkU0pDT014MUFCWkVBNU9k'+\
                                   'ejN5ZWpVSTNBVU5UUVdjIiwib3JpZ2luIjoiaHR0cHM6Ly9pZHAuZGV2LmVkdWlkLnNlIiwidH'+\
                                   'lwZSI6IndlYmF1dGhuLmdldCJ9',
                                   'credentialId': 'V1vXqZcwBJD2RMIH2udd2F7R9NoSNlP7ZSPOtKHzS7n/rHFXcXbSpOoX//'+\
                                                   'aUKyTR6jEC8Xv678WjXC5KEkvziA==',
                                   'signature': 'MEYCIQC5gM8inamJGUFKu3bNo4fT0jmJQuw33OSSXc242NCuiwIhAIWnVw2Sp'+\
                                                'ow72j6J92KaY2rLR6qSXEbLam09ZXbSkBnQ'}
                                  )

                self.app.config['FIDO2_RP_ID'] = 'idp.dev.eduid.se'
                response = client.post('/post-action', data=data, content_type=self.content_type_json)
                self.assertEquals(response.status_code, 200)
                data = json.loads(response.data)
                self.assertEquals(len(self.app.actions_db.get_actions(self.user.eppn, 'mock-session')), 1)
                mock_idp_app = MockIdPApp(self.app.actions_db)
                mock_idp_app.logger = self.app.logger
                add_actions(mock_idp_app, self.user, MockTicket('mock-session'))
                self.assertEquals(len(self.app.actions_db.get_actions(self.user.eppn, 'mock-session')), 0)
Esempio n. 30
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. 31
0
    def test_action_webauthn_legacy_token(self, mock_complete_authn):
        #mock_complete_authn.return_value = ({'keyHandle': 'test_key_handle'},
        #        'dummy-touch', 'dummy-counter')
        #
        # Add a working U2F credential for this test
        u2f = U2F(version='U2F_V2',
                  keyhandle='V1vXqZcwBJD2RMIH2udd2F7R9NoSNlP7ZSPOtKHzS7n_rHFXcXbSpOoX__aUKyTR6jEC8Xv678WjXC5KEkvziA',
                  public_key='BHVTWuo3_D7ruRBe2Tw-m2atT2IOm_qQWSDreWShu3t21ne9c-DPSUdym-H-t7FcjV7rj1dSc3WSwaOJpFmkKxQ',
                  app_id='https://dev.eduid.se/u2f-app-id.json',
                  attest_cert='',
                  description='unit test U2F token'
                  )
        self.user.credentials.add(u2f)
        self.app.central_userdb.save(self.user, check_sync=False)

        with self.session_cookie(self.browser) as client:
            self.prepare(client, Plugin, 'mfa', action_dict=MFA_ACTION)
            with self.app.test_request_context():
                with client.session_transaction() as sess:
                    fido2_state = Fido2Server._make_internal_state(
                        base64.b64decode('3h/EAZpY25xDdSJCOMx1ABZEA5Odz3yejUI3AUNTQWc='), 'preferred')
                    sess['eduid_webapp.actions.actions.mfa.webauthn.state'] = json.dumps(fido2_state)
                    csrf_token = sess.get_csrf_token()

                data = json.dumps({'csrf_token': csrf_token,
                                   'authenticatorData': 'mZ9k6EPHoJxJZNA+UuvM0JVoutZHmqelg9kXe/DSefgBAAAA/w==',
                                   'clientDataJSON': 'eyJjaGFsbGVuZ2UiOiIzaF9FQVpwWTI1eERkU0pDT014MUFCWkVBNU9k'+\
                                   'ejN5ZWpVSTNBVU5UUVdjIiwib3JpZ2luIjoiaHR0cHM6Ly9pZHAuZGV2LmVkdWlkLnNlIiwidH'+\
                                   'lwZSI6IndlYmF1dGhuLmdldCJ9',
                                   'credentialId': 'V1vXqZcwBJD2RMIH2udd2F7R9NoSNlP7ZSPOtKHzS7n/rHFXcXbSpOoX//'+\
                                                   'aUKyTR6jEC8Xv678WjXC5KEkvziA==',
                                   'signature': 'MEYCIQC5gM8inamJGUFKu3bNo4fT0jmJQuw33OSSXc242NCuiwIhAIWnVw2Sp'+\
                                                'ow72j6J92KaY2rLR6qSXEbLam09ZXbSkBnQ'}
                                  )

                self.app.config['FIDO2_RP_ID'] = 'idp.dev.eduid.se'
                response = client.post('/post-action', data=data, content_type=self.content_type_json)
                self.assertEquals(response.status_code, 200)
                data = json.loads(response.data)
                self.assertEquals(len(self.app.actions_db.get_actions(self.user.eppn, 'mock-session')), 1)