Standard HTTP header to indicate location of OpenID Connect server? - http

We're developing a native application that accesses content on a resource server (which is also under our control). The resource server will require the user of the native app to authenticate by OpenID Connect to get an access key which is passed as a bearer token (RFC 6750). The authorization server is a separate server running Keycloak.
I'd like to avoid hard-coding information into the client software about the address of the authorization server. Instead, I'd like the resource server to provide the link to the auth server's provider discovery endpoint, possibly as part of the HTTP 401 challenge. I could just invent an X-MyApp-* header, but I was wondering if there is an established convention for this (whether an HTTP header, body content in the 401 response, a standard URL on the resource server etc)?

RFC6750 define the usage of WWW-Authenticate Response Header.
Section 3 of the spec define follow,
If the protected resource request does not include authentication
credentials or does not contain an access token that enables access
to the protected resource, the resource server MUST include the HTTP
"WWW-Authenticate" response
You may utilise this header to respond back the address of the authorization server. Specification allows to have attributes other than the ones defined by specification,
All challenges defined by this specification MUST use the auth-scheme
value "Bearer". This scheme MUST be followed by one or more
auth-param values. The auth-param attributes used or defined by this
specification are as follows. Other auth-param attributes MAY be
used as well.
Now if we can define a custom attribute named auth_server, then we can add it to 401 response's WWW-Authenticate header as below
WWW-Authenticate: Bearer realm="example", auth_server="URL-TO-OIDC-SERVER"
Your client must parse the header and extract the auth_server value .

Related

Does HTTP protocol facilitate for specification of URI(s) associated with an authentication realm?

As a preface I'd like to claim I have some understanding of how the HTTP-supported authentication is supposed to work according to RFC 7235.
I am specifically interested to know how a client is supposed to know, after authenticating, which URIs on the server it is expected to provide same authorization (through the Authorization header) bearer for? Furthermore, is there any provision by HTTP to assist client in determining which Authorization headers it (the client) may have available (through whatever means it acquires them -- "login" form/dialog etc), would go with which realm(s)?
A realm doesn't seem to be specified in the form of an URI or even a regular expression of an URI, it's a value the interpretation of which appears to be left to the HTTP client application. Of note, a "Protection Space (Realm)" is defined, quoting:
A protection space is defined by the canonical root URI (the scheme and authority components of the effective request URI (see Section 5.5 of RFC7230) of the server being accessed, in combination with the realm value if present.
The above is all well and good, but it doesn't facilitate client mapping realms to URIs that may require authorization.
Say my Web server returns a response with status code 401 and the WWW-Authenticate: Bearer realm="The hangout" header line, for a request with a given URI, let's say /foobar. That makes it obvious that subsequent requests to the particular URI must include Authorization header line corresponding to solved challenge (as the client authenticates the user). No problem there. But what about e.g. requests with URI(s) that have the same pathname - those starting with /foobar/ -- is there an implication here that the same Authorization value is expected for these as well? What about entirely unrelated URI pathnames [on the same server]?
It would seem beneficial for the kind of authorization negotiation HTTP already does, to somehow relate or facilitate said relation of realms to URIs. But maybe I am missing something very obvious. Does HTTP do something along of what I am describing? Does it facilitate it in any way, at least, beyond leaving it entirely to the application? How would one realistically let the client determine which authorization bearer to send for which requests? Must it always get a 401 and a challenge response first, before knowing for sure requests to the particular URI and only said URI, must include related authorization bearer?
HTTP is a stateless protocol that deals with a request-response pair. The protocol does not deal with any information that would describe the concept of a "page", "site", "application", etc. Even though it deals with hypermedia, the protocol itself doesn't go beyond the concrete request. This means that you won't get any information from the protocol itself about any other paths under the same domain that are in the same authentication realm. This is left to the documentation of APIs or websites.
It seems to me that your research is centered on one type of authentication process that we call basic auth, know they are some other ways to authenticate a user and that they might suits your needs better as basic auth is kinda old as you can see on that RFC you linked.
To my understanding, the principle behind basic auth is to have a simple process based on challenges. When your client asks for a resource and that resource is protected by authentication, the server responds with a challenge : 401 Unauthorized with a header WWW-authenticate: Basic realm="some realm". The client then know the resource is restricted and depending on the realm, knows if it can have access (or asks the user for credentials for that realm), and try to access with a basic auth header : Authorization: Basic viFWGrwehryfviehtNRBRGWrwGERThRGE. You then repeat that process every time you need a resource.
HTTP and basic auth don't implement any sort of deeper and more complex system for authentication like you're searching for. It's one of the simplest system as its name implies and has not a lot more to offer. I'd even add that it's one of the riskier way to authenticate a system (even using SSL cert and cert pinning) as the client must send credentials for every single authenticated resource request.
In case you want to search other ways to authenticate requests, here are some :
OAuth (2.0) (most secured and complex)
Bearer (JWT or session tokens)
API keys

What to do with headers on following HTTP 303

I'm trying to determine what a client should do with headers on receiving a 303 (See Other) from the server. Specifically, what should be done with the Authorization header that was sent on the initial request?
Here's the problem: the client makes a request to myserver.com (HTTP request method is not relevant here) and the server at myserver.com responds with a 303 and the Location header contains otherserver.com/some_resource/. Tools like Postman and curl will follow the redirect by passing all the same headers in the subsequent request to otherserver.com. I haven't found a way to make these tools drop the headers.
In the case I've described, sending the Authorization header to otherserver.com seems like a security risk: otherserver.com now knows my token and possibly what host it can be used on so now the token is compromised. This can also cause errors, depending on how the destination host is configured. In the case where the redirect is to another resources on the same host (ie, myserver.com) then the Authorization header will (probably) need to be sent, and because it's the same host nothing is compromised.
Effectively, in different situations it seems that the correct behaviour is different. The relevant section in the RFC does not address this issue. In developing my own API, I've written documentation telling API clients to drop the Authorization header on redirect to otherserver.com. However, based on mucking around with curl and Postman, it's not clear to me either (a) what the default behaviour is for a typical HTTP client library or (b) whether HTTP client libraries permit easy modification of the HTTP headers before following a 303 redirect. As a result, it's possible my suggestion isn't practical. I also know of no way for the server to instruct the client as to what it should do with headers on following the 303 redirect.
What should a HTTP client do with the headers when it follows a 303 redirect? Who is responsible for deciding whether to use the same headers on the redirect, the HTTP client or server?
You can argue that when sending the 303 with otherserver.com's Location, myserver.com trusted otherserver.com to handle your token. It could have sent the token in the background as well. From the client's perspective, the client trusts myserver.com to handle the token, store and verify it securely, etc. If myserver.com decides to send it on to otherserver.com, should the client override? In this case it can of course, but in general I don't think it should.
As an attacker does not control the response headers from myserver.com which is a legit resource, I think in general it is secure to send the token by default to the other server it specifies, maybe unless you have some good reason not to (say an explicit policy on the client).

Http basic authentication mechanism

After the user requests a protected resource X the server responds
with code 401.
The browser prompts the user to inser user-name and
password and automatically re-send the request to the server with
those authentication information
My question is : is this process repeated over and over for each protected resource ?
Look at RFC 2617. There is stated for basic-athentication :
Upon receipt of an unauthorized request for a URI within the
protection space, the origin server MAY respond with a challenge ...
and also
A client SHOULD assume that all paths at or deeper than the depth of
the last symbolic element in the path field of the Request-URI also
are within the protection space specified by the Basic realm value of
the current challenge. A client MAY preemptively send the
corresponding Authorization header with requests for resources in
that space without receipt of another challenge from the server.
Similarly, when a client sends a request to a proxy, it may reuse a
userid and password in the Proxy-Authorization header field without
receiving another challenge from the proxy server.
So, from the server side this may occur at any request the the server deems unauthenticated. If resource Y does not share the prefix that had been yuthenticated with resource X then the server will re-request authentication.
For avoiding this the authentication scheme e.g. could request authentication for a common prefix of the related resources , such that authentication for prefix of resource X also covers resource Y as a prefix. This will allow the client to send the authentication header and cause the server to detect the call as already being authenticated.
Once the user input the password, the browser will remember it.
each time the client request the resource at the same website, the browser will send the authentication header automatically.

http authorization not sent for resources on page?

I'm successfully setting up an HTTP Digest Authorization between the web browser and the server. But some of the resources on the same page to the same host are failing because the browser isn't sending the authorization for them.
For example,
Page https://myhost/A/B/C/D/E/ is loaded, browser sends Authorization header.
Page contains IMG ref to https://myhost/A/B/C/D/E/F.JPG, browser sends Authorization header.
Page also contains IMG ref to https://myhost/A/B.JPG, but for some reason browser does not send Authorization header. Server returns 401 Unauthorized but browser does not retry with authorization or pop up a username/password field, it simply displays the "broken image" icon.
I have looked a bit at how HTTP Authorization and I don't see anything mentioned regarding the scope of a request. Nevertheless, because I am explicitly sending back a 401 if the browser doesn't send Authorization for a request, I would expect it should work.
How can I fix this problem?
HTML authorization is governed by RFC 2617, which in section 1.2 says:
The realm value (case-sensitive), in combination with the canonical
root URL (the absoluteURI for the server whose abs_path is empty; see
section 5.1.2 of [2]) of the server being accessed, defines the
protection space.”. Later in the same section it says: “The protection
space determines the domain over which credentials can be
automatically applied. If a prior request has been authorized, the
same credentials MAY be reused for all other requests within that
protection space for a period of time determined by the authentication
scheme, parameters, and/or user preference.
So as long as the two URLS are in the same "protection space" the browser is supposed to resend the same credentials. However in this case the problem is that they are not. If authorization occurs in the https://myhost/A/B/C/D/E/ space, then the browser may not see a need to send authorization for https://myhost/A/B.JPG.
Section 2 mentions:
A client SHOULD assume that all paths at or deeper than the depth of
the last symbolic element in the path field of the Request-URI also
are within the protection space specified by the Basic realm value of
the current challenge. A client MAY preemptively send the
corresponding Authorization header with requests for resources in that
space without receipt of another challenge from the server.
So the solution is to make sure that the WWW-Authenticate header sent by the server sends a domain=/ entry, so that everything under that will be considered in the same protection space.

Should HTTP Client parse HTTP Headers in response with the error 404 Not Found

I cannot find any RFC or Standard of HTTP client behavior in case it gets HTTP response with an error 4xx. I know the 401, 407 are the examples when the HTTP headers are parsed, but...
I have the concrete problem for OPTIONS method (HTTP1.1). The server responses 401 Unauthorized, so client tries to authenticate and re-sends the request with an authentication. After that the response has the error 404 Not Found and HTTP header is filled with Set-Cookie HTTP Header. The client use Apache Java HTTPClient/HTTPComponents, which ignores HTTP headers in case of an error in the response.
Should this HTTP Header be accepted by the client? I believe it should not be, but I cannot find the supportive quotation in the RFC.
RFC 2616 does not specify that any headers should be ignored, not for 404 responses and not for 4xx responses in general either.
RFC 6265 allows clients to ignore Set-Cookie headers, but does not specify situations where that might happen; a single example is given, that does not cover your case:
the user agent might wish to block responses to "third-party" requests
from setting cookies
In your case, since your server seems to use HTTP basic access authentication, it does not seem to concern the Set-Cookie header. In HTTP basic authentication, the Authorization header is sent by the client with every request, so there should be no need to keep state in a cookie.
It is not clear from your question if you have a very specific HTTP server that you're talking to, or if you are implementing a general HTTP client that is supposed to work with whatever server you throw it at. If you have such a specific case that the HTTP server you work with sends state with 404 responses, and you're required to honor that state in order to communicate with the server, and you have no control over the server, then it does not matter what the standard says; you will honor the state sent, or you will not be able to talk to the server.
If, on the other hand, you're implementing a general client and need it to work regardless of the remote server, then your best bet is to stick to RFC 1958:
Be strict when sending and tolerant when receiving.
Implementations must follow specifications precisely when sending to
the network, and tolerate faulty input from the network. When in
doubt, discard faulty input silently, without returning an error
message unless this is required by the specification.
Which, to me, would mean that you should honor the full response received, regardless of the status code, unless you have an objective reason making it impossible for you to do so. I don't see a reason to ignore the state, even if it violates the standard (or in this case, your personal perception of the standard, since it does not say anything about accepting or ignoring the state).
Update: RFC 2617 (HTTP Authentication) states:
A client SHOULD assume that all paths at or deeper than the depth of
the last symbolic element in the path field of the Request-URI also
are within the protection space specified by the Basic realm value of
the current challenge. A client MAY preemptively send the
corresponding Authorization header with requests for resources in
that space without receipt of another challenge from the server.
It is highly inconsistent if the server expects HTTP authentication for one URL, but does not honor it for URLs beneath it, requiring a separate cookie-based authentication for them. If anything should be changed in your server implementation, it should be to harmonize the authentication scheme for all resources.

Resources