Custom authorization via HTTP headers in Ruby on Rails - 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.

Related

Why does JWT need to be sent as a Bearer Token header?

I am adding JWT Auth for a completely new frontend to a legacy Rails backend.
Upon HTTP request, it seems most sources suggest I send the token back to the server via Bearer Header.
Why? What is the additional value of sending via header (bearer or basic). What can't I simply pass the JWT back to the server via .json and authenticate the token from there.
What benefit does an Authorization header give me, and moreso, what does a Bearer Authorization header give me?
I can of course simply follow everyone's example, but want to understand why. The bearer docs are verbose and hard to understand what I'm gaining over simple sending the JWT as part of the data in the request.
Thank you.
You can technically send a json body on each request with the JTW but that would be non standard behaviour (for instance, GET requests should not have a body via the spec).
A more standard way would be to provide an Authorization HTTP header.
The Authorization header is not specific to JWTs and its role is to specify an auth scheme between the client and the server.
Another way would be to include the JWT inside a cookie but that would make the behaviour browser specific while the HTTP header can be sent by virtually any HTTP client.
P.S
Bear in mind that contrary to Auth cookies which are sent by the browser automatically the Authorization header needs to be set by the client explicitly.

OpenID Connect, oAuth2 - Where to start?

I am not sure which approach I should be taking in our implementation and need some guidance.
I have a REST API (api.mysite.com) built in the Yii2 Framework (PHP) that accesses data from mysite.com (database). On mysite.com our users will be able to create Connected Apps that will provision a client id + secret - granting access to their account (full scope?).
Based on my research, the next step seems to be setting up something to actually provide the bearer tokens to be passed to the api - I have been leaning towards oAuth2, but then I read that oAuth2 does not provide authentication. Based on this I think I need OpenID Connect in order to also provide user tokens because my API needs to restrict data based on the user context.
In this approach, it is my understanding that I need to have an Authentication Server - so a few questions:
Is there software I can install to act as an OpenID Connect/oAuth2 authentication server?
Are there specific Amazon Web Services that will act as an OpenID Connect/oAuth2 Authentication Server?
I am assuming the flow will be: App makes a request to the auth server with client id + secret and receives an access token. Access token can be used to make API calls. Where are these tokens stored (I am assuming a database specific to the service/software I am using?)
When making API calls would I pass a bearer token AND a user token?
Any insight is greatly appreciated.
your understanding is not very far from reality.
Imagine you have two servers one for Authentication, this one is responsible for generating the tokens based on a Authorization Basic and base64 encoded CLientID / ClientSecret combo. This is application authentication basically. If you want to add user data as well, simply pass username / password in the post body, authenticate on the server side and then add some more data to the tokens, like the usernames, claims, roles, etc
You can control what you put in these tokens, if you use something like JWT ( Json Web Tokens ) then they are simply json bits of data.
then you have a Resource server, you hit it with a Authorization Bearer and the token you obtained from the Authorization one.
Initially the tokens are not stored anywhere, they are issued for a period of time you control. You can however do something else and store them in a db if you really want to. The expiration is much safer though, even if someone gets their hands on them they won't be available for long! In my case I used 30 minutes for token validity.
Now, you haven't specified what languages/frameworks you are looking into. If you use something like dot net then look into IdentityServer, version 4 is for Dot net core, 3 for anything below.
I also have a pretty long article on this subject if you are interested:
https://eidand.com/2015/03/28/authorization-system-with-owin-web-api-json-web-tokens/
Hopefully all this clarifies some of the questions you have.
-- Added to answer a question in comments.
The tokens contain all the information they need to be authenticated by the resource server correctly, you don't need to store them in a database for that. As I already said, you can store them but in my mind this makes them less secure. Don't forget you control what goes into a token so you can add usernames if that's what you need.
Imagine this scenario, you want to authenticate the application and the user in the same call to the Authorization Server. Do the OAuth2 in the standard way, which means authenticate the application first based on the client id / client secret. If that passes then next do the user authentication. Add the username or userid to the token you generate and any other bits of information you need. What this means that the resource server can safely assume that the username passed to it in the token has already been validated by the authentication server otherwise no token would have been generated in the the first place.
I prefer to keep these two separate myself, meaning let the AS ( Authorization Server) to deal with the application level security. Then on the RS (Resource Server) side you have an endpoint point like ValidateUser for example, which takes care of the user validation, after which you can do whatever you need. Pick whichever feels more appropriate for your project I'd say.
One final point, ALWAYS make sure all your api calls ( both AS and RS are just apis really ) are made over HTTPS and never ever have any important information transmitted via a GET call which means the URL can be intercepted. Both Headers and POST body are encrypted and secure over HTTPS.
This should address both your questions, I believe.

Q: Token based auth API and Javascript, can you protect other clientside files from being accessed?

Question
If you would use a similar setup as the following examples:
Simple WebAPI
Javascript OIDCClient and usermanager
Would it be possible to protect other clientside files from being accessed? Say for example i have a directory with certain files which you need a certain role to be able to access them.
Would it be possible to protect my SPA from being accessed before logging in?
Or is there a better solution which would have you end up with a protected api, folders/files on a server, SPA and a silent renew mechanism like there is in the OIDCClient?
#dmccaffery helped me out by answering my question, here is his answer for those of you who are interested.
To summarize using the OIDCClient for an SPA is certainly the way to go. Exposing stuff which needs authorization should be done by using an API. Protecting parts of your Angular App can be done using a Route guard.
The way it works is as follows:
The access token is either a JWT or a bearer token (usually) and is
added by the oidc client to every HTTP request in an authorization
header — when a web API receives a reques, the bearer token
authorization middleware will parse this HTTP header and will call the
token introspection endpoint (and potentially the user info endpoint)
to have the token validated and the users claims retrieved… if the
token was manipulated by the client, it will not be valid, and an HTTP
error will be returned (usually a 403). If the token was valid, a
claims identity is created and assigned to the http request context.
The API will now have a thread with an identity already assigned to it
that represents that user.
Also he pointed out 2 pluralsight courses which would probably be useful:
https://www.pluralsight.com/courses/building-securing-restful-api-aspdotnet
https://www.pluralsight.com/courses/oauth2-openid-connect-angular-aspdotnet

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

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.

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).

Resources