Chainlit / chainlit

Build Conversational AI in minutes ⚡️
https://docs.chainlit.io
Apache License 2.0
7.06k stars 926 forks source link

Add custom endpoint to serve files with OAuth active #1477

Open Jimmy-Newtron opened 3 days ago

Jimmy-Newtron commented 3 days ago

https://github.com/Chainlit/chainlit/blob/2556985c94e20d977e4dc62c4fec2bcfb204f6d6/frontend/src/components/atoms/elements/PDF.tsx#L11

I am trying to figure out how to achieve my goal of serving private files (PDF, images, audio, videos, ...) that can be stored in a central S3 storage, by simply adding a custom endpoint with authentication (OAuth).

My actual setup returns an error 401 because the token is not part of the request to the server.

How can I ensure to have the token?

dosubot[bot] commented 3 days ago

Hey there, @Jimmy-Newtron! I'm here to help you with any bugs, questions, or contributions you have. Let's tackle this together!

To serve private files with OAuth authentication, you need to ensure that the authentication token is included in the request to your custom endpoint. Here's a step-by-step approach to achieve this:

  1. Create a Custom Endpoint: Use FastAPI to define a custom endpoint that serves the files. Ensure this endpoint requires authentication by checking for a valid token.

    from fastapi import FastAPI, Depends, HTTPException
    from fastapi.responses import FileResponse
    from your_auth_module import get_current_user
    
    app = FastAPI()
    
    @app.get("/serve-file")
    async def serve_file(file_path: str, user=Depends(get_current_user)):
       if not user:
           raise HTTPException(status_code=401, detail="Unauthorized")
       # Logic to fetch the file from S3
       return FileResponse(file_path)
  2. Modify the Frontend Component: In your PDFElement component, ensure that the token is included in the request. You can use the Fetch API or Axios to set custom headers.

    import React, { useEffect, useState } from 'react';
    import { useAuth } from 'path-to-your-auth-hook';
    
    const PDFElement = ({ element }) => {
     const { token } = useAuth();
     const [pdfUrl, setPdfUrl] = useState(null);
    
     useEffect(() => {
       if (element.url) {
         const fetchPdf = async () => {
           const response = await fetch(`/serve-file?file_path=${element.url}`, {
             headers: {
               'Authorization': `Bearer ${token}`
             }
           });
           if (response.ok) {
             setPdfUrl(element.url);
           } else {
             console.error('Failed to fetch PDF');
           }
         };
         fetchPdf();
       }
     }, [element.url, token]);
    
     if (!pdfUrl) return null;
    
     return <iframe src={pdfUrl} />;
    };
    
    export default PDFElement;
  3. Ensure Token Management: Use a state management solution like Recoil to manage the authentication token. The useAuth hook should provide access to the token, which is then used in the request headers.

By following these steps, you can ensure that the token is included in the request to your custom endpoint, allowing you to serve private files securely with OAuth authentication.

To continue talking to Dosu, mention @dosu.