Multiple Authorization and Custom Headers


#1

Hello folks! I’m in serious doubts about this I just wanna know your thoughts about it.

I currently finishing my API and is about ready to go to production, the thing is I’m kinda in doubt about the Authorization Schema I should use.

I not using OAuth in my Application and for now I don’t in need for it.

API Access - Q1

My Users needs an private token ( passed in Header ) and a public token ( passed in url ) to proceed into the resource.

Example:

curl -H Authorization-Custom: "Token" mything.com/api/{public_key}/something

For now I using an Custom Header to do the Authorization but reading some articles I started to see it as a bad practice.

My Authetication Header:

Authorization-Custom: < Token >

What people call a Good Practise:

Authorization: Bearer < Token >

The thing is that sometimes I need to use Authorization Basic together with the Bearer and fetching its values is quite a pain than Authorization-Custom and Authorization Basic.

Should I quit using my own Authorization header and use the one predicted in the HTTP Protocols ?

Authorization: < type > < token >

In terms of Slim:

// Value from Header ( Private Token )
// Easily ready for querying and stuff.

$token = $request->getHeaderLine('Authorization-Custom)'

// If there's more than one Header with this name this'll return an String comma separated.
// What would lead me to unnecessary work exploding it twice, because there's an Basic and Bearer before the Token.

$authHeader = $request->getHeaderLine('Authorization);

Problem when using both - Q2

I’ve noticed that when the Request comes with two Headers with the same Key ( Like the example above ) using $request->getHeaders() leads to an Exception.

Example:

Request:

curl -H “Authorization: Basic < CREDENTIALS >” -H “Authorization: Bearer < ACCESS_TOKEN >” example.com/api/EndpointAnywhere

Code:

$headers = $request->getHeaders();

return $response->withJson($headers);

After doing that an RunTimeException is throwed:

Uncaught RuntimeException: Malformed UTF-8 characters, possibly incorrectly encoded in...

Conclusion:

Should I stay with my Custom Headers pattern ? ( Authorization-Custom: < Token > ) and what would be causing the RunTimeException ?

Give me your thoughts and advices about this ! I seeking more opinions about Q1 thought.

Obs: All requests are trough SSL. So either way they are safe. ( Or should be ).

Obs2: Don’t mind the Authorization-X header name I would put something that would make more sense.

Thanks,
LosLobos


#2

Q1

The header names don’t really matter that much. Yes, Authorization is the canonical header for sending authentication data to the server, but as you already figured out you can do pretty much what you want in the backend. It might be worthy to strive to conform to the standards if the API is meant to be used by third parties, though. (as per the “principle of less surprise”)

Q2

That error is to be expected, the HTTP specification does not allow for multiple headers with the same name†. However it allows for multiple values on the same header, separated by commas. You prolly seen this before:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-US,en;q=0.8,es;q=0.6,fr;q=0.4,ca;q=0.2,pt;q=0.2

in Slim, $request->getHeader('Accept-Encoding); would give you array(‘gzip’, ‘deflate’, ‘sdch’, ‘br’). So what you could actually do is:

Authorization: <type> <token>(, <type> <token>)*

PD a minor gripe I have with your scheme is that the “private” token is as public as the other one, as both go in the request. But of course I don’t have any more information, these names might make sense in another context that I don’t know of.

† only one exception to this rule comes to mind: an HTTP response may have multiple Set-Cookie headers.


#3

That was my principal concern, using something that Users are not used to can cause confusion. I’ll try to stick with the standards if I can, not sure if it’ll be the best option.

The Private Key is not public as its passed in the Header on an HTTPS Request and its not visible in the sending packet. ( That what private key means to my system )