Why do I need to follow the OAuth spec/guidelines? - oauth

I feel silly even asking this question, but am at the limits of my understanding, and am hoping someone can provide some context.
I'm looking at the following (https://stormpath.com/blog/token-auth-for-java/) which states:
The access_token is what will be used by the browser in subsequent requests... The Authorization header is a standard header. No custom headers are required to use OAuth2. Rather than the type being Basic, in this case the type is Bearer. The access token is included directly after the Bearer keyword.
I'm in the process of building a website, for which I'll be coding both the back-end REST service, as well as the front-end browser client. Given this context, why do I need to follow any of the guidelines given above? Instead of using the access_token, Authorization and Bearer keywords, what's stopping me from using any keywords I like, or skipping the Bearer keyword entirely in the header? After all, as long as the front-end and back-end services both read/write the data in a consistent manner, shouldn't everything work fine?
Are the keywords and guidelines given above merely best-practice suggestions, to help others better understand your code/service? Are they analogous to coding-styles? Or is there any functional impact in not following the above guidelines?

Given this context, why do I need to follow any of the guidelines given above?
Because they are standardized specifications that everyone is meant to conform to if they want to interact with each other.
Instead of using the access_token, Authorization and Bearer keywords, what's stopping me from using any keywords I like, or skipping the Bearer keyword entirely in the header?
Nothing, except that it won't be OAuth anymore. It will be something custom that you created for yourself that noone else will understand how to use, unless you publish your own spec for it.
After all, as long as the front-end and back-end services both read/write the data in a consistent manner, shouldn't everything work fine?
Who is to say that you alone will ever write the only front-end? Or that the back-end will never move to another platform? Don't limit yourself to making something custom when there are open standards for this kind of stuff.
Are the keywords and guidelines given above merely best-practice suggestions, to help others better understand your code/service?
No. They are required protocol elements that help the client and server talk to each other in a standardized manner.
Authorization is a standard HTTP header used for authentication. It has a type so the client can specify what kind of authentication scheme it is using (Basic vs NTLM vs Bearer, etc). It is important for the client to specify the correct scheme being used, and for the server to handle only the schemes it recognizes.
Bearer is the type of authentication that OAuth uses in the Authorization header. access_token is a parameter of OAuth's Bearer authentication.
If you use the Authorization header (which you should), you must specify a type, as required by RFCs 2616 and 2617:
Authorization = "Authorization" ":" credentials
credentials = auth-scheme #auth-param
auth-scheme = token
auth-param = token "=" ( token | quoted-string )
So, in this case, Bearer is the auth-scheme and access_token is an auth-param.
Are they analogous to coding-styles?
No.
Or is there any functional impact in not following the above guidelines?
Yes. A client using your custom authentication system will not be able to authenticate on any server that follows the established specifications. Your server will not be able to authenticate any client that does not use your custom authentication system.

Related

Custom authorization via HTTP headers in Ruby on Rails

I have 2 internal Rails services, which need to speak to each other.
I need an advice how to make it secure enough and with minimum effort.
Currently service A sends Authorization HTTP header to service B, which contains secret token. Simple HTTP Token-based method, nothing special. But I also need somehow to communicate a user token, so service B will know, which user is talking to it.
My current solution is following:
send Authorization Token token=blabla user_token=blabla2
use existing in Rails methods to parse it
identify user by provided user_token
inspired by this StackOverflow post
Alternatives:
Amazon way with something like: Authorization: MY-APP-V1 Token=blabla Credential=user_token, but I need custom parser for it.
Custom HTTP header like X-USER-TOKEN, but seems like RFC is not in favor of this idea.
Your proposal or suggestion
Thank you very much for any help.
I'm curious as to why the user token is not enough, can you elaborate on this?
But assuming you want to continue with the double-token approach, something like JWT could be used to encode the user token with the secret token. That way you will just have 1 token and can send it simply as Authorization: Bearer xxxxxx.

WWW-Authenticate schemes for OpenID Connect

I'm writing my own codes for the OpenID Connect protocol. Basically, I intend to write my own provider and related stuff on Google App Engine's platform using Jersey and Google's datastore via Objectify library.
I'm in the middle of implementing the (access/refresh) token endpoint and there's this client authentication that I need to take care of. I'm just wondering if there are preset authentication schemes' keywords that I could send if in case the client did not have client_secret_basic set during the registration process (or whatever's set in the datastore entry.)
For a failed client authentication with the following methods, the scheme is used as response in the WWW-Authenticate header (401):
client_secret_basic: Basic,
client_secret_post: ???,
client_secret_jwt: ???,
private_key_jwt: ???,
none: obviously none.
I've looked at some open source implementations, nimbus' and OAuth-Apis', but they don't seem to handle this minor issue (they only respond with the generic error response defined in OAuth2 rfc6749#section-5.2.)
If there are no predefined keywords, then I suppose I'll have to make up my own. But it would be great if they exist.
The authoritative list for these is at IANA. There, you can find these handfuls:
Basic
Bearer
Digest
HOBA
Mutual
Negotiate
OAuth
SCRAM-SHA1
SCRAM-SHA-256
vapid
Which of these is client_secret_post, client_secret_jwt and private_key_jwt? None. You'll need to map those to one from the registered list above or return your own values. Better yet, you can submit a draft to the OAuth working group or the OpenID Foundation to get the above IANA registry updated with something that makes sense for these missing cases. Then, we can all interop :-)

Recommended design for OTP/2FA support in OAuth2

I'm trying to add OTP/2FA support into OAuth2, but after much reading through the RFC6749, it's still not clear how OTP/2FA could be cleanly added without violating the specification.
Although OTP/2FA entry can be added into the authorize dialog flow, there is no provision for adding it into token. For example, public client apps with Resource owner password-based privileges may want to provide the token directly when requesting a new access_token, rather than having to embed a HTML dialog box.
Therefore my questions are;
Does the RFC allow for custom grant_type? Should this be used to provide 2FA/OTP functionality?
Does the RFC allow for additional attributes on an existing grant_type? For example, grant_type=token&otp_code=1234 (RFC does not make it clear if additional attributes are allowed on grant_type's within the specification)
Should OTP functionality be placed into headers? This is the approach that Github used, but it feels really ugly/hacky.
Are there any other approaches that I have overlooked?
Thank you in advance
The RFC allows for an extension (custom) grant, see section https://www.rfc-editor.org/rfc/rfc6749#section-8.3. That grant could define additional attributes.
OAuth 2.0 does not define how the Resource Owner authenticates to the Authorization Server, with the exception of the Resource Owner Password Credentials grant. Your proposal could be designed as an extended variant of that grant.
I'm working on something similar. I've got an endpoint at which you can request certain metadata for a user such as whether or not 2fa / mfa / otp is turned on and the salt (and iterations and algorithm) for Proof of Secret / Secure Remote Password.
If you go that route you can simply extend the grant types with an mfa or totp field (that's what I'm doing). You could also create a custom grant type as mentioned above (perhaps more proper).
Another solution is to check for MFA / 2FA / OTP during the authorization dialog step.
If I were done with my OAuth2 implementation I'd link you to that code too, but here are some libraries for an Authenticator:
Browser Authenticator has the components you need to generate and verify a key and token in the browser: https://git.coolaj86.com/coolaj86/browser-authenticator.js
Node Authenticator has the complementary server-side code: https://git.coolaj86.com/coolaj86/node-authenticator.js
You would still need to provide your own database storage mechanism and link it in to your OAuth implementation or you could make a very simple one and run it as a microservice.
I agree with Hanz Z.: you can design your own grant type to consume OTP.
But OTP can also be used for client authentication (confidential clients as you have to store credentials).
For example, we could imagine an header in the token request (X-OAuth2-OTP = 01234567). Client authentification will fail if the client activated OTP but no header is set.
Based on specifc SCOPE (Ex. OTP) you can mark bearer(access_token) as ""verified_otp = false"" on the backend, then after authorization server received valid otp for that session mark your bearer(access_token) as ""verified_otk = true"". For your resource server, check verified_otk field befores authorize calls that depends this verification.

Rails security concerns with Authorization token in header for API

I'm building an API and I want every request to contain a token. I found a pretty simple way to do this, but I am wondering if I'm missing any security implications.
The way I'm currently doing it is using authenticate_or_request_with_http_token. I use that to check the token within the header combined with the user's email within a request. If both are legitimate -- then go through with the request.
I am also enforcing https on every request. Is this enough for a secure app? If somebody intercepts the request they can just take the params and the headers and make requests on behalf of a user, but I figured that ssl should encode everything properly. Am I completely misunderstanding ssl as well as the rest of the way I built it?
I think you are basically right.
But the most secure way to do API auth is with something like hmac, where the token is actually generated specific to the specific request and the time, so even if someone does see the URL, they still can't even use it to replay the same API request, let alone make other requests.
http://rc3.org/2011/12/02/using-hmac-to-authenticate-web-service-requests/
For instance, Amazon uses an HMAC-based approach to their API's.
But I think your analysis is correct that in general, if you enforce https, nobody ought to be able to see the pass token clients include in the request. I can't explain why people use HMAC instead; maybe just because there are so so many things that can go wrong and lead to someone seeing the token even in request headers. Including several kinds of man-in-the-middle attacks which ought not to be possible, but if a slip-up somewhere else makes one possible, the HMAC-based approach will still, for instance, prevent a man-in-the-middle from modifying the request the client meant to send, before it reaches the server.
There is HMAC built into the ruby stdlib. Digest::HMAC in the stdlib tells you to use OpenSSL::HMAC instead, but OpenSSL::HMAC contains no docs at all, and Digest::HMAC at least includes some bare bones examples docs. It would be nice to have better docs, but together with the overview of HMAC linked above, you can probably figure out how to use the stdlib ruby hmac to implement your auth pretty easily. It does put a higher burden on the client though, to find an HMAC library in the language of their choice, and implement the hmac auth to your app's specifications (there are a couple choices in how you might incorporate hmac into actual auth flow).

SOA - Authentication Service design

I'm designing a Service Oriented Architecture, and I also do need an authentication service in order to recognize clients and allow them to access resources.
Actually I found two possible solutions:
sign each single request using a pubkey and privatekey
token-based authentication using pubkey and privatekey
I'm not assuming an oauth2 service since it would add too many overhead designing the system for my needs, instead I do prefer to adopt a simpler (but also strong) authentication solution.
So here I come with my AuthenticationService, that can either be queried by the client making the API request (obtaining a token to pass alongside the request) or be queried by each single API endpoint to perform a reverse check of the HMAC that signed the request to see if it matches (checking if the private key used to produce the HMAC was valid).
I can see the latest to be simpler for the final developer performing several operations, but it would also require more checks to validate the token and handle it's expiration...
What potential security issues could the token solution raise that the single-request HMAC doesn't? What do you prefer and, possibly, why?
At the end I finally designed an authentication service based on the same Amazon solution.
It requires users to sign each request using the private key. So the request will send an Authorization header with the value "PUBKEY:SIGNATURE", where the signature is a HMAC composed of any request data (it could be the request body itself) plus a timestamp, to be passed inside the Date header. This implementation is strong enough to avoid MITM and replay attacks.
For more info about this solution here is a great explanation that helped me a lot to understand the real implementation.
Hope this really help someone else in the world facing the same problem.

Resources