I'm planning to build a web app ("my app") which is accessed by users already logged into another web app run by the customer ("their app"). The goal is that users don't have to re-authenticate (re-enter their passwords into my app), rather their app should pass some information to my app that I can use to validate the user.
I know I could cook something up, like passing the user ID signed with a pre-shared secret key and some salt, but I was wondering whether there's an existing scheme or library for this use case. My app will be in Python, both apps run on different machines under different domains, and I'd like to keep required changes to their app to a minimum.
I believe the most popular protocol for this sort of deal is OAuth. There's a Python library for it as well.
SAML is another standard for SSO between disparate websites (e.g. different domains). Ping the customer to see if they already have support for it. If so, the Wikipedia page is a good place to start to gain a footing. Also check out this previous thread on Stack Overflow
Related
TLDR: I have a slack app for managing private channels in its development workspace and tokens for it that inherit my user privileges. How can someone else in the same workspace obtain tokens for this app that inherit their user privileges instead?
Ok, so the background of this is: i need to manage the membership of a bunch of private channels based on some more or less complicated ldap-related conditions. For this, i wanted to write a simple Python program that got the membership of the channels in question, did its ldap magic to figure out who should be where, and then make it so.
I have implemented this and all works fine so far. The issue now is that i (that is my slack user) cannot be in all of these channels for privacy reasons. The API and Bot tokens i have obtained inherit all of my own user privileges. That means i can neither see nor administrate the channels that i'm not a part of.
Based on what i've read in the documentation of the Slack API, there's a way to have another user go through the OAuth process for the app that i created to get the tokens, get their own tokens, and use them with the Python program that i wrote. That would be fine, but i can't figure out how to do this.
Noone else has access to the app directly. The documentation makes it seem like i need to give people a specially formatted link (the "Add to Slack Button") that they can click on to get taken through the process. But that seems to require a "redirect URL". I'm not sure what this is and the documentation isn't very clear on it, but it seems they are assuming that the app is running on a server somewhere and will need to answer requests from Slack or something. That's not the case. It's a fairly simple Python script, not some always-up cloud app that will be responding to Slack Events.
So it feels like i'm missing something. Either i have some fundamental misconception about how this is supposed to work, or there is a simple way for someone else to get a token like that and i'm not seeing it.
Yes. If you want other users to authenticate your app (e.g. generate tokens so your app can perform tasks on the users behalf) you need to create an installation routine using Ouath 2.0. That installation routine is a small web app that has the "Add to Slack" button, a HTML interface and is able to run through the Oauth 2.0 process. That web app needs to run on a public web server.
For development purpose that web server can also run on your local dev machine with a VPN tunnel to the public Internet. Slack recommends using the VPN service ngrok for that purpose.
Here is the situation:
We use Flask for a website application development.Also on the website sever, we host a RESTful service. And we use Flask-login for as the authentication tool, for BOTH the web application access and the RESTful service (access the Restful service from browsers).
Later, we find that we need to, also, access the RESTful from client calls (python), so NO session and cookies etc. This gives us a headache regarding the current authentication of the RESTful service.
On the web, there exist whole bunch of ways to secure the RESTful service from client calls. But it seems no easy way for them to live together with our current Flask-login tool, such that we do not need to change our web application a lot.
So here are the question:
Is there a easy way(framework) so the RESTful services can support multiple authentication methods(protocols) at the same time. Is this even a good practice?
Many thanks!
So, you've officially bumped into one of the most difficult questions in modern web development (in my humble opinion): web authentication.
Here's the theory behind it (I'll answer your question in a moment).
When you're building complicated apps with more than a few users, particularly if you're building apps that have both a website AND an API service, you're always going to bump into authentication issues no matter what you're doing.
The ideal way to solve these problems is to have an independent auth service on your network. Some sort of internal API that EXCLUSIVELY handles user creation, editing, and deletion. There are a number of benefits to doing this:
You have a single authentication source that all of your application components can use: your website can use it to log people in behind the scenes, your API service can use it to authenticate API requests, etc.
You have a single service which can smartly managing user caching -- it's pretty dangerous to implement user caching all over the place (which is what typically happens when you're dealing with multiple authentication methods: you might cache users for the API service, but fail to cache them with the website, stuff like this causes problems).
You have a single service which can be scaled INDEPENDENTLY of your other components. Think about it this way: what piece of application data is accessed more than any other? In most applications, it's the user data. For every request user data will be needed, and this puts a strain on your database / cache / whatever you're doing. Having a single service which manages users makes it a lot nicer for you to scale this part of the application stack easily.
Overall, authentication is really hard.
For the past two years I've been the CTO at OpenCNAM, and we had the same issue (a website and API service). For us to handle authentication properly, we ended up building an internal authentication service like described above, then using Flask-Login to handle authenticating users via the website, and a custom method to authenticate users via the API (just an HTTP call to our auth service).
This worked really well for us, and allowed us to scale from thousands of requests to billions (by isolating each component in our stack, and focusing on user auth as a separate service).
Now, I wouldn't recommend this for apps that are very simple, or apps that don't have many users, because it's more hassle than it's worth.
If you're looking for a third party solution, Stormpath looks pretty promising (just google it).
Anyhow, hope that helps! Good luck.
In my case I'm using the Dropbox API. Currently I'm storing the key and secret in a JSON file, just so that I can gitignore it and keep it out of the Github repo, but obviously that's no better than having it in the code from a security standpoint. There have been lots of questions about protecting/obfuscating Python before (usually for commercial reasons) and the answer is always "Don't, Python's not meant for that."
Thus, I'm not looking for a way of protecting the code but just a solution that will let me distribute my app without disclosing my API details.
Plain text. Any obfuscation attempt is futile if the code gets distributed.
Don't know if this is feasible in your case. But you can access the API via a proxy that you host.
The requests from the Python APP go to the proxy and the proxy makes the requests to the Dropbox API and returns the response to the Python app. This way your api key will be at the proxy that you're hosting. The access to the proxy can be controlled by any means you prefer. (For example username and password )
There are two ways depending on your scenario:
If you are developing a web application for end users, just host it in a way that your API key does not come to disclosure. So keeping it gitignored in a separate file and only upload it to your server should be fine (as long there is no breach to your server). Any obfuscation will not add any practical benefit, it will just give a false feeling of security.
If you are developing a framework/library for developers or a client application for end users, ask them to generate an API key on their own.
I have created an application in python. And I am using extjs for the front-end.
Once a valid user logs in, I want to use the username of the logged in user for further transactions.
I wanted urgent help on how session management is to be done in python.
Thanks in advance.
You don't do "session management in Python". You do "session management in a framework, which may be implemented in Python".
A session can be implemented in many ways, but normally is implemented via Cookies. For example, Django (a Python framework), writes a cookie with a value called session containing a given string (say aabbccddeeff12345). For every request, Django checks whether the cookie exists, and if it does, it maps it to a user.
This is far from trivial. However, if you use Django (or most robust web frameworks in any language), this is completely transparent.
If you don't know what a cookie is, or are unfamiliar with web security, I don't think this is a problem that you should tackle yourself.
Use a framework, and understand it.
If you don't use a framework or if your framework doesn't provide session management, Beaker is a popular library do this.
Examples at https://beaker.groovie.org/sessions.html#using show how to store a username in the session object.
I'm writing a facebook desktop application for the first time using the PyFacebook api. Up until now, since I've been experimenting, I just passed the secret key along with the api key to the Facebook constructor like so:
import facebook
fb = facebook.Facebook("my_api_key", "my_secret_key")
and then logged in (fb.login() opens a browser) without any trouble. But now, I want to distribute the code and since it's python and opensource, I want to have some way of protecting my secret key. The wiki mentions I can use a server and ask for my secret key using the server each time my app runs (as I understand), but I have no clue as to how to start doing this, and how this should be done. I have never done web programming and don't know where I can get a server, and how to get the server to do what is needed in this case, and I don't know how can I use that server. I would really appreciate some help!
Thank you.
The relevant page on the FB developer wiki recommends a server component that just keeps your secret key and handles auth.getSession(), then gives your desktop app a session key. See that link for details.
EDIT: cmb's session keys approach is better than the proxy described below. Config files and GAE are still applicable. /EDIT
You could take a couple approaches. If your code is open-source and will be used by other developers, you could allow the secret key to be set in a configuration file. When you distribute the code, place a dummy key in the file and create some instructions on how to obtain and set the key in the config file.
Alternately, if you want to do the server approach, you'll basically be creating a proxy* that will take requests, add the secret key and then forward them on to Facebook. A good, free (unless/until your app gets a lot of users) Python-based service is Google App Engine. They also have a bunch of tutorial videos to get you started.
* E.g., when myservice.appspot.com/getUserInfo?uid=12345 is called, your service will execute something like the following.
userinfo = fb.users.getInfo(self.request.get('uid')...)
Ideally, you'd want to abstract it enough that you don't have to explicitly implement every FB API call you make.
One last thing to keep in mind is that many FB API calls do not require the secret key to be passed.