def test_generate_token(self): """ Testing the generating of JWTs Good data should return a formatted plain-text string in the form: xxx.yyy.zzz where x is header information, y is json payload, and z is a signature Bad data should raise a TypeError in jwt_placeholder Test only confirms the payload is valid on good data, or that a TypeError is raised on bad data """ """Testing json objects""" for data in self.good_data_list: jwt = jwt_placeholder.generate_token(data) header, payload, signature = str(jwt).split('.') self.assertTrue(base64_to_json_compare(payload, data)) """Testing non-json objects""" for data in self.bad_data_list: with self.assertRaises(TypeError): jwt = jwt_placeholder.generate_token(data)
def test_token_expiration(self): """ Testing that the JWT's expiration wokrs as expected Since this unit test exists with the backend, it can manually overide the expiration times Will test that a token validates as expected within an expiration period Will test that a token is invalid after the expiration period """ # Grab the first good piece of data data = self.good_data_list[0] jwt = jwt_placeholder.generate_token(data) """ Confirm that our token validates as expected """ self.assertTrue(jwt_placeholder.validate_token(jwt)) # We'll modify the expiration time, but teardown() will set it back to the original time # Set the expiration time to 1 second in the past jwt_placeholder.token_expiration_time = -1 # This token, while signed properly, has an expiration date of 1 second ago jwt = jwt_placeholder.generate_token(data) """ Confirm that our token validation raises an exception """ with self.assertRaises(jwt_lib.exceptions.ExpiredSignatureError): ret_val = jwt_placeholder.validate_token(jwt)
def test_grab_token_payload(self): """ Testing the payload-grabbing of JWTs The payload/claims used to generate a JWT should matche the output from the grab_token_payload function """ """Testing valid and invalid comparisons""" for data in self.good_data_list: jwt = jwt_placeholder.generate_token(data) data_from_JWT = jwt_placeholder.grab_token_payload(jwt) """Valid comparison - should be True""" self.assertTrue(data == data_from_JWT) """Invalid comparison - should be False""" for bad_data in self.bad_data_list: self.assertFalse(bad_data == data_from_JWT)
def login(request): """ Only available as a POST request Body: { usr (str): username as it shows in the database } Return: Return a JWT (plain-string) on success with the following header and payload Header: { typ (str): "JWT" alg (str): "HS256" } Payload: { first_name (str) last_name (str) username (str) email (str) } Return Unauthorized Error(401) otherwise Raises: TODO - is it good practice to raise in Django views? """ # Grab the username within the POST body requested_username = request.POST.get('username') # Attempt to grab first/last name, username, and email from the database # SQL equivilent: SELECT first_name, last_name, username, email FROM Identity WHERE Identity.username = requested_username user_data = Identity.objects.filter(username=requested_username).values('first_name', 'last_name', 'username', 'email') # If the query returned nothing, then the username isn't in the database if len(user_data) < 1: return HttpResponse('Unauthorized', status=http_unauthorized_response) # Otherwise, return a JWT containing the first/last name, username, and email token = j.generate_token(user_data[0]) return HttpResponse(token)
def test_validate_token(self): """ Testing the validation of JWTs A legitimate JWT should return True An illegitimate/tampered JWT should raise an InvalidSignatureError An improperly formatted token should raise a DecodeError """ # Grab a JWT and confirm that jwt_placeholder can successfully validate it data = self.good_data_list[0] jwt = jwt_placeholder.generate_token(data) """Testing a valid token""" self.assertTrue(jwt_placeholder.validate_token(jwt)) # Create our own token to try and pass off on the server local_key = 'secret' wrong_key_jwt = jwt_lib.encode(data, local_key, algorithm='HS256') """Testing a token signed with the wrong secret key""" with self.assertRaises(jwt_lib.exceptions.InvalidSignatureError): ret_val = jwt_placeholder.validate_token(wrong_key_jwt) # Tamper with a valid token and try and validate it # We'll reuse the jwt from before since it is already vetted header, payload, signature = jwt.decode('utf-8').split('.') # We'll add additional data to the payload and re-encode it tampered_jwt = (header + '.' + payload + "ExtraData" + '.' + signature).encode('utf-8') """Testing a token with tampered data""" with self.assertRaises(jwt_lib.exceptions.InvalidSignatureError): ret_val = jwt_placeholder.validate_token(tampered_jwt) """Testing malformed token""" with self.assertRaises(jwt_lib.exceptions.DecodeError): ret_val = jwt_placeholder.validate_token( "Just a regular, unencoded string!")