Custom Authorization Header

Igor Morse picture Igor Morse · Mar 3, 2017 · Viewed 12.6k times · Source

I know there is enough content for this question on the Stack Overflow but my subject is not the same as the others. ( Kinda the same but not equal )

I want to hear the community thoughts of what I doing and to see if I can improve somewhere or not.

I'm currently using BASIC Authorization for my login EndPoint as it doesn't require complexity and its over https so its fine the way it is.

Example:

GET - /api/login

Authorization : Basic BASE64String(username:password)

Some of my EndPoints require Tokens to be granted access to the resource. These Tokens I'm sending trough Headers and Https-Secured.

The thing is I'm not using a conventional method of doing these Authorizations. Some examples below:

Example 1:

GET - /api/hardware/{PUBLIC_TOKEN}/getMe

Authorization-Hardware : PRIVATE_TOKEN

This EndPoint doesn't require the Authorization-Hardware Header, but if included more things are done by the API. ( Not relevant here )

Example 2:

GET - /api/login/{id}

Authorization-Person : USER_TOKEN

This EndPoint otherwise is necessary including the Authorization-Person Header with the User Token to access the resource. ( Note that how the Token is generated is irrelevant here )

To access the API EndPoints an HTTPS request is necessary.

I gave arbitrary names to the Custom Headers and EndPoints above just to give a picture of what my Authorization Schema is, the names doesn't match the original ones. So don't bother the names just foccus on the schema.

My question is: Not following the convetional way is such a bad thing ? Creating Custom Authorization Headers is bad somehow ( if it is why ? ).

I find this way simpler to give Authorization and a secure way of passing tokens, all these Tokens can be re-generated in the platform again.

Lots of devices and a Mobile Application is already using this Schema, but its all under Development Environment and its not in Production yet. My fear is that this non-conventional way of doing this can affect users of the API in the future. Hope the community thoughts can help me to improve this.

EDIT: 26/03/2017

I would like to know if it would be better and why implementing in the way that is described in the protocol, as its harder to fetch from the Headers when multiple Authorizations is required than when you have a Custom Header and wants to retrieve its value.

Following the Protocol you should use Authorization Header like this:

Authorization: <type> <value>

Example:

GET - /api/login/{id}

Authorization : User USER_TOKEN

But I just can't see what I gain following this, because when fetching its value would come a String or in the example case it would return User Token.

Using an Custom Header its way easier validating the Token. Multiple Authorizations can give a headache too following the protocol way.

Answer

robbat2 picture robbat2 · Apr 2, 2017

TL;DR Some header names such as Authorization have special rules about caching as well as proxy & client handling; your custom header names would not get the special behavior unless you modified every single proxy & client.

The point of using the common Authorization: <type> <value> header as defined in RFC7234 is mostly to ensure that clients & HTTP proxies that natively implement handling of those headers behave CORRECTLY.

Section 4.2 of RFC7234 says:

A proxy forwarding a request MUST NOT modify any Authorization fields in that request. See Section 3.2 of [RFC7234] for details of and requirements pertaining to handling of the Authorization field by HTTP caches.

The Proxy may modify, omit, log or cache your other Authorization-* headers.

RFC7234, section 3.2 says that requests/responses Authorization header MUST not be cached (except in specific circumstances).

RFC7235, section 5.1.2, point 7 furthermore has this say to about NEW authentication schemes that use headers other than Authorization:

Therefore, new authentication schemes that choose not to carry credentials in the Authorization header field (e.g., using a newly defined header field) will need to explicitly disallow caching, by mandating the use of either Cache-Control request directives (e.g., "no-store", Section 5.2.1.5 of [RFC7234]) or response directives (e.g., "private").

So what should you do...? If you controller both ends of the system entirely, it's not unreasonable to define a new type value that might have multiple parameters to cover any combination of one or more token types, just avoiding the , character:

Authorization: MyAuth User=USER_TOKEN/Hardware=HWTOKEN/Person=PERSONTOKEN/Basic=...

The alternative depends on server & client implementations more, and would be using a , as the alternate version list form of multiple headers:

Authorization: User USER_TOKEN, Hardware=HWTOKEN, Person=PERSONTOKEN, Basic=...

Which depending on the server & client, may be treated the same as:

Authorization: User USER_TOKEN
Authorization: Hardware HWTOKEN
Authorization: Person PERSONTOKEN
Authorization: Basic ...

The problem here is "MAY" (lots of added emphasis) be treated the same. There's discussions suggestion that various versions of Apache & NGINX don't treat this consistently, and that the older HTTP RFCs are very unclear about the intended behavior.