Multiple HTTP Authorization headers?
Asked Answered
I

8

93

Is it possible to include multiple Authorization Headers in an HTTP message? Specifically, I would like to include one of Bearer token type (passing an OAuth access token) and one of Basic type (passing a base64 encoded username:password).

GET /presence/alice HTTP/1.1 
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
Authorization: Basic YXNkZnNhZGZzYWRmOlZLdDVOMVhk

I see no reason this should not be possible, just wanted to vet it with the community to be sure.

Isatin answered 26/3, 2015 at 15:31 Comment(1)
c.f. #3762345Erwin
L
61

**** UPDATE Feb 2021 *** Please read the comments to this response. Their general conclusion seems to be that some web servers accept multiple Authorization schemes, but that it goes against RFC 7230/7235 ****

This should be possible, you just have to add a comma between field values, e.g:

GET /presence/alice HTTP/1.1 
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM, Basic YXNkZnNhZGZzYWRmOlZLdDVOMVhk

This is defined in RFC7230, section 3.2.2, Field Order:

A sender MUST NOT generate multiple header fields with the same field name in a message unless either the entire field value for that header field is defined as a comma-separated list [i.e., #(values)] or the header field is a well-known exception (as noted below).

A recipient MAY combine multiple header fields with the same field name into one "field-name: field-value" pair, without changing the semantics of the message, by appending each subsequent field value to the combined field value in order, separated by a comma. The order in which header fields with the same field name are received is therefore significant to the interpretation of the combined field value; a proxy MUST NOT change the order of these field values when forwarding a message.

I don't know whether all web servers accept this - at the time of writing I'm in the middle of a debate with a colleague about whether it should work or not.

Lambertson answered 21/7, 2016 at 22:3 Comment(10)
The answer, it seems, is no - at least not with Apache 2.4.Rondeau
I think that this should be the accepted answer. Works perfect for me with the comma. Basic auth and JWT.Notification
This seems to solve the OP's problem in the best way.Sensitivity
No. That section is only applicable to the header whose entire field value is defined as a comma-separated list, such as Accept-Encoding header. Authorization header's field value is, however, not defined like that.Preliminary
But isn't the credentials field in the ABNF designed to be comma-separated though @Preliminary ?Lambertson
@Sam Critchley the header has one credentials field, and the credentials field consists of two parts: an auth-scheme and a param/a list of params. Params can be comma separated, but, no, the credentials field in its entirety is not a list. (Credentials being plural does not matter here — it’s a scalar value.)Preliminary
This is a wrong implementation! Refer to the RFC, appendix C: tools.ietf.org/html/rfc7235#appendix-C Authorization is not a comma separated list. If a server accepts it, it's not implementing the protocol per the RFC.Cardinale
@Elie Saad, RFC 7235 says, "Note: Many clients fail to parse a challenge that contains an unknown scheme. A workaround for this problem is to list well-supported schemes (such as "basic") first." This means the header can contain multiple challenges. Each challenge is separated by commas, and each can have a comma separated list of parameters. Each parameter will have an equals sign (=) in it, while a new challenge will begin with the scheme, which doesn't have an equals sign in it.Dis
@Dis It is a note for the WWW-Authenticate and Proxy-Authenticate headers. They can contain multiple challenges, but the Authorization header can contain only one scheme.Preliminary
@Preliminary You are correct. Thank you for the clarification.Dis
E
42

No, it's not possible. See the syntax definition in http://greenbytes.de/tech/webdav/rfc7235.html#header.authorization

Etch answered 26/3, 2015 at 21:11 Comment(4)
Whilst I ought to believe you since I know who you are, what you say it at odds with the spec: "When creating their values, the user agent ought to do so by selecting the challenge with what it considers to be the most secure auth-scheme that it understands, obtaining credentials from the user as appropriate." — Specifically, 1) "ought", 2) token68 excludes "," meaning a comma won't be interpreted as part of a token, and 3) There's nothing in the spec to say multiple Auth. headers can't be provided i.e. 2 headers CRLF-separated. See also github.com/nickstenning/nginx-multiauthErwin
You can only use multiple header fields when they are defined using list syntax; see greenbytes.de/tech/webdav/rfc7230.html#rfc.section.3.2.2.p.2Etch
@JulianReschke can we set a first authorization header that would contain the basic auth, and set a second authorization header that would contain the bearer auth, in the same request?Isochronal
No, that would be invalid syntax.Etch
C
12

I had a similar question. It seems to be a quite common issue (Link to question). I ended up with changing the authorization header for the bearer token to a non standard one like

X-Auth:Bearer mF_9.B5f-4.1JqM

This way it is just another HTTP header and the basic http authorization will pass. If you are developing your own API this should be no problem.

Some further research

Based on the RFC 2617 here are some interesting details.

The user agent MUST choose to use one of the challenges with the strongest auth-scheme it understands and request credentials from the user based upon that challenge.

Note that many browsers will only recognize Basic and will require that it be the first auth-scheme presented. Servers should only include Basic if it is minimally acceptable.

Cranwell answered 2/9, 2015 at 10:11 Comment(1)
RFC 2617 is irrelevant nowadays. You need to check RFC 7235.Etch
T
2

If you are using python in backend then you can simply pass dict in bearer and before processing it in backend do json.loads

This way you can pass multiple values in one authorisation header

Example: Pass {"access_token" : access_token, "app_id" : 2}

backend json.loads("{"access_token" : access_token, "app_id" : 2}")

Tressietressure answered 29/6, 2021 at 9:5 Comment(0)
B
1

Header fields are key/value pairs. So as long as they are unique and you/programmers know who is who, this is fine. For example:

AuthorizationBearer: Bearer mF_9.B5f-4.1JqM
AuthorizationBasic: Basic YXNkZnNhZGZzYWRmOlZLdDVOMVhk

When my Angular interceptor sends Authorization111: Bearer xyz123 to Node API, API will extract the token value as

// you can do more validation here, i.e, length
var token = header.headers["authorization111"].toString().split(' ')[1];  
Bellanca answered 10/6, 2021 at 4:45 Comment(3)
I think this is a great answer, however I would have a condition ensuring there is a white space in the value, otherwise the server will spit out a logic error.Sil
@FiddleFreak Can you explain details?Bellanca
I would stop right at the const arrAuthHeader = req.get('Authorization').split(" ");, then check the variable with two if conditions > if (!arrAuthHeader) and if(arrAuthHeader.length < 2). So you can properly throw errors. Then you just do the assignments const bearer = arrAuthHeader[0]; and const token = arrAuthHeader[1];Sil
N
1

While comma separated values within the Authorization are technically the best solution, as a last stand you could try to prepend the plain user credentials as part of the url with the httpClient of your choice and sending the Bearer Header with it. This only works with Basic authorization, but it may work if nothing else does:

https://myUsername:[email protected]/presence/alice

Since the password is used in Plaintext here, this is only for the sense of completeness not the recommended way to go.

Nolen answered 1/9, 2023 at 20:17 Comment(0)
P
0

I can't speak for whether or not it's a good idea have multiple auth headers. I've done it in unit tests in order to check handling of requests with multiple auth headers, this is how I did it:

var headerValues = new[] { $"Basic {basicToken}", $"Bearer {bearerToken}" };
var context = new DefaultHttpContext();
context.Request.Headers.Append("Authorization", new StringValues(headerValues));

This will yield one auth header with two values that can be accessed.

Pelpel answered 26/4, 2024 at 10:45 Comment(0)
P
-2

It is Possible to have mulitple Authorization Headers, I have gone through the same problem during integrating API which is accepting multiple authorizations.

Here is React js example for calling an API which is accepting multiple auth tokens.

axios.get(Constants.API+Constants.GET_USER,  {  headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
"Authorization": Constants.AUTH_Element + ',' + Constants.AUTH_ORG + ','+ 
Constants.AUTH_USER
}})
.then(function (response) {
    // handle success
    console.log(response);
})
.catch(function (error) {
    // handle error
    console.log(error);
})
.finally(function () {
    // always executed
});
Primal answered 5/6, 2019 at 8:49 Comment(1)
The question is which API?Shayneshays

© 2022 - 2025 — McMap. All rights reserved.