Closed Residuum22 closed 2 years ago
This error is occuring because the cookie is expected to be a string not a byte array or bytes. Can you share the code how you set the cookie?
Here is the environment of the creation of the cookie:
@app.post("/login")
def login(request: Request, username: str = Form(...), password: str = Form(...)):
#def login(request: Request, form_data: OAuth2PasswordRequestForm = Depends()):
# Select users from database
#user = load_user(form_data.username)
loginUser = select(members.c.username, members.c.password).where(
members.c.username == username)
result = engine.execute(loginUser)
row = result.fetchone()
logger.info("Post login user is: " + row.username)
# Check exist of the username
# if user is None:
# return templates.TemplateResponse("login.html", {"request": request, "error_status": "Didn't find any user with this username! Try again or register!"})
# Check match of the password
if row.password == password:
access_token = manager.create_access_token(
data={"sub":username}
)
logger.info("Token has been created!")
response = RedirectResponse(
url="/frontpage", status_code=status.HTTP_302_FOUND)
manager.set_cookie(response, access_token)
#logger.info("Cookie has been created!")
# return {'access_token': access_token, 'token_type': 'bearer'}
return response
else:
#raise InvalidCredentialsException
return templates.TemplateResponse("login.html", {"request": request, "error_status": "Password isn't correct! Try again!"})
And here is the user loader:
@manager.user_loader()
def load_user(username: str):
loginUser = select(members.c.username, members.c.password).where(
members.c.username == username)
result = engine.execute(loginUser)
row = result.fetchone()
if row:
logger.info("Loaded user is: " + row.username)
print("Loaded user is: " + row.username)
return row.username
else:
logger.error("User not found")
print("User not found")
return None
Honestly I have no idea why your code is not working.
What version of fastapi-login
are you using?
Have you set the use_cookie=True
argument and are you using the manager as a dependency?
This is the code I used to try if cookies are working as expected:
You can try for yourself if this works by opening 127.0.0.1:8000/login
from fastapi import FastAPI, Depends
from starlette.status import HTTP_302_FOUND
from starlette.requests import Request
from starlette.responses import HTMLResponse, RedirectResponse
from fastapi_login import LoginManager
DB = {"test-user@example.org": {"email": "test-user@example.org", "password": "hunter2"}}
app = FastAPI()
manager = LoginManager(secret="your-secret-key", token_url="/login", use_cookie=True)
@manager.user_loader()
def get_user(email: str):
return DB[email]
@app.get('/login')
def login():
"""
For testing purposes this automatically creates a access token and the redirects to /cookies
"""
access_token = manager.create_access_token(
data={'sub': 'test-user@example.org'}
)
print(f"Access token is: {access_token}")
response = RedirectResponse(url="/cookies", status_code=HTTP_302_FOUND)
manager.set_cookie(response, access_token)
print(f"Response headers are: {response.headers}")
print(f"Redirecting to '/cookies'")
return response
@app.get('/cookies')
async def list_cookies(request: Request, user=Depends(manager)):
"""
Returns a json response containing all cookies set in the request
and tries to load the user from the token, if this fails a InvalidCredentialsException is returned
"""
print('Authentication was successfull.')
print(f'Authorization cookie: {request.cookies.get(manager.cookie_name)}')
return {
'cookies': request.cookies,
'auth': {
'successful': True, # Otherwise a exception is returned
'user': user
}
}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app)
Did this help?
Sorry for the late reply, but I had not too much time in the last few days. Your code output:
{"cookies":{"access-token":"b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0LXVzZXJAZXhhbXBsZS5vcmciLCJleHAiOjE2MzM5NzAwNTB9.Xg60C82RSd4UtubpdmCtD10HeLEfioJLCVYRwvzy1sY'"},"auth":{"successful":true,"user":{"email":"test-user@example.org","password":"hunter2"}}}
I suspect if I am the only one, who having this problem, that there is something wrong with the wsl. Interesting.
Interestingly the access-token in your case still contains the b' * '
, no matter how (i.e. browser, python requests or httpie) I cannot replicate that behaviour.
Do you mind sharing which browser you use or how you get the response, just in case other people have the same issue?
I am using Edge chromium lastest build, but this issue also exist in Firefox. I will try it on my native linux machine tomorrow and I will reply back!
Thank you.
In just tried it inside a arch linux vm and it seemed to work for me just fine.
Can you also share the output of pip list
from inside your virtualenv?
Hi!
I think I have found a bug in the login with cookies. I always got 401 error, so I started to dig down in the script. Finally I have found the problem and the "hotfix" solution. Well: The byte array somewhere will be converted into string so in the cookie the
b' * '
identifiers are remamining in the cookie and the jwt parser can not parse the data. For example: Token (cookie):If I cuted down the first two byte and the last byte the decode works like a charm. Cutted token:
Have you experienced this error?