Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JWT in httponly cookie instead of HTTP header #1520

Open
4 of 7 tasks
dokterbob opened this issue Nov 13, 2024 · 1 comment
Open
4 of 7 tasks

JWT in httponly cookie instead of HTTP header #1520

dokterbob opened this issue Nov 13, 2024 · 1 comment
Assignees
Labels
architecture Overall project architecture. auth Pertaining to authentication. backend Pertains to the Python backend. frontend Pertains to the frontend. security

Comments

@dokterbob
Copy link
Collaborator

dokterbob commented Nov 13, 2024

This is an initial research ticket to pave the way towards improving the way we do authentication within chainlit (so between frontend and backend, not between backend and 3rd parties).

Steps

  • Inventory of pre-existing issues
  • Inventory of relevant backend/frontend code
  • Inventory of relevant documentation of pre-existing situation
  • Inventory of 3rd party and/or common solutions (can/should we use some library?)
  • POC implementation
  • Clear spec of feature
  • Implementation of feature

Current approach

We're keeping the JWT in localStorage, sending it along for every API request which requires authentication.
This approach is used for all clients (frontend, copilot and the React client library).

Limits to current approach

XSS vulnerabilities

We have been made aware that the combination of having the token in localStorage, where JS can access it and being able to upload files to the same domain allows crafting of link able to steal user's authentication token and thus session and history.

This is in part caused by #1101.

Authentication for get_file()

We're adding links to files on the server. To authenticate requests for these files, whilst still allowing normal HTML tags (e.g. <img src="<url>" over src=URL.createObjectURL(blob) and fetch()), sending auth data in a httponly cookie will do the trick.

Issues

Caveats

Copilot auth works differently

Ref: https://docs.chainlit.io/deploy/copilot#authentication

Issues

Cookie-based auth requires CSRF protection

Discussion

Alternative: streaming file download, setting src to blob

This approach seems more tricky -- but it's less 'stateful' and we don't need to change as much, server side.
Might be a lot of edge cases for all the different Elements we use though.

https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams

HTTP only cookies

Possibly relevant issues

Code

Client

Log-in callback

Handled client side, once user's login is validated server-side (see server code below), here:

  1. path: '/login/callback',
  2. export default function AuthCallback() {

React client useAuth()

export const useAuth = () => {

Server

httponly cookie should be set here:

  1. async def login(form_data: OAuth2PasswordRequestForm = Depends()):
  2. async def header_auth(request: Request):

And/or possibly here:

  1. async def oauth_callback(
  2. async def oauth_azure_hf_callback(

And should be read here:
https://github.com/Chainlit/chainlit/blob/main/backend/chainlit/auth.py

Where the JWT is created/validated here:

def create_jwt(data: User) -> str:

It should be removed here:

async def logout(request: Request, response: Response):

Documentation

Current situation

Future situation

Prior efforts

FastAPI/cookie based JWT

External libraries

Instead of 'rolling our own', perhaps we should consider getting rid of this code and replace it by one or more well-supported libraries.

@dokterbob dokterbob added frontend Pertains to the frontend. auth Pertaining to authentication. backend Pertains to the Python backend. security architecture Overall project architecture. labels Nov 13, 2024
@dokterbob dokterbob self-assigned this Nov 13, 2024
@dokterbob dokterbob mentioned this issue Nov 14, 2024
7 tasks
@nethi
Copy link

nethi commented Nov 30, 2024

@dokterbob I am assuming this is primarily for default frontend right ? I am assuming we will still have ability to get a chainlit access token and pass it in custom frontends.

Also, passing access token directly is also critical for copilot to work today

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
architecture Overall project architecture. auth Pertaining to authentication. backend Pertains to the Python backend. frontend Pertains to the frontend. security
Projects
None yet
Development

No branches or pull requests

2 participants