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

HTTP Basic Auth not working as expected for nginx-ingress / kubernetes #1353

Closed
tgruenert opened this issue Oct 2, 2020 · 19 comments · Fixed by #1563
Closed

HTTP Basic Auth not working as expected for nginx-ingress / kubernetes #1353

tgruenert opened this issue Oct 2, 2020 · 19 comments · Fixed by #1563
Assignees
Labels
priority/3/medium Medium priority items status/in-progress Work is in progress type/feature Request for adding a new feature

Comments

@tgruenert
Copy link

Authelia is used inside kubernetes to protecd some services used by endusers with browser. Its working nice.

Additional some technical services has to be protected. At this time these are protected by http basic auth. Ingress looks like
https://kubernetes.github.io/ingress-nginx/examples/auth/basic/

Watch at curl resonse:
WWW-Authenticate: Basic realm="Authentication Required - foo"

Now I want to replace this with an authelia basic auth protection like
https://kubernetes.github.io/ingress-nginx/examples/auth/external-auth/

My curl response does not contain WWW-Authenticate so that the browser never shows up the login popup.

Second step is more technial and i may not understand it completley.
If i authorize mysqlf with
curl https://domain.tld" -u "user:pass"
the information abaout the user does not show up in authelia logs.

At this point i would like to see an example how to paramterize nginx-ingress to put the basic auth credentials into the right header and format.

@micw
Copy link

micw commented Oct 2, 2020

Hello. I just grepped through the code and did not found any occurence of "WWW-Authenticate" which is a central part in http basic authentication (https://en.wikipedia.org/wiki/Basic_access_authentication). It looks like the advertised feature "Support of basic authentication for endpoints protected by single factor." it not implemented yet...

@james-d-elliott
Copy link
Member

We support 1FA via the header Proxy-Authorization. So in your requests if you add that header it should work. I believe the format is this:

Proxy-Authorization: Basic <base64 of "username:password">

Example for username bob, password foo:

Proxy-Authorization: Basic Ym9iOmZvbw==

(where Ym9iOmZvbw== is the base64 of bob:foo)

@tgruenert
Copy link
Author

@james-d-elliott thank you for clarify that. But thats not a complete solution in my case.

I can´t change the behaviour of a third party component. This component support HTTP Basic Auth compareable with
curl https://domain.tld" -u "user:pass"

I don´t see any element in the chain

third-party-client -> Nginx-Ingress -> Protected Backend

which can add the relevant header information to match the requirments of authelia. Would it possible to support Basic Auth also in this style with authelia? Unfortunately i can´t support it with an PR - i am not a developer,

@james-d-elliott
Copy link
Member

I will have to think about an elegant solution. The main issue is supporting HTTP Basic Auth would be easy, other than the fact it would show regular users the browser auth popup dialogue if they were not authenticated rather than the pretty GUI. I can do some testing to see if I can detect the fact the client is offering auth when we do the curl though, if we can we can do this.

We also allow rules to apply to single hosts, which depending on what this third party client is used for may work for you (i.e. daemon/service that queries a website). Additionally some services our users have used utilize an API with an API key, Usually served at domain.tld/api/ which can be bypassed since it's secured via API key (since I don't know what client/service I'm just trying to generate ideas to solve your particular case).

Also if the third party client supports customizing the curl request all you should need to add is -H "Proxy-Authorization: Basic Ym9iOmZvbw==".

@james-d-elliott james-d-elliott added type/feature Request for adding a new feature Help Wanted Issue that we'd really love outside help on. status/needs-design Requires thoughtful design priority/3/medium Medium priority items labels Oct 3, 2020
@micw
Copy link

micw commented Oct 3, 2020

How about creating a new verify endpoint that is dedicated to basic auth (or alternatively a parameter on the existing endpoint like /api/verify?auth=basic)? That one would send a www-authenticate header and accept a Authorization header as answer.

@nightah
Copy link
Member

nightah commented Oct 4, 2020

Just to add context, the reason we choose to allow basic auth against Authelia with the Proxy-Authorization header as opposed Authorization is so that the client can authenticate against Authelia and if required the protected resource too both in one hit.

@micw
Copy link

micw commented Oct 4, 2020

@nightah Thank you for clarification. I think, that's a very valid use case but another one than "simple" basic auth.

@Scapal
Copy link

Scapal commented Oct 8, 2020

Just to add context, the reason we choose to allow basic auth against Authelia with the Proxy-Authorization header as opposed Authorization is so that the client can authenticate against Authelia and if required the protected resource too both in one hit.

@nightah Could that be set as an option in the policies? Most of the time, if we use Authelia for authentication/authorization it is because the web resource itself is not protected.

You currently drive the global behaviour of Authelia, using Proxy-Authorization, around a minority use case. Most of the time we don't want the user to be aware that there is a proxy and that the authentication has to be handled in a different way.

@nightah
Copy link
Member

nightah commented Oct 9, 2020

@Scapal there's obviously a couple different ways this could be addressed.

This specific issue is limited to a Kubernetes deployment with nginx ingress because of the limitations of said instance of nginx.
Obviously if the user isn't using a Kubernetes deployment with any reverse proxy other than Traefik they have full control to submit basic auth via the Authorization header and copy the value of said header to the Proxy-Authorization header.

At a glance @micw's suggestion seems to be a reasonable one, adding either another endpoint or a parameter on the existing.
@james-d-elliott, @clems4ever any thoughts on the @micw's suggestion?

I've got another bug with MSAD that I need to resolve as a priority and not too much spare time available to me at the moment.

If anybody wants to pick this up contributions are definitely welcome!

@ThinkChaos
Copy link
Contributor

I'd like to help move this forward. I don't use k8s, but a client where I can only configure username and password. This client doesn't try to authenticate using basic auth unless it gets a WWW-Authenticate response.

What I'd love to be able to do is specify "basic" as a policy so that Authelia responds with WWW-Authenticate if no Authorization header is provided.
If this sounds like a good solution to you I'd be happy to send a PR 😃

@nightah
Copy link
Member

nightah commented Nov 19, 2020

@ThinkChaos my preference would probably be to go down the path of a query param on /api/verify or a new endpoint for basic auth as opposed to a new policy.

@james-d-elliott any preference from your perspective?

@ThinkChaos
Copy link
Contributor

Adding a param sounds like a bad idea to me because it requires clients to correctly parse out the param, and add it back when they add new segments to the base URL. The client I use fails this, and I think it's a pretty common bug.

I think having a different endpoint is also less elegant than a policy: it requires configuring the reverse proxy to use the correct endpoint depending on the situation which can get complex very quickly. I see this as pushing some auth logic to the reverse-proxy instead of keeping it in authelia.

Here are the advantages of the policy solution as I see it:

  • requires absolutely no client/reverse-proxy changes
  • gets all the powers of rules for free: explicit scope, per user/group, etc.

Being able to use rules would also easily solve the "should authelia present basic auth or pretty HTML" problem: users in the bot group get basic, the rest gets standard.
I honestly believe the param and endpoint solutions don't come close to how easy to use the policy would make this. Can you please explain what advantages you see in those solutions?

@nightah
Copy link
Member

nightah commented Nov 23, 2020

@ThinkChaos we're still discussing this a little further within the team to determine the agreed way forward.

At the moment we are leaning towards a global switch which changes the Proxy-Authorization header to Authorization to authenticate against Authelia and not passing any authentication details to the backend.
This may be revised this to switch it entirely so backend becomes Proxy-Authorization but at the moment this is unlikely.

Having said that, with the limited information available regarding your use case I don't particularly think you fall in the same category as the users that have lodged this issue. Could you not solve your problem as it stands by bypassing authentication from that specific client that you describe?

@ThinkChaos
Copy link
Contributor

(sorry for the delay I thought I had already replied)

I'm not sure I understand what you mean by "bypassing authentication from that specific client".
The client connects over the internet, so if you mean connecting directly to the service behind the reverse-proxy that's not an option for me.
This client is non interactive, and doesn't preemptively authenticate, which is why the WWW-Authenticate response is required.

Thinking about this some more I noticed my policy idea wouldn't actually be a solution for me: as the client doesn't preemptively authenticate, Authelia wouldn't be able to tell what user/group the request belongs to, and thus would be forced to use basic auth for all un-authenticated connections.

If you go ahead with the /api/verify?auth=basic method I can make it work with config changes in my reverse proxy.
Have you decided whether that's what you want to do?

@nightah
Copy link
Member

nightah commented Dec 20, 2020

@ThinkChaos what I mean is specifying a bypass rule for the IP address of your client, if it's a static IP or VPN subnet then this should be simple if the client has a dynamic IP this obviously won't work all that well.

We're going to go down the path of providing a switch to make Authelia expect basic auth details in the Authorization header and disabling Proxy-Authorization.

You're welcome to contribute the change to provide basic auth with a query parameter.

@nightah nightah self-assigned this Dec 21, 2020
@nightah nightah added status/in-progress Work is in progress and removed Help Wanted Issue that we'd really love outside help on. status/needs-design Requires thoughtful design labels Dec 21, 2020
ThinkChaos added a commit to ThinkChaos/authelia that referenced this issue Dec 27, 2020
When `/api/verify` is called with `?auth=basic`, use the standard
Authorization header instead of ProxyAuthorization.
ThinkChaos added a commit to ThinkChaos/authelia that referenced this issue Dec 27, 2020
When `/api/verify` is called with `?auth=basic`, use the standard
Authorization header instead of Proxy-Authorization.
@ThinkChaos
Copy link
Contributor

Yep I can't count on a static IP so that solution is not an option for me.

I just created PR #1563 with the minor changes required for the auth=basic query param.

ThinkChaos added a commit to ThinkChaos/authelia that referenced this issue Dec 29, 2020
When `/api/verify` is called with `?auth=basic`, use the standard
Authorization header instead of Proxy-Authorization.
ThinkChaos added a commit to ThinkChaos/authelia that referenced this issue Dec 29, 2020
When `/api/verify` is called with `?auth=basic`, use the standard
Authorization header instead of Proxy-Authorization.
ThinkChaos added a commit to ThinkChaos/authelia that referenced this issue Dec 29, 2020
When `/api/verify` is called with `?auth=basic`, use the standard
Authorization header instead of Proxy-Authorization.
ThinkChaos added a commit to ThinkChaos/authelia that referenced this issue Jan 21, 2021
When `/api/verify` is called with `?auth=basic`, use the standard
Authorization header instead of Proxy-Authorization.
ThinkChaos added a commit to ThinkChaos/authelia that referenced this issue Jan 21, 2021
When `/api/verify` is called with `?auth=basic`, use the standard
Authorization header instead of Proxy-Authorization.
@james-d-elliott
Copy link
Member

james-d-elliott commented Feb 1, 2021

So upon doing some research for the helm chart into nginx ingress (I use traefik ingress for k8s), there is a actually a fairly undocumented method to configure the ingress that could theoretically provide a solution:

@ThinkChaos @tgruenert @micw

nginxinc/kubernetes-ingress#873

(specifically that you can add completely custom directives to nginx using this method)

nightah pushed a commit to ThinkChaos/authelia that referenced this issue Feb 23, 2021
When `/api/verify` is called with `?auth=basic`, use the standard
Authorization header instead of Proxy-Authorization.
nightah added a commit that referenced this issue Feb 23, 2021
…erify (#1563)

* [FEATURE] Add auth query param to /api/verify (#1353)

When `/api/verify` is called with `?auth=basic`, use the standard
Authorization header instead of Proxy-Authorization.

* [FIX] Better basic auth error reporting

* [FIX] Return 401 when using basic auth instead of redirecting

* [TESTS] Add tests for auth=basic query param

* [DOCS] Mention auth=basic argument and provide nginx example

* docs: add/adjust basic auth query arg docs for proxies

Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
@ThinkChaos
Copy link
Contributor

@nightah could you please fix the typo in this issue's title to make sure this is easily discoverable via a search? :)

@nightah nightah changed the title HTTP Basis Auth not working as expected for nginx-ingress / kubernetes HTTP Basic Auth not working as expected for nginx-ingress / kubernetes Feb 24, 2021
@nightah
Copy link
Member

nightah commented Feb 24, 2021

@ThinkChaos done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority/3/medium Medium priority items status/in-progress Work is in progress type/feature Request for adding a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants