I have a simple login form that is opened using a GET
request, and the user submits the form with a POST
request. After successful authentication, I redirect the user to the main page of my web application using a RedirectResponse
object.
However, despite the successful redirection, the user is not authorized on the main page, as if the authentication cookie was not set. There are no error messages displayed.
Here's the code for my login route:
@router.post('/login')
def login(response: Response,
data: OAuth2PasswordRequestForm = Depends(),
db: Session = Depends(get_db)):
email = data.username
password = data.password
user = db.query(DbUser).filter(DbUser.email == email).first()
if not user:
# you can return any response or error of your choice
raise InvalidCredentialsException
if not Hash.verify(user.password, password):
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
detail='Incorrect password')
token = manager.create_access_token(
data={'sub': email}
)
resp = RedirectResponse(url='/post/stat/all',status_code=status.HTTP_302_FOUND)
manager.set_cookie(response, token)
return resp
However, if I change resp = RedirectResponse(...
to resp = 'ok'
, then everything works fine—just without a URL redirection.
Tried also with no luck:
return templates.TemplateResponse("/login/success.html",{"request": request})
What would the issue be and the way to fix it?
This is due to specifying the Response
object instead of RedirectResponse
in the manager.set_cookie()
method. As per your example:
@router.post('/login')
def login(response: Response,
^^^^^^^^
...):
...
resp = RedirectResponse(url='/post/stat/all', status_code=status.HTTP_302_FOUND)
^^^^
manager.set_cookie(response, token)
^^^^^^^^
return resp
This is why returning OK
or anything other than a custom Response
object works, as you noticed. Hence, since you are instead returning a custom RedirectResponse
, you should set the cookie for that RedirectResponse
instance:
@router.post('/login')
def login(data: OAuth2PasswordRequestForm = Depends(),
db: Session = Depends(get_db)):
...
resp = RedirectResponse(url='/post/stat/all', status_code=status.HTTP_302_FOUND)
manager.set_cookie(resp, token)
return resp
Related answer can be found here as well. A complete working example can also be found in this answer.