I'm developing my first AngularJS application with Django as backend.
My overall architecture is composed of:
Public API json-rpc server (from which I must retrive data previous authentication process (the client send a user/password with a POST request, and then, the server response with a token string).
Django framework, I use this because I need to have some models and MySQL db for additional data; and because the Public API server doesn't support CORS (is a old version) and I've created an API Proxy with one view of Django.
Angular JS App that it served by Django.
Now, when the client first send user/password with AngularJS -> Django -> API server, the server respond with token, and henceforward the Client use token to make next requests.
My question is: What's the right approach to retain the token on the client (AngularJS) (or on Django if required) after the user did login??
Do you have any suggestion on my architecture?
Thanks in advance... and... sorry for my English :)
Depending from your needs you should think about storing the token in the session storage in the local storage or in a cookie(in this case the cookie is used as a storage mechanism and not as an authentication mechanism).
Related
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/
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.
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.
I have been reading a lot about this google endpoints and I have trying to something that is not quite easy to guess. After you create a google cloud endpoint server and you deploy it is open to any HTTP request (unauthenticated). In the cloud endpoint documentation (referring to using authentication) you can read about setting OAuth2.0 to authenticate users with google account but there is no documentation about restrict the endpoint service to a specific mobile app (android or ios) and discard all other HTTP requests. So the question is how to authenticate mobile apps (no users) and prevent HTTP request (unauthenticated)? I'am building my server API(enpoints) based on Python.
Thank you.
In order to restrict your Endpoint to a specific application you can use OAuth2. This is because the OAuth2 flow does user authentication and in-turn the OAuth2 flow inherently authenticates the application requesting the OAuth2 access.
These two client samples detail how to enable authenticated calls on the client side. You have to register your apps in the Developer Console at http://cloud.google.com/console/ .
https://github.com/GoogleCloudPlatform/appengine-endpoints-helloendpoints-android (Starting after the Note in the readme)
https://github.com/GoogleCloudPlatform/appengine-endpoints-helloendpoints-ios/ (Step 8 in README)
authedGreeting is the authenticated call and you would check the User object in the method's backend project for null. If empty then you can immediately throw an unauthorized exception.
https://github.com/GoogleCloudPlatform/appengine-endpoints-helloendpoints-java-maven
Specifically, optional Step 2 in the README tells Cloud Endpoints to start looking for OAuth2 tokens in the request. If the Endpoints exposed method has a User parameter. It will populate it with a user instance only if an OAuth2 token was found, was generally valid, and the token was issued to a client ID defined in the API annotation on the service class.
During the setup of your endpoints API, in clientIds list you provide your WEB_CLIENT_ID, ANDROID_CLIENT_ID, and IOS_CLIENT_ID for example. These values tell the Google App Engine that your application will respond to HTTPS requests from web browsers and Android/iOS installed applications.
When your clients first connect your server, they must obtain an OAuth 2.0 token in order to the communication be secure and that is the reason why you use the WEB_CLIENT_ID in your installed client application. This WEB_CLIENT_ID is unique to your Google Cloud app and through it your client becomes capable of obtain an access_token and a renew_token to communicate with your backend server and your server only. This is a cross-client authorization.
So, if you need only the WEB_CLIENT_ID to obtain the access_token and the renew_token, why you need the ANDROID_CLIENT_ID and IOS_CLIENT_ID? For security reasons.
The ANDROID_CLIENT_ID is linked to a RSA signature key through the SHA1 informed at backend setup. Thus your GAE app will grant (access_token, renew_token) only installed apps signed with the same key listed at your application console (and of course in your clientIds list)
Finally Android apps signed with different or not signed will not receive any access_token, being unable to establish the secure communication channel or even communicate with your server.
I have a website which uses Amazon EC2 with Django and Google App Engine for its powerful Image API and image serving infrastructure. When a user uploads an image the browser makes an AJAX request to my EC2 server for the Blobstore upload url. I'm fetching this through my Django server so I can check whether the user is authenticated or not and then the server needs to get the url from the App Engine server. After the upload is complete and processed in App Engine I need to send the upload info back to the django server so I can build the required model instances. How can I accomplish this? I was thinking to use urllib but how can I secure this to make sure the urls will only get accessed by my servers only and not by a web user? Maybe some sort of secret key?
apart from the Https call ( which you should be making to transfer info to django ), you can go with AES encryption ( use Pycrypto/ any other lib). It takes a secret key to encrypt your message.
For server to server communication, traditional security advice would recommend some sort of IP range restriction at the web server level for the URLs in addition to whatever default security is in place. However, since you are making the call from a cloud provider to another cloud provider, your ability to permanently control the IP address of either the client and the server may diminished.
That said, I would recommend using a standard username/password authentication mechanism and HTTPS for transport security. A basic auth username/password would be my recommendation(https:\\username:password#appengine.com\). In addition, I would make sure to enforce a lockout based on a certain number of failed attempts in a specific time window. This would discourage attempts to brute force the password.
Depending on what web framework you are using on the App Engine, there is probably already support for some or all of what I just mentioned. If you update this question with more specifics on your architecture or open a new question with more information, we could give you a more accurate recommendation.
SDC provides a secure tunnel from AppEngine to a private network elsewhere -- which could be your EC2 instance, if you run it there.