danny-avila / LibreChat

Enhanced ChatGPT Clone: Features Anthropic, OpenAI, Assistants API, Azure, Groq, GPT-4o, Mistral, OpenRouter, Vertex AI, Gemini, Artifacts, AI model switching, message search, langchain, DALL-E-3, ChatGPT Plugins, OpenAI Functions, Secure Multi-User System, Presets, completely open-source for self-hosting. Actively in public development.
https://librechat.ai/
MIT License
17.2k stars 2.87k forks source link

New user system breaks Apache Basic Auth #273

Closed matthieu-kr closed 1 year ago

matthieu-kr commented 1 year ago

I previously had v0.3.3 deployed via docker and working correctly behind an Apache reverse proxy and basic auth. Since the implementation of the new user system, (using v0.4.4) Apache Basic Auth endlessly requests credentials. If I disable Basic Auth, everything works perfectly, including the new user system.

The site does load partially with Basic Auth enabled, but with 401 errors for site assets which I'm guessing is triggering the continuing requests for credentials. I'm assuming the new authentication system is creating the conflict, but I'm not sure how to resolve.

Thanks for your insight.

OnePiZ commented 1 year ago

@matthieu-kr

I had the same problem before. After checking, I found out that the reason was the domain of Apache/Nginx's reverse proxy not using HTTPS. The user system needs to carry cookie information named 'token'.

If HTTPS is not enabled. After a successful login, you can check it in the developer tools that the 'set-cookie' in the 'Response Headers' of the login request has a warning message: This attempt to set a cookie via a Set-Cookie header was blocked because it had the "Secure" attribute but was not received over a secure connection.

image

matthieu-kr commented 1 year ago

The reverse proxy is delivering content over HTTPS. Internally it's referring to the docker container via http://localhost:port. What else might I be missing?

image

danny-avila commented 1 year ago

I don't have experience with Apache, wish I could help more. The main thing the user system introduced is authorization Bearer in the request header along with cookies

ChatGPT recommends (though I'm sure you've used it more specifically to your situation, so ignore if irrelevant):

You can configure Apache to allow all requests to the directory where static files are served without requiring Basic Auth.

If the new user system uses the Authorization header, it could be that Apache is stripping out these headers. You can add this to your Apache configuration to pass them to your application: SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

matthieu-kr commented 1 year ago

Doesn't seem to work. I've been fiddling with multiple configurations with no luck. BasicAuth seems to be overriding any attempt to correctly pass the authorization Bearer in both directions.

Here's what I'm really getting at though: I could be misunderstanding the user system, but it appears that on a public domain, anyone that registers has access to the application. The BasicAuth ensured I was the only one who could access it. I'd like to be able to restrict or disable account creation entirely.

danny-avila commented 1 year ago

Doesn't seem to work. I've been fiddling with multiple configurations with no luck. BasicAuth seems to be overriding any attempt to correctly pass the authorization Bearer in both directions.

Here's what I'm really getting at though: I could be misunderstanding the user system, but it appears that on a public domain, anyone that registers has access to the application. The BasicAuth ensured I was the only one who could access it. I'd like to be able to restrict or disable account creation entirely.

Not without modifying the code. We can look into a restrict sign up feature for this case

matthieu-kr commented 1 year ago

I figured out a hacky solution, but I have no idea whether or not it's actually a secure configuration.

I think unless you have an existing session, with the configuration below, any attempts to access any of the subfolders directly (https://mydomain.com/chat/new for example) will redirect you to the login page where the block will then enforce basic auth.

I think restricting sign up would still make sense though. I appreciate your feedback and love the project!

<Location /api> 
    Satisfy any
    ProxyPass http://localhost:3080/api 
    ProxyPassReverse http://localhost:3080/api
</Location> 

<Location /> 
    AuthType Basic 
    AuthName "Restricted Area" 
    AuthUserFile /etc/apache2/.publicpasswd 
    Require valid-user

    ProxyPass http://localhost:3080/ 
    ProxyPassReverse http://localhost:3080/ 
</Location>
lsalazarm99 commented 1 year ago

Many thanks, @matthieu-kr! I think the paths that should be blocked are /login, /register, and /api/auth/register. This last one is important since it is the API service that is used to register a user.

matthieu-kr commented 1 year ago

Per your suggestion, I updated the configuration to specifically block the /api/auth/register path and added the LocationMatch to ensure that it doesn't inherit the Satisfy any directive. Everything seems to be working as expected. Basic Auth now consistently prompts for credentials and stops after a successful login. It resumes prompting upon logout.

Thanks for your help!

<Location /api/auth/register>
    AuthType Basic
    AuthName "Restricted Area"
    AuthUserFile /etc/apache2/.publicpasswd
    Require valid-user
</Location>

<LocationMatch "^/api(?!/auth/register)">
    Satisfy any
    ProxyPass http://localhost:3080/api
    ProxyPassReverse http://localhost:3080/api
</LocationMatch>

<Location /> 
    AuthType Basic 
    AuthName "Restricted Area" 
    AuthUserFile /etc/apache2/.publicpasswd 
    Require valid-user

    ProxyPass http://localhost:3080/ 
    ProxyPassReverse http://localhost:3080/ 
</Location> 
danny-avila commented 1 year ago

@matthieu-kr Thanks for supporting and using the project! I'm going to forward this to @danorlando who did all the work on the user system.

@lsalazarm99 Thank you for your assistance on this!

danny-avila commented 1 year ago

Closing registration is being worked on in #346

danny-avila commented 1 year ago

With the latest update, you can now close registration by either omitting this env variable or setting it to false

# ALLOW_REGISTRATION=true
# ...or 
ALLOW_REGISTRATION=false

See the latest release here for more info, as there are many breaking changes with the update.

https://github.com/danny-avila/LibreChat/releases/tag/v0.5.0