httpOnly cookie attempt 1
This commit is contained in:
		
							parent
							
								
									32fb68c5ea
								
							
						
					
					
						commit
						dff3074f8c
					
				
							
								
								
									
										39
									
								
								auth.py
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								auth.py
									
									
									
									
									
								
							@ -5,8 +5,8 @@ from typing import Any, Union
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import bcrypt
 | 
					import bcrypt
 | 
				
			||||||
import jwt
 | 
					import jwt
 | 
				
			||||||
from fastapi import Depends, HTTPException, status
 | 
					from fastapi import Cookie, Depends, HTTPException, status
 | 
				
			||||||
from fastapi.security import HTTPBearer
 | 
					from fastapi.security import HTTPBearer, OAuth2PasswordRequestForm
 | 
				
			||||||
from jwt.exceptions import InvalidTokenError
 | 
					from jwt.exceptions import InvalidTokenError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ACCESS_TOKEN_EXPIRE_MINUTES = 30  # 30 minutes
 | 
					ACCESS_TOKEN_EXPIRE_MINUTES = 30  # 30 minutes
 | 
				
			||||||
@ -38,6 +38,7 @@ def get_current_user(token: str = Depends(security)) -> dict:
 | 
				
			|||||||
        headers={'WWW-Authenticate': 'Bearer'}
 | 
					        headers={'WWW-Authenticate': 'Bearer'}
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    credential = token.credentials
 | 
					    credential = token.credentials
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        payload = jwt.decode(credential, JWT_SECRET_KEY, algorithms=[ALGORITHM])
 | 
					        payload = jwt.decode(credential, JWT_SECRET_KEY, algorithms=[ALGORITHM])
 | 
				
			||||||
        user_id: str = payload.get("sub")
 | 
					        user_id: str = payload.get("sub")
 | 
				
			||||||
@ -65,6 +66,40 @@ def get_current_user(token: str = Depends(security)) -> dict:
 | 
				
			|||||||
    return cur_user
 | 
					    return cur_user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_current_user2(token: str = Cookie(default=None)):
 | 
				
			||||||
 | 
					    credentials_exception = HTTPException(
 | 
				
			||||||
 | 
					        status_code=status.HTTP_401_UNAUTHORIZED,
 | 
				
			||||||
 | 
					        detail="Could not validate credentials",
 | 
				
			||||||
 | 
					        headers={'WWW-Authenticate': 'Bearer'}
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    print('TOKEN: ', token)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        payload = jwt.decode(token, JWT_SECRET_KEY, algorithms=[ALGORITHM])
 | 
				
			||||||
 | 
					        user_id: str = payload.get("sub")
 | 
				
			||||||
 | 
					        if user_id is None:
 | 
				
			||||||
 | 
					            raise credentials_exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    except InvalidTokenError:
 | 
				
			||||||
 | 
					        raise credentials_exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open('database/users.json', 'r') as f:
 | 
				
			||||||
 | 
					        text = f.read()
 | 
				
			||||||
 | 
					        if text:
 | 
				
			||||||
 | 
					            data = json.loads(text)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            raise credentials_exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    user = [i for i in data if i['id']==user_id]
 | 
				
			||||||
 | 
					    if not user:
 | 
				
			||||||
 | 
					        raise credentials_exception
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cur_user = {'id': user_id}
 | 
				
			||||||
 | 
					    cur_user['username'] = user[0]['username']
 | 
				
			||||||
 | 
					    cur_user['encryption_key'] = payload['key']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return cur_user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Hasher:
 | 
					class Hasher:
 | 
				
			||||||
    """Class for hashing and verifying passwords"""
 | 
					    """Class for hashing and verifying passwords"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -29,10 +29,14 @@ export default {
 | 
				
			|||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
    async login() {
 | 
					    async login() {
 | 
				
			||||||
      const url = `${this.apiBaseUrl}/login`;
 | 
					      const url = `${this.apiBaseUrl}/login`;
 | 
				
			||||||
 | 
					      var formData = new FormData();
 | 
				
			||||||
 | 
					      for (var key in this.form) {
 | 
				
			||||||
 | 
					        formData.append(key, this.form[key]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      const requestOptions = {
 | 
					      const requestOptions = {
 | 
				
			||||||
        method: "POST",
 | 
					        method: "POST",
 | 
				
			||||||
        headers: { "Content-Type": "application/json" },
 | 
					        // headers: { "Content-Type": "application/json" },
 | 
				
			||||||
        body: JSON.stringify(this.form),
 | 
					        body: formData,
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const response = await fetch(url, requestOptions)
 | 
					      const response = await fetch(url, requestOptions)
 | 
				
			||||||
@ -47,9 +51,10 @@ export default {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
      console.log("response: ", response);
 | 
					      console.log("response: ", response);
 | 
				
			||||||
      if ("message" in response) {
 | 
					      if ("message" in response) {
 | 
				
			||||||
        if (response.message === "authenticated") {
 | 
					        if (response.message === "Authenticated") {
 | 
				
			||||||
          const token = response.accessToken;
 | 
					          // const token = response.accessToken;
 | 
				
			||||||
          sessionStorage.setItem("token", token);
 | 
					          // sessionStorage.setItem("token", token);
 | 
				
			||||||
 | 
					          sessionStorage.setItem("authenticated", true);
 | 
				
			||||||
          this.$emit("loggedin", true);
 | 
					          this.$emit("loggedin", true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
@ -100,13 +100,14 @@ export default {
 | 
				
			|||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
    async listSecrets() {
 | 
					    async listSecrets() {
 | 
				
			||||||
      const url = `${this.apiBaseUrl}/secret`;
 | 
					      const url = `${this.apiBaseUrl}/secret`;
 | 
				
			||||||
      const token = sessionStorage.getItem("token");
 | 
					      // const token = sessionStorage.getItem("token");
 | 
				
			||||||
      const requestOptions = {
 | 
					      const requestOptions = {
 | 
				
			||||||
        method: "GET",
 | 
					        method: "GET",
 | 
				
			||||||
        headers: {
 | 
					        credentials: "include",
 | 
				
			||||||
          "Content-Type": "application/json",
 | 
					        // headers: {
 | 
				
			||||||
          Authorization: `Bearer ${token}`,
 | 
					        //   // "Content-Type": "application/json",
 | 
				
			||||||
        },
 | 
					        //   // Authorization: `Bearer ${token}`,
 | 
				
			||||||
 | 
					        // },
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      console.log(requestOptions);
 | 
					      console.log(requestOptions);
 | 
				
			||||||
      const response = await fetch(url, requestOptions)
 | 
					      const response = await fetch(url, requestOptions)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										50
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								main.py
									
									
									
									
									
								
							@ -1,19 +1,15 @@
 | 
				
			|||||||
import json
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from fastapi import Depends, FastAPI, HTTPException, status
 | 
					from fastapi import Depends, FastAPI, HTTPException, Response, status
 | 
				
			||||||
from fastapi.encoders import jsonable_encoder
 | 
					from fastapi.encoders import jsonable_encoder
 | 
				
			||||||
from fastapi.middleware.cors import CORSMiddleware
 | 
					from fastapi.middleware.cors import CORSMiddleware
 | 
				
			||||||
from fastapi.security import OAuth2PasswordBearer
 | 
					from fastapi.security import OAuth2PasswordRequestForm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from auth import Hasher, create_access_token, get_current_user
 | 
					from auth import (Hasher, create_access_token, get_current_user,
 | 
				
			||||||
from crypto import (
 | 
					                  get_current_user2)
 | 
				
			||||||
    deserialize_into_bytes,
 | 
					from crypto import (deserialize_into_bytes, fernet_decrypt, fernet_encrypt,
 | 
				
			||||||
    fernet_decrypt,
 | 
					                    generate_random_encryption_key, generate_user_passkey,
 | 
				
			||||||
    fernet_encrypt,
 | 
					                    serialize_bytes)
 | 
				
			||||||
    generate_random_encryption_key,
 | 
					 | 
				
			||||||
    generate_user_passkey,
 | 
					 | 
				
			||||||
    serialize_bytes,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
from models import Secret, User, UserLogin
 | 
					from models import Secret, User, UserLogin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app = FastAPI()
 | 
					app = FastAPI()
 | 
				
			||||||
@ -22,7 +18,7 @@ app = FastAPI()
 | 
				
			|||||||
origins = [
 | 
					origins = [
 | 
				
			||||||
    'http://localhost',
 | 
					    'http://localhost',
 | 
				
			||||||
    'http://localhost:5173',
 | 
					    'http://localhost:5173',
 | 
				
			||||||
    "*"
 | 
					    # "*"
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
app.add_middleware(
 | 
					app.add_middleware(
 | 
				
			||||||
    CORSMiddleware,
 | 
					    CORSMiddleware,
 | 
				
			||||||
@ -81,7 +77,7 @@ async def register(user: User):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.post('/login')
 | 
					@app.post('/login')
 | 
				
			||||||
async def login(user: UserLogin):
 | 
					async def login(response: Response, form_data: OAuth2PasswordRequestForm = Depends()):
 | 
				
			||||||
    """logs in the user"""
 | 
					    """logs in the user"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    users = []
 | 
					    users = []
 | 
				
			||||||
@ -90,7 +86,10 @@ async def login(user: UserLogin):
 | 
				
			|||||||
        if text:
 | 
					        if text:
 | 
				
			||||||
            users.extend(json.loads(text))
 | 
					            users.extend(json.loads(text))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cur_user = [i for i in users if i['username']==user.username]
 | 
					    username = form_data.username
 | 
				
			||||||
 | 
					    password = form_data.password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cur_user = [i for i in users if i['username']==username]
 | 
				
			||||||
    if not cur_user:
 | 
					    if not cur_user:
 | 
				
			||||||
        raise HTTPException(
 | 
					        raise HTTPException(
 | 
				
			||||||
            status_code=status.HTTP_400_BAD_REQUEST,
 | 
					            status_code=status.HTTP_400_BAD_REQUEST,
 | 
				
			||||||
@ -99,7 +98,7 @@ async def login(user: UserLogin):
 | 
				
			|||||||
    else:
 | 
					    else:
 | 
				
			||||||
        cur_user = cur_user[0]
 | 
					        cur_user = cur_user[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    password_match = Hasher.verify_password(user.password, cur_user['password'])
 | 
					    password_match = Hasher.verify_password(password, cur_user['password'])
 | 
				
			||||||
    if not password_match:
 | 
					    if not password_match:
 | 
				
			||||||
        raise HTTPException(
 | 
					        raise HTTPException(
 | 
				
			||||||
            status_code=status.HTTP_400_BAD_REQUEST,
 | 
					            status_code=status.HTTP_400_BAD_REQUEST,
 | 
				
			||||||
@ -108,16 +107,16 @@ async def login(user: UserLogin):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    encrypted_encryption_key = cur_user['encryption_key'].encode()
 | 
					    encrypted_encryption_key = cur_user['encryption_key'].encode()
 | 
				
			||||||
    salt = deserialize_into_bytes(cur_user['salt'])
 | 
					    salt = deserialize_into_bytes(cur_user['salt'])
 | 
				
			||||||
    _, master_key = generate_user_passkey(user.password, salt)
 | 
					    _, master_key = generate_user_passkey(password, salt)
 | 
				
			||||||
    encryption_key = fernet_decrypt(encrypted_encryption_key, master_key)
 | 
					    encryption_key = fernet_decrypt(encrypted_encryption_key, master_key)
 | 
				
			||||||
    access_token = create_access_token(subject=cur_user['id'], encryption_key=encryption_key)
 | 
					    access_token = create_access_token(subject=cur_user['id'], encryption_key=encryption_key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    response = {
 | 
					    # response = {
 | 
				
			||||||
        'message': 'authenticated',
 | 
					    #     'message': 'authenticated',
 | 
				
			||||||
        'accessToken': access_token
 | 
					    #     'accessToken': access_token
 | 
				
			||||||
    }
 | 
					    # }
 | 
				
			||||||
 | 
					    response.set_cookie('token', value=access_token, max_age=1800, httponly=True, path='/')
 | 
				
			||||||
    return response
 | 
					    return {'message': 'Authenticated'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.post("/secret")
 | 
					@app.post("/secret")
 | 
				
			||||||
@ -185,9 +184,9 @@ async def update_secret(secret: Secret, current_user: dict = Depends(get_current
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.get('/secret')
 | 
					@app.get('/secret')
 | 
				
			||||||
async def list_secret(current_user: dict = Depends(get_current_user)):
 | 
					async def list_secret(current_user: dict = Depends(get_current_user2)):
 | 
				
			||||||
    """Returns the encrypted secrets of the user."""
 | 
					    """Returns the encrypted secrets of the user."""
 | 
				
			||||||
 | 
					    print('cuuuuuurrrrr', current_user)
 | 
				
			||||||
    data = []
 | 
					    data = []
 | 
				
			||||||
    with open('database/secrets.json', 'r') as f:
 | 
					    with open('database/secrets.json', 'r') as f:
 | 
				
			||||||
        text = f.read()
 | 
					        text = f.read()
 | 
				
			||||||
@ -207,10 +206,11 @@ async def list_secret(current_user: dict = Depends(get_current_user)):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.get('/validate-token')
 | 
					@app.get('/validate-token')
 | 
				
			||||||
async def validate_token(current_user: dict = Depends(get_current_user)):
 | 
					async def validate_token(current_user: dict = Depends(get_current_user2)):
 | 
				
			||||||
    user_id = current_user['id']
 | 
					    user_id = current_user['id']
 | 
				
			||||||
    print("user_id: ", user_id)
 | 
					    print("user_id: ", user_id)
 | 
				
			||||||
    if user_id is not None:
 | 
					    if user_id is not None:
 | 
				
			||||||
        return {'message': 'authenticated'}
 | 
					        return {'message': 'authenticated'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
 | 
					    raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
 | 
				
			||||||
 | 
					    # return {'message': "hello"}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user