Example #1
0
    def setUp(self):
        self.setUp_user_realms()
        set_policy(name="WebAuthn", scope=SCOPE.ENROLL,
                   action='{0!s}={1!s},{2!s}={3!s}'.format(WEBAUTHNACTION.RELYING_PARTY_NAME,
                                                           self.rp_name,
                                                           WEBAUTHNACTION.RELYING_PARTY_ID,
                                                           self.rp_id))
        set_privacyidea_config(WEBAUTHNCONFIG.APP_ID, self.app_id)
        self.user = User(login='******', realm=self.realm1,
                         resolver=self.resolvername1)
        # TODO: extract token enrollment into a local function
        # init token step 1
        self.token1 = init_token({'type': 'webauthn',
                                  'serial': self.serial1},
                                 user=self.user)
        # TODO: use mocking to set nonce
        with patch('privacyidea.lib.tokens.webauthntoken.WebAuthnTokenClass._get_nonce') as mock_nonce:
            mock_nonce.return_value = webauthn_b64_decode(self.nonce1)
            res = self.token1.get_init_detail(self.init_params, self.user)
        self.assertEqual(self.serial1, res['serial'], res)
        self.assertEqual(self.nonce1, res['webAuthnRegisterRequest']['nonce'], res)

        # init token step 2
        self.token1.update({
            'type': 'webauthn',
            'serial': self.serial1,
            'regdata': self.reg_data1,
            'clientdata': self.client_data1,
            WEBAUTHNACTION.RELYING_PARTY_ID: self.rp_id,
            WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_LEVEL: ATTESTATION_LEVEL.NONE,
            'HTTP_ORIGIN': self.app_id
        })
        res = self.token1.get_init_detail()
        self.assertEqual('Yubico U2F EE Serial 61730834',
                         res['webAuthnRegisterResponse']['subject'], res)
        # enroll the second webauthn token
        # init token step 1
        self.token2 = init_token({'type': 'webauthn',
                                  'serial': self.serial2},
                                 user=self.user)
        with patch('privacyidea.lib.tokens.webauthntoken.WebAuthnTokenClass._get_nonce') as mock_nonce:
            mock_nonce.return_value = webauthn_b64_decode(self.nonce2)
            res = self.token2.get_init_detail(self.init_params, self.user)
        self.assertEqual(self.serial2, res['serial'], res)
        self.assertEqual(self.nonce2, res['webAuthnRegisterRequest']['nonce'], res)

        # init token step 2
        self.token2.update({
            'type': 'webauthn',
            'serial': self.serial2,
            'regdata': self.reg_data2,
            'clientdata': self.client_data2,
            WEBAUTHNACTION.RELYING_PARTY_ID: self.rp_id,
            WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_LEVEL: ATTESTATION_LEVEL.NONE,
            'HTTP_ORIGIN': self.app_id
        })
        res = self.token2.get_init_detail()
        self.assertEqual('Yubico U2F EE Serial 23925734103241087',
                         res['webAuthnRegisterResponse']['subject'], res)
Example #2
0
    def test_03_token_update(self):
        with patch('privacyidea.lib.tokens.webauthntoken.WebAuthnTokenClass._get_nonce') as mock_nonce:
            mock_nonce.return_value = webauthn_b64_decode(REGISTRATION_CHALLENGE)
            self.token.get_init_detail(self.init_params, self.user)
        self.token.update({
            'type': 'webauthn',
            'serial': self.token.token.serial,
            'regdata': REGISTRATION_RESPONSE_TMPL['attObj'],
            'clientdata': REGISTRATION_RESPONSE_TMPL['clientData'],
            WEBAUTHNACTION.RELYING_PARTY_ID: RP_ID,
            WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_LEVEL: ATTESTATION_LEVEL.NONE,
            'HTTP_ORIGIN': ORIGIN
        })
        web_authn_registration_response = self.token.get_init_detail().get("webAuthnRegisterResponse")

        self.assertTrue(web_authn_registration_response
                        .get("subject")
                        .startswith("Yubico U2F EE Serial"))
        self.assertTrue(self
                        .token
                        .get_tokeninfo(WEBAUTHNINFO.ATTESTATION_ISSUER)
                        .startswith("CN=Yubico U2F Root CA Serial"))
        self.assertTrue(self
                        .token
                        .get_tokeninfo(WEBAUTHNINFO.ATTESTATION_SUBJECT)
                        .startswith("CN=Yubico U2F EE Serial"))
        self.assertEqual(CRED_ID, self.token.decrypt_otpkey())
        self.assertEqual(PUB_KEY, self.token.get_tokeninfo(WEBAUTHNINFO.PUB_KEY))
Example #3
0
    def test_07_none_attestation(self):
        self.init_params['nonce'] = webauthn_b64_decode(
            NONE_ATTESTATION_REGISTRATION_CHALLENGE)
        self.init_params[
            WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_FORM] = 'none'
        self.user = User(login=NONE_ATTESTATION_USER_NAME)
        self.token.get_init_detail(self.init_params, self.user)
        self.token.update({
            'type':
            'webauthn',
            'serial':
            self.token.token.serial,
            'regdata':
            NONE_ATTESTATION_REGISTRATION_RESPONSE_TMPL['attObj'],
            'clientdata':
            NONE_ATTESTATION_REGISTRATION_RESPONSE_TMPL['clientData'],
            WEBAUTHNACTION.RELYING_PARTY_ID:
            RP_ID,
            WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_LEVEL:
            ATTESTATION_LEVEL.NONE,
            'HTTP_ORIGIN':
            ORIGIN
        })
        web_authn_registration_response = self.token.get_init_detail().get(
            'webAuthnRegisterResponse')

        self.assertEqual(NONE_ATTESTATION_CRED_ID, self.token.decrypt_otpkey())
        self.assertEqual(NONE_ATTESTATION_PUB_KEY,
                         self.token.get_tokeninfo(WEBAUTHNINFO.PUB_KEY))
Example #4
0
 def _create_challenge(self):
     self.token.set_otpkey(hexlify_and_unicode(
         webauthn_b64_decode(CRED_ID)))
     self.token.add_tokeninfo(WEBAUTHNINFO.PUB_KEY, PUB_KEY)
     self.token.add_tokeninfo(WEBAUTHNINFO.RELYING_PARTY_ID, RP_ID)
     (_, _, _, response_details) = self.token.create_challenge(
         options=self.challenge_options)
     return response_details
Example #5
0
 def test_06_missing_origin(self):
     self.challenge_options['nonce'] = webauthn_b64_decode(ASSERTION_CHALLENGE)
     self._create_challenge()
     sign_count = self.token.check_otp(otpval=None,
                                       options={
                                           "credentialid": CRED_ID,
                                           "authenticatordata": ASSERTION_RESPONSE_TMPL['authData'],
                                           "clientdata": ASSERTION_RESPONSE_TMPL['clientData'],
                                           "signaturedata": ASSERTION_RESPONSE_TMPL['signature'],
                                           "user": self.user,
                                           "challenge": hexlify_and_unicode(self.challenge_options['nonce']),
                                           "HTTP_ORIGIN": '',
                                       })
     self.assertTrue(sign_count == -1)
Example #6
0
    def test_08_missing_attestation(self):
        self.init_params['nonce'] = webauthn_b64_decode(NONE_ATTESTATION_REGISTRATION_CHALLENGE)
        self.user = User(login=NONE_ATTESTATION_USER_NAME)
        self.token.get_init_detail(self.init_params, self.user)

        with self.assertRaises(RegistrationRejectedException):
            self.token.update({
                'type': 'webauthn',
                'serial': self.token.token.serial,
                'regdata': NONE_ATTESTATION_REGISTRATION_RESPONSE_TMPL['attObj'],
                'clientdata': NONE_ATTESTATION_REGISTRATION_RESPONSE_TMPL['clientData'],
                WEBAUTHNACTION.RELYING_PARTY_ID: RP_ID,
                WEBAUTHNACTION.AUTHENTICATOR_ATTESTATION_LEVEL: ATTESTATION_LEVEL.UNTRUSTED,
                'HTTP_ORIGIN': ORIGIN
            })
    def test_05_no_user_presence_fail_assertion(self):
        webauthn_assertion_response = self.getAssertionResponse()
        auth_data = webauthn_b64_decode(
            webauthn_assertion_response.assertion_response['authData'])
        flags = struct.unpack('!B', auth_data[32:33])[0]
        flags = flags & ~AuthenticatorDataFlags.USER_PRESENT
        auth_data = auth_data[:32] + struct.pack('!B', flags) + auth_data[33:]
        webauthn_assertion_response.assertion_response[
            'authData'] = webauthn_b64_encode(auth_data)

        # FIXME This *should* fail because UP=0, but will fail anyway later on because the signature is invalid.
        # TODO Build a mock Authenticator implementation, to be able to sign arbitrary authenticator data statements.
        # TODO Sign an authenticator data statement with UP=0 and test against that so that the signature is valid.
        with self.assertRaises(AuthenticationRejectedException):
            webauthn_assertion_response.verify()
Example #8
0
 def test_07_webauthn_b64_decode(self):
     self.assertEqual(webauthn_b64_decode(URL_DECODE_TEST_STRING), URL_DECODE_EXPECTED_RESULT)