Skip to content

Commit

Permalink
Setting the jwt_token in the cookie (#574)
Browse files Browse the repository at this point in the history
* Setting the cookie on the frontend to make it more secure

* Removing comments
  • Loading branch information
sylviamclaughlin authored Jul 10, 2024
1 parent 2ac5480 commit d70ef3d
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 30 deletions.
12 changes: 8 additions & 4 deletions app/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,9 @@ async def rate_limit_handler(request: Request, exc: RateLimitExceeded):
@limiter.limit("5/minute")
async def logout(request: Request):
request.session.pop("user", None)
request.session.pop("access_token", None)
return RedirectResponse(url="/")
response = RedirectResponse(url="/")
response.delete_cookie("access_token")
return response


# Login route. You will be redirected to the google login page
Expand Down Expand Up @@ -209,8 +210,11 @@ async def auth(request: Request):
if user_data:
request.session["user"] = dict(user_data)
jwt_token = create_access_token(data={"sub": user_data["email"]})
request.session["access_token"] = jwt_token
return RedirectResponse(url="/")
response = RedirectResponse(url="/")
response.set_cookie(
"access_token", jwt_token, httponly=True, secure=True, samesite="Strict"
)
return response


# User route. Returns the user's first name that is currently logged into the application
Expand Down
33 changes: 10 additions & 23 deletions app/server/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,37 +48,24 @@ def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):

async def get_current_user(request: Request):
"""
Retrieves the current authenticated user from the request.
This asynchronous function attempts to retrieve the user information
from either the session token or the session user stored in the request.
It performs the following steps:
1. Checks for the presence of an access token and session user in the request.
2. If neither is present, raises an HTTP 401 Unauthorized exception.
3. Attempts to decode the access token to extract the user information.
4. If the token is invalid or the user information is not present in the token,
it raises an HTTP 401 Unauthorized exception.
5. Returns the user information if successfully extracted from the token.
Extracts and verifies the JWT token from the request cookies to authenticate the user.
Args:
request (Request): The FastAPI request object containing session data.
Raises:
HTTPException: If neither the access token nor the session user is present in the request.
HTTPException: If the access token is invalid or the user information is not found.
Parameters:
request (Request): The HTTP request object containing the cookies.
Returns:
str: The user information extracted from the token or session.
str: The user identifier extracted from the JWT token payload.
Raises:
HTTPException: If the JWT token is not found, is invalid, or does not contain a valid user identifier.
"""
# we are going to get the access token and the session user from the request to double check
token = request.session.get("access_token")
session_user = request.session.get("user")
if not token and not session_user:
jwt_token = request.cookies.get("access_token")
if not jwt_token:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Not authenticated"
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
payload = jwt.decode(jwt_token, SECRET_KEY, algorithms=[ALGORITHM])
user = payload.get("sub")
if user is None:
raise HTTPException(
Expand Down
2 changes: 1 addition & 1 deletion app/tests/server/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ async def test_get_current_user_no_token_or_session_user(mock_request):
with pytest.raises(HTTPException) as exc_info:
await utils.get_current_user(mock_request)
assert exc_info.value.status_code == 401
assert exc_info.value.detail == "Not authenticated"
assert exc_info.value.detail == "Invalid token"


@pytest.mark.asyncio
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/components/AWSRequestForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ const AWSRequestForm = ({ onSend }) => {
// Fetch accounts from API
const fetchAccounts = async () => {
try {
const response = await fetch('/accounts');
const response = await fetch('/accounts', {
method: 'GET',
credentials: 'include', //Include cookies with requests
});
const data = await response.json();
setAccounts(data); // Assuming the API returns an array of account numbers
} catch (error) {
Expand Down Expand Up @@ -63,6 +66,7 @@ const AWSRequestForm = ({ onSend }) => {
headers: {
'Content-Type': 'application/json',
},
credentials: 'include', //Include cookies with requests
body: JSON.stringify(requestData),
});
if (!response.ok) {
Expand Down
1 change: 0 additions & 1 deletion frontend/src/scenes/logout/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const Logout = () => {

if (response.ok) {
// Clear the authentication state and redirect to the landing page
navigate('/');
window.location.reload(); // Refresh the session
} else {
console.error('Failed to log out');
Expand Down

0 comments on commit d70ef3d

Please sign in to comment.