def test_unsign_expired(self): value = 'TestSigner' signed = signing.TimestampSigner().sign(value) signed = base64.urlsafe_b64encode(bytes(signed, encoding='utf')).decode() with self.assertRaises(signing.SignatureExpired): signer.SIGNER.unsign(signed, 0)
def unsubscribe_reports(request, username): if ":" in username: signer = signing.TimestampSigner(salt="reports") try: username = signer.unsign(username) except signing.BadSignature: return render(request, "bad_link.html") else: # Username is not signed but there should be a ?token=... parameter # This is here for backwards compatibility and will be removed # at some point. try: signing.Signer().unsign(request.GET.get("token")) except signing.BadSignature: return render(request, "bad_link.html") user = User.objects.get(username=username) profile = Profile.objects.for_user(user) profile.reports_allowed = False profile.next_report_date = None profile.nag_period = td() profile.next_nag_date = None profile.save() return render(request, "accounts/unsubscribed.html")
def test_get_specific_question(self, client, db): survey = self.create_survey() survey.participant_can_skip = True survey.save() participant = self.create_participant(survey.pk) participant.save() question = self.create_question() question.save() question1 = Question( text='h0w good is hes?', attribute='porfessionalitaet', connotation=True, ) question1.save() signer = signing.TimestampSigner() token = signer.sign(participant.email) kwargs = { 'survey_pk': survey.pk, 'token': token, 'question_pk': question.pk } response = client.get(reverse('surver-answer-specific', kwargs=kwargs)) assert response.context[0]['statement'] == question.text
def test_project_transfer_accept_from_admin_member_with_valid_token_with_enough_slots( client): user_from = f.UserFactory.create() user_to = f.UserFactory.create(max_private_projects=1) signer = signing.TimestampSigner() token = signer.sign(user_to.id) project = f.create_project(owner=user_from, transfer_token=token, is_private=True) f.MembershipFactory(user=user_from, project=project, is_owner=True) f.MembershipFactory(user=user_to, project=project, is_owner=True) client.login(user_to) url = reverse("projects-transfer-accept", kwargs={"pk": project.pk}) data = { "token": token, } mail.outbox = [] response = client.json.post(url, json.dumps(data)) assert response.status_code == 200 assert len(mail.outbox) == 1 assert mail.outbox[0].to == [user_from.email] project = Project.objects.get(pk=project.pk) assert project.owner.id == user_to.id assert project.transfer_token is None
def test_invalid_or_alumni_account(self): dev_user_ = User.objects.create(email="*****@*****.**", cn="test", given_name="Test Dev", employee_id='testdev01') app_ = App.objects.create( user=dev_user_, name="An App", callback_url="www.somecallbackurl.com/callback") signer = signing.TimestampSigner() # Generate a random state for testing state = ''.join( random.choices(string.ascii_letters + string.digits, k=32)) data = app_.client_id + state signed_data = signer.sign(data) response = self.client.get( '/oauth/shibcallback', {'appdata': signed_data}, HTTP_EPPN='*****@*****.**', HTTP_CN='testxxx', HTTP_DEPARTMENT='Dept of Alumni', HTTP_GIVENNAME='Test', HTTP_DISPLAYNAME='Test User', HTTP_EMPLOYEEID='xxxtest01', ) self.assertEqual(response.status_code, 403)
def test_project_transfer_reject_from_admin_member_with_other_user_token( client): user_from = f.UserFactory.create() user_to = f.UserFactory.create() other_user = f.UserFactory.create() signer = signing.TimestampSigner() token = signer.sign(other_user.id) project = f.create_project(owner=user_from, transfer_token=token) f.MembershipFactory(user=user_from, project=project, is_owner=True) f.MembershipFactory(user=user_to, project=project, is_owner=True) client.login(user_to) url = reverse("projects-transfer-reject", kwargs={"pk": project.pk}) data = { "token": token, } mail.outbox = [] response = client.json.post(url, json.dumps(data)) assert response.status_code == 400 assert "Token is invalid" == response.data["_error_message"] assert len(mail.outbox) == 0
def test_project_transfer_reject_from_not_admin_member(client): user_from = f.UserFactory.create() user_to = f.UserFactory.create() signer = signing.TimestampSigner() token = signer.sign(user_to.id) project = f.create_project(owner=user_from, transfer_token=token, public_permissions=["view_project"]) f.MembershipFactory(user=user_from, project=project, is_owner=True) f.MembershipFactory(user=user_to, project=project, is_owner=False) client.login(user_to) url = reverse("projects-transfer-reject", kwargs={"pk": project.pk}) data = { "token": token, } mail.outbox = [] response = client.json.post(url, json.dumps(data)) assert response.status_code == 403 assert len(mail.outbox) == 0
def test_org_register(env, client): signer = signing.TimestampSigner( salt='customer-registration-captcha-127.0.0.1') r = client.post('/bigevents/account/register', { 'email': '*****@*****.**', 'name_parts_0': 'John Doe', 'challenge': signer.sign('1+2'), 'response': '3', }, REMOTE_ADDR='127.0.0.1') assert r.status_code == 302 assert len(djmail.outbox) == 1 with scopes_disabled(): customer = env[0].customers.get(email='*****@*****.**') assert not customer.is_verified assert customer.is_active r = client.post( f'/bigevents/account/activate?id={customer.identifier}&token={TokenGenerator().make_token(customer)}', { 'password': '******', 'password_repeat': 'PANioMR62', }) assert r.status_code == 302 customer.refresh_from_db() assert customer.check_password('PANioMR62') assert customer.is_verified
def test_repeat_activation(self): """ Once activated, attempting to re-activate an account (even with a valid key) does nothing. """ resp = self.client.post( reverse('registration_register'), data=self.valid_data ) signer = signing.TimestampSigner(salt=REGISTRATION_SALT) activation_key = signer.sign(self.valid_data['username']) resp = self.client.get( reverse( 'registration_activate', args=(), kwargs={'activation_key': activation_key} ) ) # First activation redirects to success. self.assertRedirects(resp, reverse('registration_activation_complete')) resp = self.client.get( reverse( 'registration_activate', args=(), kwargs={'activation_key': activation_key} ) ) # Second activation fails. self.assertEqual(200, resp.status_code) self.assertTemplateUsed(resp, 'registration/activate.html')
def test_it_serves_confirmation_form(self): sig = signing.TimestampSigner(salt="reports").sign("alice") url = "/accounts/unsubscribe_reports/%s/" % sig r = self.client.get(url) self.assertContains(r, "Please press the button below") self.assertNotContains(r, "submit()")
def unsubscribe_email(request, code, signed_token): # Some email servers open links in emails to check for malicious content. # To work around this, on GET requests we serve a confirmation form. # If the signature is at least 5 minutes old, we also include JS code to # auto-submit the form. ctx = {} if ":" in signed_token: signer = signing.TimestampSigner(salt="alerts") # First, check the signature without looking at the timestamp: try: token = signer.unsign(signed_token) except signing.BadSignature: return render(request, "bad_link.html") # Check if timestamp is older than 5 minutes: try: signer.unsign(signed_token, max_age=300) except signing.SignatureExpired: ctx["autosubmit"] = True else: token = signed_token channel = get_object_or_404(Channel, code=code, kind="email") if channel.make_token() != token: return render(request, "bad_link.html") if request.method != "POST": return render(request, "accounts/unsubscribe_submit.html", ctx) channel.delete() return render(request, "front/unsubscribe_success.html")
def post(self, request, *args, **kwargs): url_token = kwargs["token"] try: data = signing.TimestampSigner(salt="radiologo").unsign(url_token) decoded = signing.b64_decode(data.encode()) pk = (struct.unpack(str("!i"), decoded[:4])[0], decoded[4:])[0] except BadSignature: raise BadInviteTokenException user = get_object_or_404(get_user_model(), pk=pk) invite = Invite.objects.get(invited_user=user) self.check_different_token(url_token, invite.sent_token) self.check_expired(invite) self.check_accepted(invite) password = request.data["password"] validate_password(password, user=user, password_validators=get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)) user.set_password(password) invite.accepted = True user.is_registered = True user.save() invite.save() return Response(status=status.HTTP_200_OK)
def unsubscribe_reports(request, signed_username): # Some email servers open links in emails to check for malicious content. # To work around this, for GET requests we serve a confirmation form. # If the signature is more than 5 minutes old, we also include JS code to # auto-submit the form. ctx = {} signer = signing.TimestampSigner(salt="reports") # First, check the signature without looking at the timestamp: try: username = signer.unsign(signed_username) except signing.BadSignature: return render(request, "bad_link.html") # Check if timestamp is older than 5 minutes: try: username = signer.unsign(signed_username, max_age=300) except signing.SignatureExpired: ctx["autosubmit"] = True if request.method != "POST": return render(request, "accounts/unsubscribe_submit.html", ctx) user = User.objects.get(username=username) profile = Profile.objects.for_user(user) profile.reports_allowed = False profile.next_report_date = None profile.nag_period = td() profile.next_nag_date = None profile.save() return render(request, "accounts/unsubscribed.html")
def test_get_specific_question(self, client, db): survey = self.create_survey() survey.participant_can_skip = True survey.save() participant = self.create_participant(survey.pk) participant.save() question = self.create_question() question.save() question1 = Question( text="h0w good is hes?", attribute="porfessionalitaet", connotation=True, ) question1.save() signer = signing.TimestampSigner() token = signer.sign(participant.email) kwargs = { "survey_pk": survey.pk, "token": token, "question_pk": question.pk } response = client.get(reverse("surver-answer-specific", kwargs=kwargs)) assert response.context[0]["statement"] == question.text
def test_timestamp_signer(self): value = 'hello' _time = time.time time.time = lambda: 123456789 try: signer = signing.TimestampSigner('predictable-key') ts = signer.sign(value) self.assertNotEqual(ts, signing.Signer('predictable-key').sign(value)) self.assertEqual(signer.unsign(ts), value) time.time = lambda: 123456800 self.assertEqual(signer.unsign(ts, max_age=13), value) self.assertEqual(signer.unsign(ts, max_age=12), value) # max_age parameter can also accept a datetime.timedelta object self.assertEqual( signer.unsign(ts, max_age=datetime.timedelta(seconds=11)), value) self.assertRaises(signing.SignatureExpired, signer.unsign, ts, max_age=10) with self.assertRaises(signing.SignatureExpired): self.assertEqual( signer.unsign(ts, max_age=datetime.timedelta(seconds=10)), value) finally: time.time = _time
def test_it_handles_missing_user(self): self.alice.delete() sig = signing.TimestampSigner(salt="reports").sign("alice") url = "/accounts/unsubscribe_reports/%s/" % sig r = self.client.post(url) self.assertContains(r, "Unsubscribed")
def test_signed_username_works(self): sig = signing.TimestampSigner(salt="reports").sign("alice") url = "/accounts/unsubscribe_reports/%s/" % sig r = self.client.get(url) self.assertContains(r, "You have been unsubscribed") self.profile.refresh_from_db() self.assertFalse(self.profile.reports_allowed)
def test_unsign_max_age_none(self): value = 'TestSigner' signed = signing.TimestampSigner().sign(value) signed = base64.urlsafe_b64encode(bytes(signed, encoding='utf')) signed = signed.decode() actual = signer.SIGNER.unsign(signed) self.assertIsInstance(actual, str) self.assertEqual(actual, value)
def get_username(request): session_id = request.COOKIES.get('session_id', 0) if not session_id: return session_id timestamp_signing = signing.TimestampSigner() result = timestamp_signing.unsign(session_id, max_age=60 * 60 * 24) username = signing.loads(result)['username'] return username
def get_signer(): kwargs = {"salt": settings.SALT} if django.VERSION[:2] >= (3, 1): # pragma: no cover kwargs["algorithm"] = "sha1" if settings.MAX_AGE is None: return signing.Signer(**kwargs) else: return signing.TimestampSigner(**kwargs)
def dispatch(self, request, *args, **kwargs): self.token = kwargs["token"] signer = signing.TimestampSigner() try: self.email = signer.unsign(self.token) except signing.BadSignature: raise Http404 return super().dispatch(request, *args, **kwargs)
def test_user_cannot_create_feedback_if_it_already_exists(self): url = factories.FeedbackFactory.get_list_url() feedback = factories.FeedbackFactory() issue = feedback.issue signer = signing.TimestampSigner() token = signer.sign(issue.uuid.hex) response = self.client.post(url, data={'evaluation': 10, 'token': token},) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def __init__(self, **kwargs): routes = [ (r'/socket', SprintHandler), (r'/(?P<model>task|sprint|user)/(?P<pk>[0-9]+)', UpdateHandler), ] super().__init__(routes, **kwargs) self.subscriber = RedisSubscriber(Client()) self.publisher = Redis() self._key = config('WATERCOOLER_SECRET_KEY') self.signer = signing.TimestampSigner(self._key)
def generate_token(self): # Inspired by: https://github.com/aaugustin/django-sesame/ raw_token = struct.pack( str("!i"), self.invited_user.pk) + crypto.pbkdf2( self.invited_user.email, "radiologo", 10000) url_ready_token = signing.TimestampSigner(salt="radiologo").sign( signing.b64_encode(raw_token).decode()) self.sent_token = url_ready_token return url_ready_token
def test_unsign_an_invalid_structure(self): """ Given an invalid data type (not a dict), a BadSignature exception should be raised. """ signer = signing.TimestampSigner() signature = signer.sign(signing.dumps('this is not a dict')) with self.assertRaises(signing.BadSignature): self.sut(signature)
def validate_signature(secret: str, max_age: Union[int, timedelta] = None, value: str = "check") -> bool: """Validate that a secret contains the expected value and that it has not expired if necessary.""" try: signer = signing.TimestampSigner(salt=settings.SECRET_URL_SALT) result = signer.unsign(secret, max_age=max_age) return result == value except (signing.BadSignature, signing.SignatureExpired): return False
def get_activation_key(self, user): """ Generate the activation key which will be emailed to the user. """ signer = signing.TimestampSigner(salt=REGISTRATION_SALT) activation_key = signer.sign( str(getattr(user, user.USERNAME_FIELD)) ) return activation_key
def test_aged_signature_autosubmits(self): with patch("django.core.signing.time") as mock_time: mock_time.time.return_value = time.time() - 301 signer = signing.TimestampSigner(salt="reports") sig = signer.sign("alice") url = "/accounts/unsubscribe_reports/%s/" % sig r = self.client.get(url) self.assertContains(r, "Please press the button below") self.assertContains(r, "submit()")
def test_unsigns_an_empty_dict(self): """ Given that a dict is returned, but does not have appropriate keys, a BadSignature exception should raised. """ signer = signing.TimestampSigner() signature = signer.sign(signing.dumps({'fizz': 'buzz'})) with self.assertRaises(signing.BadSignature): self.sut(signature)
def test_user_can_create_feedback(self, user): url = factories.FeedbackFactory.get_list_url() issue = factories.IssueFactory() signer = signing.TimestampSigner() token = signer.sign(issue.uuid.hex) if user: self.client.force_authenticate(getattr(self.fixture, user)) response = self.client.post(url, data={'evaluation': 10, 'token': token},) self.assertEqual(response.status_code, status.HTTP_201_CREATED)