I’m using the Istio OPA adapter to manage AuthN and AuthZ. Some of my backend services need to know who is making a given request; for example, to populate a created_by column when a given user creates something.
I’m trying to figure out an elegant way of decoding the JWT and putting the “sub” field into a “user” header before the request gets sent to the actual backend service. This way, a given service would simply need to look at the “user” header rather than dealing with parsing the JWT.
Any ideas or recommendations on how this could be accomplished are appreciated.
You should be able to add headers with Lua code in an EnovyFilter or with a Mixer filter starting in Istio 1.1.
Take a look at this issue which describes some experimenting with adding headers extracted from JWT fields to affect routing:
https://github.com/istio/istio/issues/8444.
Related
I just want to make sure I've got the overall idea down and don't create an implementation that violates basic security best practices. Can somebody please check my understanding?
As I understand it, a user can log in to my application and the authentication server REST API can return a JWT that is signed, but NOT encrypted. Inside that token I can have claims inside the payload that my client application can access, such as features the user can use on the application. That way my client side website can change functionality based on the user privileges and roles. The JWT claims in the payload are NOT sensitive. They will be strings representing categories for images or documents, things like that.
When the user wants to get additional content (like a document, image, or video) from other REST API endpoints, they submit the JWT along with the GET request. My API can then verify the signature of the JWT and grant API access if appropriate.
This last part is what I'm most unsure about. My intent is to use another authorization server API endpoint which takes the JWT in a POST request and returns a simple "valid/invalid" response. My thought is that my Content Delivery Network (CDN) can use this API to verify that the JWT in possession is validly signed. I believe (and maybe here is where I'm goofing up) that the authorization server API can be publicly accessible to ease use by my other microservices. This seems fine because I'm just giving a boolean pass/fail on the validity of the token so I don't see any need to hide or obfuscate the API. I question this because I know AWS has backend stuff to validate and authorize for API calls but I like the simplicity of just using REST APIs for everything for my first implementation; to maintain simplicity.
So in summary:
1.) Signed, unencrypted JWT with non-sensitive user roles/privileges.
2.) Unencrypted so client side webpage can selectively render content based on user.
3.) Public authorization API that anybody could technically use so that my CDN (and other microservices) can validate JWTs.
Any major issue with this approach? Have I committed any technical sins?
Thank you so much in advance for your time on this matter.
Okay, I think I've sorted this out myself after finding a great video tutorial on this stuff. Below is the video I watched:
https://www.youtube.com/watch?v=_XbXkVdoG_0
I had some misconceptions and this video sorted them out. It appears that what I described in my question is precisely how JWT should be used.
I have created a Rest service. In this service I want to know which client is calling the service. Is there any method to check the properties or information of the client.
I don't know what you exactly mean by "which client". I see two things:
The terminal kind. This can be known using the User-Agent header if set.
The authenticated user using the Authorization header. The content in this header allows to get the corresponding user. This allows to authenticate requests. In this case, this link could help you: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/.
Hope it helps you,
Thierry
Is there a way to dynamically set the endpoints in WSO2 API Manager to something other than the configured production and sandbox URLs? In my case, I want to route based on an incoming header value; resulting in something like:
https://my_dynamically_determined_subdomain.my_static_domain.com
I tried doing this with a custom handler class that writes my desired URL to the "To" header, but that doesn't seem to affect the routing.
Is there another way to accomplish this?
Your approach seems to be good. You can set "To" header dynamically. But you have to use a Default Endpoint, instead of a HTTP Endpoint. Default Endpoint will send the message to the URL found in "To" header. Please modify your inSequence of the API Configuration (found in $AM_HOME/repository/deployment/server/synapse-configs/default/api/your-api.xml) to replace the HTTP endpoint with a Default endpoint, as shown below.
If you want to do this to all of your APIs, then you can edit velocity_templates.xml so that all the APIs will be published with default endpoints automatically. Please refer this doc for more details on this. It is worth to have a look at this blog post which is discussing a similar pattern what you are trying to do.
Having for instance
http://mywebsite.com?increase_counter=true/
I want to let someone increase counter on my database with a GET request but only when he is authenticated. How can someone be authenticated when coding in something external? eg shell or API.
Should I consider using tokens in GET request or is there an easy way to firstly authenticate someone with a simple request POST or GET and then execute url? EG I want to authenticate myself to django app with a simple shell. How to do it? Maybe another way?
I think your easiest approach is to include some sort of authentication tokens with the GET itself. The problem is that in order for you to be able to use other forms of authentication, you'll need to actually package the data (HTTP Authentication requires an authentication header, traditional authentication requires a cookie header).
If all you want to do is create a simple point-of-entry, then GET parameters are no more complicated than concatenating some strings.
Some existing web services I consume have methods that look something like this:
List<Employee> employees =
employeeService.GetEmployees(accessKey, allDepartments);
The accessKey serves two purposes; it acts as both authentication and identification. Only valid access codes are responded to (authentication) and it services as a link to a particular client's data.
If the services were to be done a restful manner I'm not sure how this would be achieved. I definitely would not want to do something like this:
http://www.business.com/<GuidHere>/Employees/
Since this would show the accessKey, which is somewhat secret, (ie, its usually in an encrypted file on the client which uses this) we can't show the GUID in a URI. How is something like this achieved using a restful architecture?
You could send the authentication token using HTTP headers.
If this is a RESTful web service I'm assuming it's being consumed by a machine so why not pass the access key in the url?
At then end of the day you need to put it somewhere and hiding them in hidden form fields in the browser (if the service is to be browsable) isn't much in the way of security.
If the key is so sensitive, why not symmetrically encrypt on the server per session and pass that value around instead?
Just some thoughts.
Kev
If time isn't an issue implementing OAuth security may be useful. OAuth uses a public key, and also a secret. The mess is hashed (in most cases) and the server will use the public key + it's copy of the secret to do the same hashing and make sure its result matches the requests.
The benefit is you wouldn't need to use HTTPS or POST. Get* REST api methods should be using the HTTP GET method (I'm not sure if being RESTful is your goal, just thought I would point that out). I agree with Mr. Pang, use http://www.business.com/employees. The query string could contain the list of department ids.
For your case the service call wouldn't have the 'accessKey' argument, rather it would become the public key (I imagine) and be used in either the headers, query string, or as a POST param.
Some good info on OAuth: http://www.hueniverse.com/hueniverse/
As Troy Alford pointed out, my original suggestion was incorrect. You shouldn't be using POST in a situation like this. You should use a GET request with the authentication information in the HTTP headers. Take a look at basic access authentication for one way to do that.