def test_oauth_crypto(self): phrase = 'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE' token = { 'access_token': 'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE', 'expires_in': oauth2_settings.ACCESS_TOKEN_EXPIRE_SECONDS, 'token_type': 'Password', 'refresh_token': 'abc', 'scope': 'read write' } data = encrypt_access_token(token) if not data: self.fail() result = decrypt_access_token(data) if not result: self.fail() if phrase != result['access_token']: self.fail('Decrypted value does not match phrase.')
def sdLogin(request, *args, **kwargs): # TODO: Support the "next" parameter in the template javascript redirect code. # This POST method is called by javascript and expects some JSON in return. # The goal here is to authenticate the user with oauth and then encrypt the # oauth information. The encrypted information will be stored in a browser cookie, # to be later decrypted in the middleware level to set the "Authorization" header. if request.method == 'POST': if 'username' not in request.POST or 'password' not in request.POST: raise ValueError # Manually do django authentication. username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) if user is not None and user.is_active: # Log our user in to django login(request, user) # Create and encrypt the access token based on this user enc = encrypt_access_token(create_access_token(user, user.profile.oauth_scope)) # Setup login redirect if 'next' in request.GET: redirect = request.GET['next'] else: redirect = settings.LOGIN_REDIRECT_URL # Format our response response = JsonResponse( dict([('status', 'OK'), ('next', redirect)]) ) # Set the encrypted token in the response. response.set_cookie('token', enc.decode('UTF-8')) response.set_cookie('fade-page-in', 1) else: # Send our error message response = JsonResponse( dict([('status', 'ERROR')]) ) return response else: form = accounts.forms.SDAuthenticationForm() context = { 'form': form, 'next': request.GET['next'] if 'next' in request.GET else None, } return render(request, 'accounts/login.html', context)
def test_token_encryption(self): """ Test the encryption and decryption of the access token """ enc_token = encrypt_access_token(self.token) self.assertTrue(enc_token) token = decrypt_access_token(enc_token) self.assertTrue(is_access_token_valid(token)) self.assertTrue(token)
def process_request(self, request): # Check to see if this is the login/logout page, if so just return. if '/accounts/login/' in request.path or '/accounts/logout/' in request.path: return # TODO: Only do oauth token stuff when the url is an API url if 'token' in request.COOKIES: # Get the encrypted access token data, fix any equal sign encoding. enc = request.COOKIES['token'].replace('%3D', '=').encode('UTF-8') # Decrypt the access token data token = decrypt_access_token(enc) # Check for a valid oauth token. if token is not None and 'access_token' in token: # Check to see if access token is not valid. if not is_access_token_valid(token): # TODO: Figure out when we should *not* just refresh the token. # Try to refresh the token. token = refresh_access_token(token) # If we have a good refreshed token, update the cookies. if 'access_token' in token: # Encrypt the new token enc = encrypt_access_token(token) # Set the token into the request object cookies = request.COOKIES.copy() cookies['token'] = enc.decode('UTF-8') cookies['token-update'] = "1" request.COOKIES = cookies.copy() else: # Refresh token failed return HttpResponseRedirect('/accounts/logout/') # Create the Authorization header with the access token. request.META['Authorization'] = 'bearer {0}'.format(token['access_token']) else: pass
def test_api_node_post(self): """ The url '/api/nodes' requires the oauth2 encrypted token when creating a record. If the 'token' cookie is not set, then the node API requires the HTTP_NODE header value set to access and update records. """ # Encrypt the token and store it in the client cookies. self.client.cookies['token'] = encrypt_access_token(self.token).decode('UTF-8') # Set node header value and see if we can retrieve the node record. response = self.client.get('/api/nodes/1/', HTTP_NODE=self.machine_id) self.assertEquals(response.status_code, 200) # Check for any unmatched fields. If there are, then check client models or node models # for field updates. data = response.json() # Update Node record data['dist_version'] = u'camelot' response = self.client.post('/api/nodes/', data=data) self.assertEquals(response.status_code, 200) self.assertEquals(response.json()['dist_version'], 'camelot') # Remove token cookie so we can test node authentication self.client.cookies.pop('token', None) # Test accessing the node record with no authentication set. We should get access denied. response = self.client.get('/api/nodes/') self.assertEquals(response.status_code, 403) # Set node header value and see if we can retrieve the node record. response = self.client.get('/api/nodes/1/', HTTP_NODE=self.machine_id) self.assertEquals(response.status_code, 200) # Check for any unmatched fields. If there are, then check client models or node models # for field updates. unmatched = set(response.json()) ^ set(data) self.assertTrue(len(unmatched) == 0)
def login_view(request, *args, **kwargs): # TODO: Support the "next" parameter in the template javascript redirect code. # This POST method is called by javascript and expects some JSON in return. # The goal here is to authenticate the user with oauth and then encrypt the # oauth information. The encrypted information will be stored in a browser cookie, # to be later decrypted in the middleware level to set the "Authorization" header. if request.method == 'POST': if 'username' not in request.POST or 'password' not in request.POST: raise ValueError # Manually do django authentication. username = request.POST['username'] password = request.POST['password'] user = authenticate(request=request, username=username, password=password) if user is not None and user.is_active: # Log our user in to django login(request, user) # Create and encrypt the access token based on this user enc = encrypt_access_token( create_access_token(user, user.profile.oauth_scope)) # Setup login redirect if 'next' in request.GET: redirect = request.GET['next'] else: redirect = settings.LOGIN_REDIRECT_URL # Format our response response = JsonResponse( dict([('status', 'OK'), ('next', redirect)])) # TODO: find out why this delays forever when celery service is not running # user_security_event.delay(username, 'login') # Set the encrypted token in the response. response.set_cookie('token', enc.decode('UTF-8')) response.set_cookie('fade-page-in', 1) else: # Send our error message response = JsonResponse(dict([('status', 'ERROR')])) # user_security_event.delay(username, 'login', success=False) return response else: form = forms.LoginForm() context = { 'form': form, 'next': request.GET['next'] if 'next' in request.GET else None, } return render(request, 'accounts/login.html', context)