If you’re building Python web apps — you might have heard of our awesome Python libraries which make adding users and authentication into your web apps way easier:
What you probably didn’t know, however, is that our Python library just got a whole lot more interesting. Last week we made a huge release which added several new features.
The Basics
Since the beginning of time, our Python library has made creating user accounts, managing groups and permissions, and even storing profile information incredibly easy.
If you’re not familiar with how this works, take a look at the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
from stormpath.client import Client client = Client(id='xxx', secret='xxx') # Create an app. app = client.applications.create({'name': 'myapp'}, create_directory=True) # Create a user. account = app.accounts.create({ 'given_name': 'Randall', 'surname': 'Degges', 'password': 'iDONTthinkso!222', 'custom_data': { 'secret_keys': [ 'blah', 'woot', 'bankstuff', ], }, }) # Create a group. admins_group = app.groups.create({ 'name': 'admins' }) # Add the user to the group. account.add_group(admins_group) |
The code above creates a new user account, stores some account information, creates a group, and puts that user into the group — all in a few lines of code.
With Stormpath, all users are stored on Stormpath’s servers, where we encrypt the user information and provide abstractions and libraries to make handling authentication as simple as possible.
NOTE: You can install our library via PyPI, the Python package manager: pip install stormpath
.
ID Site
A while back, some of us over here were chatting about ways to make authentication better, and the idea of ID Site was born.
What if, as a developer, you didn’t have to render views and templates to perform common authentication tasks?
What if, all you had to do was redirect the user to some sub-domain (like login.yoursite.com), and all of the authentication and registration stuff would be completely taken care of for you?
Furthermore — what if you could fully customize the way your login pages look using all the latest-and-greatest tools?
It would be totally awesome, right?
Well — that’s what ID Site does!
ID Site is a hosted product we run that allows you to easily handle complex authentication rules (including SSO, social login, and a bunch of other stuff), while providing users a really nice, clean experience.
And as of our latest Python release — you can now use it really easily!
To redirect a user to your ID Site to handle authentication stuff, all you need to do is generate a secure URL using our helper functions:
1 2 3 |
url = app.build_id_site_redirect_url('http://login.mysite.com/redirect') # Then you'd want to redirect the user to url. |
By default, the normal login page looks something like this (depending on whether or not you have social login and other features enabled):
After the user signs in, they’ll be redirect back to whatever URL you specify as a parameter above — then you can create a user session and persist the user’s information — this way you know they’ve been logged in.
Again — this is super easy.
Assuming you’re writing code to handle the redirect, you’d do something like this:
1 2 3 |
result = app.handle_id_site_callback(request) # result.account is the user's account. |
Bam! And just like that, you can register, login, and logout users.
API Keys and Authentication!
Let’s say you’re building a REST API, and need to ensure only certain users have access to the API. This means you’ve got to generate API keys for each user, and authenticate incoming API requests.
Depending on the tools and libraries you’re using, this could be either a very simple or very painful task.
With our latest Python release, you can now generate as many API keys as you want for each of your users. This means building API services just got a wholeeeeee lot easier:
1 2 3 4 |
# Generate an API key for a user. key = account.api_keys.create() print key.id, key.secret |
Each API key has two parts:
- An
id
(similar to a username). - A
secret
(similar to a password).
Once you’ve generated an API key for a user, and given that key TO the user, they can then use their API key to authenticate against your API service using either:
- HTTP Basic Authentication, or
- OAuth2
To authenticate a user via HTTP Basic Authentication, you write code that looks like this:
1 2 3 4 5 6 7 8 9 10 11 |
# Assuming the user sent you their API credentials properly, by passing in # the `headers` option our library will handle authentication for you. result = app.authenticate_api( allowed_scopes=None, http_method=None, uri=None, body=None, headers=request.headers ) # result.account is now the user's account object! |
The above code will work properly when a developer sends an authenticated API request of the form:
1 2 3 4 5 |
GET /troopers/tk421/equipment Accept: application/json Authorization: Basic MzRVU1BWVUFURThLWDE4MElDTFVUMDNDTzpQSHozZitnMzNiNFpHc1R3dEtOQ2h0NzhBejNpSjdwWTIwREo5N0R2L1g4 Host: api.trooperapp.com |
For OAuth flows, things are equally simple — firstly, you need to request an OAuth token by exchanging your API keys for an OAuth token:
1 2 3 4 5 6 7 8 |
POST /oauth/token Accept: application/json Authorization: Basic MzRVU1BWVUFURThLWDE4MElDTFVUMDNDTzpQSHozZitnMzNiNFpHc1 Content-Type: application/x-www-form-urlencoded Host: api.trooperapp.com grant_type=client_credentials |
When this request is made, on the server-side you can generate a token by calling the authenticate_api
method:
1 2 3 4 5 6 7 8 9 |
result = app.authenticate_api( allowed_scopes=None http_method='POST', uri='/blah', body=request.body, headers=request.headers ) # result.token is now the user's OAuth token object! |
From this point on, the developer can now pass that token as their credentials:
1 2 3 4 5 |
GET /troopers/tk421/equipment Accept: application/json Authorization: Bearer 7FRhtCNRapj9zs.YI8MqPiS8hzx3wJH4.qT29JUOpU64T Host: api.trooperapp.com |
And if you want to secure an API endpoint with OAuth, you just use the same authenticate_api
method as before:
1 2 3 4 5 6 7 8 9 |
result = app.authenticate_api( allowed_scopes=None http_method='POST', uri='/blah', body=request.body, headers=request.headers ) # result.token is now the user's OAuth token object! |
Cool, right?!
Using our new API stuff, you can easily build out a public (or private) facing API service complete with both HTTP Basic Authentication and OAuth2.
Github and LinkedIn
Lastly, we’ve also added two brand new social providers to platform: Github and LinkedIn.
This means that if you want to allow your web users to log into your app via:
- Github or
You can easily do so with just a few lines of code!
Future Stuff
We’re still working really hard to improve our Python library — we’re cleaning up our docs, simplifying our internal APIs, and doubling down on our efforts to make it the most awesome, simple, and powerful tool out there.
If you have any feedback (good or bad), please send us an email! We’d love hear from you: [email protected]