예제 #1
0
def test_login_webauthn(live_server, selenium, test_user):  # pylint: disable=unused-argument
    """test login by webauthn"""

    device = SoftWebauthnDevice()
    device.cred_init(webauthn.rp.id, b'randomhandle')
    persist_and_detach(
        WebauthnCredential(user=test_user,
                           user_handle=device.user_handle,
                           credential_data=cbor.encode(
                               device.cred_as_attested().__dict__)))

    selenium.get(url_for('auth.login_route', _external=True))
    selenium.find_element_by_xpath(
        '//form//input[@name="username"]').send_keys(test_user.username)
    selenium.find_element_by_xpath('//form//input[@type="submit"]').click()

    # some javascript code must be emulated
    webdriver_waituntil(selenium, js_variable_ready('window.pkcro_raw'))
    pkcro = cbor.decode(
        b64decode(
            selenium.execute_script('return window.pkcro_raw;').encode(
                'utf-8')))
    assertion = device.get(pkcro, 'https://%s' % webauthn.rp.id)
    selenium.execute_script(
        'authenticate_assertion(CBOR.decode(Sner.base64_to_array_buffer("%s")));'
        % b64encode(cbor.encode(assertion)).decode('utf-8'))
    # and back to standard test codeflow

    webdriver_waituntil(
        selenium,
        EC.presence_of_element_located((By.XPATH, '//a[text()="Logout"]')))
예제 #2
0
def test_as_attested_cred():
    """test straight credential generation and access"""

    device = SoftWebauthnDevice()
    device.cred_init('rpid', b'randomhandle')

    assert isinstance(device.cred_as_attested(), AttestedCredentialData)
예제 #3
0
    def initialized_device(self, create, extracted, **kwargs):  # pylint: disable=unused-argument
        """DI or self initialize device"""

        if extracted:
            device = extracted
        else:
            device = SoftWebauthnDevice()
            device.cred_init(webauthn.rp.id, b'randomhandle')

        self.user_handle = device.user_handle
        self.credential_data = cbor.encode(device.cred_as_attested().__dict__)
예제 #4
0
def create_test_wncred(a_test_user):
    """test webauthn credential"""

    device = SoftWebauthnDevice()
    device.cred_init(webauthn.rp.id, b'randomhandle')
    return WebauthnCredential(user_id=a_test_user.id,
                              user=a_test_user,
                              user_handle=device.user_handle,
                              credential_data=cbor.encode(
                                  device.cred_as_attested().__dict__),
                              name='testcredential')
예제 #5
0
def test_wncred(test_user):  # pylint: disable=redefined-outer-name
    """persistent test registered webauthn credential"""

    device = SoftWebauthnDevice()
    device.cred_init(webauthn.rp.ident, b'randomhandle')
    wncred = WebauthnCredential(user_id=test_user.id,
                                user=test_user,
                                user_handle=device.user_handle,
                                credential_data=cbor.encode(
                                    device.cred_as_attested().__dict__),
                                name='testcredential')
    yield persist_and_detach(wncred)
예제 #6
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'])
예제 #7
0
def test_example_server_authentication(client):  # pylint: disable=redefined-outer-name
    """Authentication example"""

    # Already registered credential is typicaly part of fixture test-case code.
    #
    # NOTE: the storage of the credential data on the RP side is not in scope
    # of Webauthn spec. Yubico example server uses module scoped variable.
    device = SoftWebauthnDevice()
    device.cred_init('localhost', b'randomhandle')
    tests.example_server.credentials = [device.cred_as_attested()]

    # Browser starts authentication by requesting
    # publicKeyCredentialRequestOptions (pkcro) from the RP.
    pkcro = cbor.decode(client.post('/api/authenticate/begin').data)
    print('publicKeyCredentialRequestOptions: ', pkcro)

    # publicKeyCredentialRequestOptions object is passed to the authenticator,
    # which performs requester user verification and return credential object
    # (assertion).
    assertion = device.get(pkcro, 'https://localhost')
    print('credential assertion: ', assertion)

    # Browser conveys assertion data to the RP for authentication.
    assertion_data = cbor.encode({
        'credentialId': assertion['rawId'],
        'clientDataJSON': assertion['response']['clientDataJSON'],
        'authenticatorData': assertion['response']['authenticatorData'],
        'signature': assertion['response']['signature'],
        'userHandle': assertion['response']['userHandle']
    })
    raw_response = client.post(
        '/api/authenticate/complete',
        input_stream=BytesIO(assertion_data),
        content_type='application/cbor'
    )
    authentication_response = cbor.decode(raw_response.data)
    print('authentication response:', authentication_response)

    # RP will verify assertion and on success proceeds with user logon.
    assert authentication_response == {'status': 'OK'}
예제 #8
0
def test_webauthn_login_route(client, test_user):
    """test login by webauthn"""

    device = SoftWebauthnDevice()
    device.cred_init(webauthn.rp.ident, b'randomhandle')
    persist_and_detach(
        WebauthnCredential(user=test_user,
                           user_handle=device.user_handle,
                           credential_data=cbor.encode(
                               device.cred_as_attested().__dict__)))

    form = client.get(url_for('app.login_route')).form
    form['username'] = test_user.username
    response = form.submit()
    assert response.status_code == HTTPStatus.FOUND

    response = response.follow()
    # some javascript code muset be emulated
    pkcro = cbor.decode(
        b64decode(
            client.post(url_for('app.webauthn_pkcro_route'), {
                'csrf_token': get_csrf_token(client)
            }).body))
    assertion = device.get(pkcro, 'https://%s' % webauthn.rp.ident)
    assertion_data = {
        'credentialRawId': assertion['rawId'],
        'authenticatorData': assertion['response']['authenticatorData'],
        'clientDataJSON': assertion['response']['clientDataJSON'],
        'signature': assertion['response']['signature'],
        'userHandle': assertion['response']['userHandle']
    }
    form = response.form
    form['assertion'] = b64encode(cbor.encode(assertion_data))
    response = form.submit()
    # and back to standard test codeflow
    assert response.status_code == HTTPStatus.FOUND

    response = client.get(url_for('app.index_route'))
    assert response.lxml.xpath('//a[text()="Logout"]')