Multiple backend servers accessible from a Flask server - python

I want to have a front-end server where my clients can connect, and depending on the client, be redirected (transparently) to another Flask application that will handle the specific client needs (eg. there can be different applications).
I also want to be able to add / remove / restart those backend clients whenever I want without killing the main server for the other clients.
I'd like the clients to:
not detect that there are other servers in the backend (the URL should be the same host)
not have to reenter their credentials when they are redirected to the other process
What would be the best approach?

The front-end server that you describe is essentially what is known as a reverse proxy.
The reverse proxy receives requests from clients and forwards them to a second line of internal servers that clients cannot reach directly. Typically the decision of which internal server to forward a request to is made based on some aspect of the request URL. For example, you can assign a different sub-domain to each internal application.
After the reverse proxy receives a response from the internal server it forwards it on to the client as if it was its own response. The existence of internal servers is not revealed to the client.
Solving authentication is simple, as long as all your internal servers share the same authentication mechanism and user database. Each request will come with authentication information. This could for example be a session cookie that was set by the login request, direct user credentials or some type of authentication token. In all cases you can validate logins in the same way in all your applications.
Nginx is a popular web server that works well as a reverse proxy.

Sounds like you want a single sign-on setup for a collection of service endpoints with a single entry point.
I would consider deploying all my services as Flask applications with no knowledge of how they are to be architected. All they know is all requests for resources need some kind of credentials associated with them. The manner you pass those credentials can vary. You can use something like the FAS Flask Auth Plugin to handle authentication. Or you can do something simpler like package the credentials provided to your entry service in the HTTP headers of the subsequent requests to other services. Flask.request.headers in your subsequent services will give you access to the right headers to pass to your authentication service.
There are a lot of ways you can go when it comes to details, but I think this general architecture should work for you.

Related

Sharing sessions between two flask servers

I have a backend with two flask servers. One that handles all RESTfull request and one that is an flask-socketio server. Is there a way how I can share the session variables (Logged in User etc.) between these two applications? They do run over different ports if that is important.
How I have understood sessions they work over client session cookies so shouldn't both of these servers have access to the information? If yes how? and if not is there a way to achieve the same effect?
There are a couple of ways to go at this, depending on how you have your two servers set up.
The easiest solution is to have both servers appear to the client on the same domain and port. For example, you can have www.example.com/socket.io as the root for your Socket.IO server, and any other URLs on www.example.com going to your HTTP server. To achieve this, you need to use a reverse proxy server, such as nginx. Clients do not connect directly to your servers, instead they connect to nginx on a single port, and nginx is configured to forward requests the the appropriate server depending on the URL.
With the above set up both servers are exposed to the client on the same domain, so session cookies will be sent to both.
If you want to have your servers appear separate to your client, then a good option to share session data is to switch to server-side sessions, stored in Redis, memcache, etc. You can use the Flask-Session to set that up.
Hope this helps!
I found that flask.session.sid = sid_from_another_domain works fine in having individual sub domains case.
I have several flask apps has individual domain names like A.domain.com, B.domain.com, and C.domain.com.
They all are based on flask and has redis session manager connected to same redis server.
I wanted to federate them to be logged in at once and to be logged out too.
I had to save the session id on db with user infomation together when I logged in A and passed it to domain B.
These domains communicates using oauth2 protocol, and I used flask_dance in this case.
And set it into flask.session.sid on B domain.
And then I could confirmed that this implementation works fine.

Django rest Framework : encrypt response data

I am using Django rest Framework to build a REST API for one of my clients. The app provides some sensitive information such as passwords when the client asks for it through an API call.
Now, only authorized clients can access to the app and besides that, only authorized IP can connect.
But what if someone was listening in the middle of that connection ? He would see all the datas in clear.
Is there a way to encrypt those info, maybe with a password, and then decrypt it when it arrives ? (the client would have to update his app, but it's not a problem).
I was thinking maybe to create an "EncryptedResponse" instead of "Response" in my django app.
Thanks
If you don't have one already, purchase an SSL certificate and configure your site to load the API over HTTPS. That way the connection between the authorized client and your application would be encrypted which will prevent a man in the middle attack that you're describing.
If you're not going to load the API over HTTPS, then the authentication token, or API key, or whatever you're using to authenticate the client can also be intercepted.
However, if you're looking to stick to the encrypting the data route, I've found this guide that looks like it should help you be able do what you need to do:
http://gpiot.com/blog/encrypted-fields-pythondjango-keyczar/

API registration and authentication service

I'm working on an API registration and authentication service application using python. Developers will be able to register their application (domain name of the application) and a random API key will be generated for the registered application.
Next, the registered application will send the API key to the API service with each API request. API server will authenticate the domain of the incoming request with the passed API key to confirm that the request is valid. I'm using Forwarded Host to validated the domain name of the API request, however it doesn't work as in some cases (when the opened page is the first page), Forward Host comes blank.
Are there a better approach to authenticate the request or any changes required in the API registration process to reliably authenticate the request? Some pointers will be helpful.
Using Authorization proxy
Samples are "3scale.net", offering free tier, other commercial solutions exist too.
Open source solution I am aware of is ApiAxle, which is much simpler, but still very useful.
The proxy takes care of managing access keys and forwards request back to real application only in case, it is really to be served.
Using Authorization service
Another solution is to have some internal service evaluating set of client provided keys (providerid, appid, accesskey, ...) are authrized or not. For this purpose, you have to:
set up authorization service
modify your code by adding 2-3 lines at the top of each call calling the authentication service.
Sample code for 3scale is here: https://github.com/3scale/3scale_ws_api_for_python
Conclusions
Authentication proxy makes the application simple and not bothering about who is asking. This can be advantage until your application needs to know who is asking.
Authentication service requires changing your code.

Mocking Oauth providers while testing

I have an app that I'm writing which authenticates against an Oauth 2.0 authorisation server. I'd like to test the parts that are accessible only after you've logged in but the Oauth server is an external dependency that complicates and make brittle my tests.
Any suggestions on how I should go about this? What the industry practices for something like this? My gut feel is to somehow mock out the server so that it allows access to the protected resources.
In case it matters, this is a Python webapp written using Flask.
I am using a custom oauth server which will run on my own domain and while it's possible to add some kind of sandboxing functionality as FoxMask has suggested, I'd much prefer being able to run the test without requiring an extra server running.
From the consumer (i.e. your application) side, the OAuth2 process can be separated in two parts:
the redirect from your application to the OAuth2 provider's "authorize" URL
the exchange of the "code" returned by the OAuth2 provider for an access token
For #1 all you need to test is that when you invoke the route that starts the authentication process the response returned is a redirect to the OAuth2 provider. This is easily accomplished with Flask's test client. The response should have a status code of 302 and a "Location" header set to the authorize URL for your OAuth2 provider. Note that you do not need to provider to be up, you are just testing that the response is a redirect, but you do not need to actually redirect.
Testing for #2 is a little bit more involved. Your Flask app has a special URL that is designated as the "redirect URL" for the OAuth2 provider to send you back the authorization code. You can just invoke this URL with the Flask test client passing a mock code and that has no issue.
The problem is that in the view function that handles your redirect URL you need to invoke the OAuth2 provider to exchange the auth code for an access token, and this is done synchronously. To prevent this transaction to happen you have to check app.config['TESTING'] and in that case skip the actual request and replace it with a fake response that includes a mock access token.
From then on you will need to also fake any additional calls into the OAuth2 provider that send the access token to request data.
If you are using an OAuth2 client library in your Flask app it may be easier to create the mock provider without having to create testing exceptions in your application. In my case I'm using rauth, and for this I have created a subclass of the OAuth2Service class that overrides the proper methods and responds with mock data that I have captured from a real session. Then in my test setup I just create the mock service and the application is fooled into thinking it is talking to a real server.
I hope this helps.

python (flask) redirect request via client

I have been trying to do something which I think should be pretty simple. The situation is as follows. The client makes a request for a resource on my web server. My flask application processes the request and determines that this resource is located at a certain location on another web server and the client should make a request of that server instead.
I know I can use the redirect function to tell the client to send a request to the remote location, but my problem is that the remote location is the Amazon Glacier servers. These servers require a request to be made in a certain way, with a special signature (see http://docs.aws.amazon.com/amazonglacier/latest/dev/amazon-glacier-signing-requests.html). My flask application knows how to go about the business of making these requests in the required way. I essentially want to know if it's possible to send a response to my client saying, send this request (generated by my application, with all the required signing) to the Amazon server?
Any ideas?
If the request can be encoded with get params like
http://www.redirecturl.com/?param1=bla&param2=blub
then it should work no problem. Just construct the request as a string and pass it to redirect().
As far as i know, you can't tell a client to send specific headers to a HTTP redirect URL.
Hitting the Glacier URL serverside would be the easiest. Using javascript on the clientside would only work if Glacier is implementing CORS.

Categories