def _check_webauthn_result(self, state_token, login_data): """ wait for webauthN challenge """ nonce = login_data['_embedded']['factor']['_embedded']['challenge']['challenge'] credential_id = login_data['_embedded']['factor']['profile']['credentialId'] response = {} """ Authenticator """ verif = WebAuthnClient(self.ui, self._okta_org_url, nonce, credential_id) try: client_data, assertion = verif.verify() except: client_data = b'fake' assertion = FakeAssertion() client_data = str(base64.urlsafe_b64encode(client_data), "utf-8") signature_data = base64.b64encode(assertion.signature).decode('utf-8') auth_data = base64.b64encode(assertion.auth_data).decode('utf-8') response = self._http_client.post( login_data['_links']['next']['href'] + "?rememberDevice=false", json={'stateToken': state_token, 'clientData':client_data, 'signatureData': signature_data, 'authenticatorData': auth_data}, headers=self._get_headers(), verify=self._verify_ssl_certs ) response.raise_for_status() response_data = response.json() if 'status' in response_data and response_data['status'] == 'SUCCESS': if 'stateToken' in response_data: return {'stateToken': response_data['stateToken'], 'apiResponse': response_data} if 'sessionToken' in response_data: return {'stateToken': None, 'sessionToken': response_data['sessionToken'], 'apiResponse': response_data} else: return {'stateToken': None, 'sessionToken': None, 'apiResponse': response_data}
def _activate_webauthn_factor(self, state_token): enrollment_response = self._enroll_factor(state_token) response_json = enrollment_response.json() next_link = response_json['_links']['next'] if next_link['name'] != 'activate': raise RuntimeError( 'Expected next link to be an activation link, actually got: ' + next_link["name"]) factor_obj = response_json['_embedded']['factor'] activation_obj = factor_obj['_embedded']['activation'] challenge = activation_obj.get('challenge') user_obj = activation_obj.get('user', {}) webauthn_client = WebAuthnClient(self.ui, self._okta_org_url, challenge) client_data_json, attestation = webauthn_client.make_credential( user_obj) client_data = str(base64.urlsafe_b64encode(client_data_json), 'utf-8') attestation_data = str(base64.urlsafe_b64encode(attestation), 'utf-8') response = self._http_client.post(next_link['href'], json={ "stateToken": state_token, "clientData": client_data, "attestation": attestation_data }, headers=self._get_headers(), verify=self._verify_ssl_certs) response.raise_for_status() session_token = response.json()['sessionToken'] redirect_url = quote(self._okta_org_url + '/enduser/settings?enrolledFactor=FIDO_WEBAUTHN') response = self._http_client.get( self._okta_org_url + '/login/sessionCookieRedirect?checkAccountSetupComplete=true&' 'token={session_token}&redirectUrl={redirect_url}'.format( session_token=session_token, redirect_url=redirect_url), headers=self._get_headers(), verify=self._verify_ssl_certs) response.raise_for_status() return attestation.auth_data.credential_data.credential_id, user_obj.get( 'name', 'gimme-aws-creds')