def post(self, request, *args, **kwargs): if 'response' not in request.POST or any( x not in request.POST["response"] for x in ['clientData', 'registrationData', 'version']): messages.error(request, "Invalid U2F response, please try again.") return redirect('multifactor:home') device, cert = u2f.complete_registration( request.session['multifactor_u2f_enroll_'], json.loads(request.POST["response"]), [mf_settings['U2F_APPID']]) cert = x509.load_der_x509_certificate(cert, default_backend()) cert_hash = hashlib.sha384(cert.public_bytes(Encoding.PEM)).hexdigest() if UserKey.objects.filter(**self.base, properties__cert=cert_hash).exists(): messages.info(request, "That key's already in your account.") return redirect('multifactor:home') key = UserKey.objects.create( user=request.user, key_type=KEY_TYPE_U2F, properties={ "device": json.loads(device.json), "cert": cert_hash, "domain": request.get_host(), }, ) write_session(request, key) messages.success(request, "U2F key added to account.") return redirect('multifactor:home')
def bind(**kwargs): """ Complete registration of the new key Variables: None Arguments: data => Response to the enroll challenge Data Block: None Result example: { "success": True } """ uname = kwargs['user']['uname'] data = request.json if "errorCode" in data: return make_api_response({'success': False}, err=U2F_CLIENT_ERROR_MAP[data['errorCode']], status_code=400) user = STORAGE.get_user(uname) current_enroll = session.pop('_u2f_enroll_') try: device, cert = complete_registration(current_enroll, data, [APP_ID]) except Exception as e: return make_api_response({'success': False}, err=e.message, status_code=400) user.setdefault('u2f_devices', []).append(device.json) STORAGE.save_user(uname, user) return make_api_response({"success": True})
def register_token(devices=[]): token = SoftU2FDevice() request = begin_registration(APP_ID, devices) data = request.data_for_client response = token.register(FACET, data['appId'], data['registerRequests'][0]) device, cert = complete_registration(request.json, response) return device, token
def _register_response(user_id, response_data): client = get_client() user = get_user(user_id) register_response = response_data.registerResponse challenge = register_response.clientData.challenge request_data = store.retrieve(client.id, user_id, challenge) if request_data is None: raise exc.NotFoundException('Transaction not found') request_data = json.loads(request_data) registration, cert = complete_registration( request_data, register_response, client.valid_facets) attestation = get_attestation(cert) if not app.config['ALLOW_UNTRUSTED'] and not attestation.trusted: raise exc.BadInputException('Device attestation not trusted') if user is None: app.logger.info('Creating user: %s/%s', client.name, user_id) user = User(user_id) client.users.append(user) transports = sum(t.value for t in attestation.transports or []) dev = user.add_device(registration.json, cert, transports) # Properties from the initial request have a lower precedence. dev.update_properties(request_data['properties']) dev.update_properties(response_data.properties) db.session.commit() app.logger.info('Registered device: %s/%s/%s', client.name, user_id, dev.handle) return dev.get_descriptor(get_metadata(dev))
def bind(request): import hashlib enroll = request.session['_u2f_enroll_'] data = simplejson.loads(request.POST["response"]) device, cert = complete_registration(enroll, data, [settings.U2F_APPID]) cert = x509.load_der_x509_certificate(cert, default_backend()) cert_hash = hashlib.md5(cert.public_bytes(Encoding.PEM)).hexdigest() q = User_Keys.objects.filter(key_type="U2F", properties__icontains=cert_hash) if q.exists(): return HttpResponse( "This key is registered before, it can't be registered again.") User_Keys.objects.filter(username=request.user.username, key_type="U2F").delete() uk = User_Keys() uk.username = request.user.username uk.owned_by_enterprise = getattr(settings, "MFA_OWNED_BY_ENTERPRISE", False) uk.properties = { "device": simplejson.loads(device.json), "cert": cert_hash } uk.key_type = "U2F" uk.save() return HttpResponse("OK")
def bind(user, version, registration_data, client_data, description=''): security_user = SecurityUser.from_user(user, current_app.private_userdb) enrollment_data = session.pop('_u2f_enroll_', None) if not enrollment_data: current_app.logger.error('Found no U2F enrollment data in session.') return {'_error': True, 'message': 'security.u2f.missing_enrollment_data'} data = { 'version': version, 'registrationData': registration_data, 'clientData': client_data } device, der_cert = complete_registration(enrollment_data, data, current_app.config['U2F_FACETS']) cert = x509.load_der_x509_certificate(der_cert, default_backend()) pem_cert = crypto.dump_certificate(crypto.FILETYPE_PEM, cert) if not isinstance(pem_cert, six.string_types): pem_cert = pem_cert.decode('utf-8') u2f_token = U2F(version=device['version'], keyhandle=device['keyHandle'], app_id=device['appId'], public_key=device['publicKey'], attest_cert=pem_cert, description=description, application='eduid_security', created_ts=True) security_user.credentials.add(u2f_token) save_and_sync_user(security_user) current_app.stats.count(name='u2f_token_bind') return { 'message': 'security.u2f_register_success', 'credentials': compile_credential_list(security_user) }
def form_valid(self, form): """Complete the registration process.""" u2f_request = self.request.session.pop( REGISTRATION_REQUEST_SESSION_KEY, None) if u2f_request is None: form.add_error(None, _('Registration request not found.')) return self.form_invalid(form) u2f_response = form.cleaned_data['u2f_response'] try: device, attestation_cert = u2f.complete_registration( u2f_request, u2f_response) except (TypeError, ValueError, KeyError) as error: _LOGGER.info("U2F registration failed with error: %r", error) form.add_error(None, _('Registration failed.')) return self.form_invalid(form) U2fDevice.objects.create(user=self.request.user, version=device['version'], key_handle=device['keyHandle'], public_key=device['publicKey'], app_id=device['appId'], transports=device['transports'], raw_attestation=attestation_cert) return super(U2fRegistrationView, self).form_valid(form)
def perform_binding(self, cleaned_data): enroll = cleaned_data['u2f_enroll_signed'] bind_data = cleaned_data['u2f_bind'] try: cleaned_data['device'], cleaned_data[ 'cert'] = complete_registration(enroll, bind_data, [FACET]) except ValueError as e: raise forms.ValidationError("Key enrollment failed. {}.".format( str(e)))
def try_enroll(self, enrollment_data, response_data, device_name=None): binding, cert = u2f.complete_registration(enrollment_data, response_data, self.u2f_facets) devices = self.config.setdefault("devices", []) devices.append({ "name": device_name or "Security Key", "ts": int(time.time()), "binding": dict(binding), })
def try_enroll(self, enrollment_data, response_data, device_name=None): binding, cert = u2f.complete_registration(enrollment_data, response_data, self.u2f_facets) devices = self.config.setdefault('devices', []) devices.append( { 'name': device_name or 'Security Key', 'ts': int(time.time()), 'binding': dict(binding), } )
def try_enroll(self, enrollment_data, response_data, device_name=None): binding, cert = u2f.complete_registration(enrollment_data, response_data, self.u2f_facets) devices = self.config.setdefault('devices', []) devices.append({ 'name': device_name or 'Security Key', 'ts': int(time.time()), 'binding': dict(binding), })
def _register_device(self): icp = self.env['ir.config_parameter'].sudo() baseurl = icp.get_param('web.base.url') for device in self: registration_data, cert = u2f.complete_registration( request.session.u2f_last_registration_challenge, device.json, [baseurl]) device.json = registration_data.json del request.session['u2f_last_registration_challenge'] return True
def clean_token(self): response = self.cleaned_data['token'] try: request = self.request.session['u2f_registration_request'] u2f_device, attestation_cert = u2f.complete_registration(request, response) self.u2f_device = u2f_device if U2FDevice.objects.filter(public_key=self.u2f_device['publicKey']).count() > 0: raise forms.ValidationError("U2F device has already been linked to another user") except ValueError as e: raise forms.ValidationError("U2F device could not be verified: " + str(e)) return response
def form_valid(self, form): token_response = form.cleaned_data["token_response"] u2f_challenge = self.request.session["u2f_challenge"] device, _ = complete_registration( u2f_challenge, token_response, [zentral_settings["api"]["tls_hostname"]]) UserU2F.objects.create(user=self.request.user, name=form.cleaned_data["name"], device=device) messages.info(self.request, "U2F device registered") return super().form_valid(form)
def bind(self, username, data): user = self.users[username] enroll = user.pop('_u2f_enroll_') device, cert = complete_registration(enroll, data, [self.facet]) user.setdefault('_u2f_devices_', []).append(device.json) log.info("U2F device enrolled. Username: %s", username) cert = x509.load_der_x509_certificate(cert, default_backend()) log.debug("Attestation certificate:\n%s", cert.public_bytes(Encoding.PEM)) return json.dumps(True)
def form_valid(self, form): response = form.cleaned_data['response'] request = self.request.session['u2f_registration_request'] del self.request.session['u2f_registration_request'] device, attestation_cert = u2f.complete_registration(request, response) self.request.user.u2f_keys.create( public_key=device['publicKey'], key_handle=device['keyHandle'], app_id=device['appId'], ) messages.success(self.request, _("Key added.")) return super(AddKeyView, self).form_valid(form)
def bind(): app_id = get_origin(request.environ) username = request.args.get('username', 'user') data = request.data.decode() user = users[username] enroll = user.pop('_u2f_enroll_') device, cert = complete_registration(enroll, data, [app_id]) user.setdefault('_u2f_devices_', []).append(device.json) print("U2F device enrolled. Username: %s", username) cert = x509.load_der_x509_certificate(cert, default_backend()) log.debug("Attestation certificate:\n%s", cert.public_bytes(Encoding.PEM)) return json.dumps(True)
def u2f_register(): # TODO(tsileo): ensure no duplicates if request.method == "GET": payload = u2f.begin_registration(ID) session["challenge"] = payload return htmlify(render_template("u2f.html", payload=payload)) else: resp = json.loads(request.form.get("resp")) device, device_cert = u2f.complete_registration( session["challenge"], resp) session["challenge"] = None DB.u2f.insert_one({"device": device, "cert": device_cert}) session["logged_in"] = False return redirect("/login")
def create(cls, u2f_device, enroll_challenge, data, name=None): data['version'] = 'U2F_V2' device, cert = complete_registration(json.loads(enroll_challenge), data, [settings.OTP_U2F_APP_ID]) if not name: cert = x509.load_der_x509_certificate(cert, default_backend()) name = cert.subject.get_attributes_for_oid( NameOID.COMMON_NAME)[0].value return cls.objects.create(name=name, device=u2f_device, version=device['version'], public_key=device['publicKey'], transports=json.dumps(device['transports']), key_handle=device['keyHandle'])
def u2f_register(): # TODO(tsileo): ensure no duplicates if request.method == 'GET': payload = u2f.begin_registration(ID) session['challenge'] = payload return render_template( 'u2f.html', payload=payload, ) else: resp = json.loads(request.form.get('resp')) device, device_cert = u2f.complete_registration( session['challenge'], resp) session['challenge'] = None DB.u2f.insert_one({'device': device, 'cert': device_cert}) return ''
def post(self, request, format=None): user = request.user response = request.data.get('response') reg_req = get_object_or_404(U2FRegistrationRequest, user=user) reg_request = json.loads(reg_req.body) device, attestation_cert = u2f.complete_registration( reg_request, response) U2FKey.objects.create( user=user, publicKey=device['publicKey'], keyHandle=device['keyHandle'], appId=device['appId'], ) reg_req.delete() return Response({"resp": "success"})
def try_enroll( self, enrollment_data, response_data, has_webauthn_register, device_name=None, state=None ): if has_webauthn_register: data = json.loads(response_data) client_data = ClientData(websafe_decode(data["response"]["clientDataJSON"])) att_obj = base.AttestationObject(websafe_decode(data["response"]["attestationObject"])) binding = self.webauthn_registration_server.register_complete( state, client_data, att_obj ) else: data, cert = u2f.complete_registration(enrollment_data, response_data, self.u2f_facets) binding = dict(data) devices = self.config.setdefault("devices", []) devices.append( {"name": device_name or "Security Key", "ts": int(time()), "binding": binding} )
def bind(request): enroll = request.session['_u2f_enroll_'] data = json.loads(request.POST["response"]) device, cert = complete_registration(enroll, data, [settings.U2F_APPID]) cert = x509.load_der_x509_certificate(cert, default_backend()) cert_hash = hashlib.md5(cert.public_bytes(Encoding.PEM)).hexdigest() if UserKey.objects.filter(key_type="U2F", properties__icontains=cert_hash).exists(): return HttpResponse("This key is registered before, it can't be registered again.") UserKey.objects.filter(username=request.user.get_username(), key_type="U2F").delete() UserKey.objects.create( username=request.user.get_username(), properties={ "device": json.loads(device.json), "cert": cert_hash, }, key_type="U2F", ) return HttpResponse("OK")
def completeU2FRegistration(self, user_name, object_dn, data): # Do we have write permissions for the requested attribute self.__check_acl(user_name, object_dn, "w") uuid = self.__dn_to_uuid(object_dn) user_settings = self.__settings[uuid] data = loads(data) binding, cert = complete_registration(user_settings.pop('_u2f_enroll_'), data, [self.facet]) devices = [DeviceRegistration.wrap(device) for device in user_settings.get('_u2f_devices_', [])] devices.append(binding) user_settings['_u2f_devices_'] = [d.json for d in devices] self.__save_settings() self.__log.info("U2F device enrolled. Username: %s", user_name) self.__log.debug("Attestation certificate:\n%s", cert.public_bytes(Encoding.PEM)) return True
def completeU2FRegistration(self, user_name, object_dn, data): # Do we have write permissions for the requested attribute self.__check_acl(user_name, object_dn, "w") uuid = self.__dn_to_uuid(object_dn) user_settings = self.__settings[uuid] data = loads(data) binding, cert = complete_registration( user_settings.pop('_u2f_enroll_'), data, [self.facet]) devices = [ DeviceRegistration.wrap(device) for device in user_settings.get('_u2f_devices_', []) ] devices.append(binding) user_settings['_u2f_devices_'] = [d.json for d in devices] self.__save_settings() self.__log.info("U2F device enrolled. Username: %s", user_name) self.__log.debug("Attestation certificate:\n%s", cert.public_bytes(Encoding.PEM)) return True
def add_2fa(): form = forms.AddTokenForm() if form.validate_on_submit(): # Complete 2FA registration registered_device = complete_registration(session['u2f_enroll'], form.response.data)[0].json user = models.User.query.filter_by(id=session['user']).first() u2f_cred = models.U2FCredentials(name=form.name.data, owner=user.id, device=registered_device) db.session.add(u2f_cred) db.session.commit() flash("Authentication token added", "success") return redirect(url_for('login')) # Start 2FA registration enroll = begin_registration(app_id, []) session['u2f_enroll'] = enroll.json challenge = enroll.data_for_client['registerRequests'][0]['challenge'] return render_template('add_2fa.html', challenge=challenge, appId=app_id, version="U2F_V2", form=form)
def bind(user, version, registration_data, client_data, description=''): security_user = SecurityUser.from_user(user, current_app.private_userdb) enrollment_data = session.pop('_u2f_enroll_', None) if not enrollment_data: current_app.logger.error('Found no U2F enrollment data in session.') return error_response(message=SecurityMsg.missing_data) data = { 'version': version, 'registrationData': registration_data, 'clientData': client_data } device, der_cert = complete_registration(enrollment_data, data, current_app.config.u2f_facets) cert = x509.load_der_x509_certificate(der_cert, default_backend()) pem_cert = crypto.dump_certificate(crypto.FILETYPE_PEM, cert) if not isinstance(pem_cert, six.string_types): pem_cert = pem_cert.decode('utf-8') u2f_token = U2F.from_dict( dict( version=device['version'], keyhandle=device['keyHandle'], app_id=device['appId'], public_key=device['publicKey'], attest_cert=pem_cert, description=description, created_by='eduid_security', created_ts=True, )) security_user.credentials.add(u2f_token) save_and_sync_user(security_user) current_app.stats.count(name='u2f_token_bind') credentials = compile_credential_list(security_user) return success_response(payload=dict(credentials=credentials), message=SecurityMsg.u2f_registered)
def add_key(request): if request.method == 'GET': origin = get_origin(request) u2f_request = u2f.begin_registration(origin) request.session['u2f_request'] = u2f_request context = {'u2f_request': json.dumps(request.session['u2f_request'])} return render(request, 'registration/add_key.html', context) u2f_response = request.POST['response'] origin = get_origin(request) device, attestation_cert = u2f.complete_registration( request.session['u2f_request'], u2f_response) models.U2FKey.objects.update_or_create( user=request.user, defaults={ 'public_key': device['publicKey'], 'key_handle': device['keyHandle'], 'app_id': device['appId'], }, ) messages.success(request, 'Yubikey configured.') del request.session['u2f_request'] request.session['yubikey_authenticated'] = True return redirect('home')