Skip to content
This repository was archived by the owner on Oct 2, 2023. It is now read-only.

Commit 449a802

Browse files
author
Grace Yim
committed
Simplify README
1 parent 862c0c6 commit 449a802

File tree

1 file changed

+56
-206
lines changed

1 file changed

+56
-206
lines changed

README.md

Lines changed: 56 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -1,192 +1,83 @@
11
#ToopherPython [![Build Status](https://travis-ci.org/toopher/toopher-python.png?branch=master)](https://travis-ci.org/toopher/toopher-python)
2-
### Introduction
2+
33
ToopherPython is a Toopher API library that simplifies the task of interfacing with the Toopher API from Python code. This project wrangles all the required OAuth and JSON functionality so you can focus on just using the API.
44

55
### Python Version
6-
\>=2.6.0
6+
* 2.6
7+
* 2.7
78

8-
### Learn the Toopher API
9+
### Documentation
910
Make sure you visit [https://dev.toopher.com](https://dev.toopher.com) to get acquainted with the Toopher API fundamentals. The documentation there will tell you the details about the operations this API wrapper library provides.
1011

11-
### OAuth Authentication
12-
First off, to access the Toopher API you'll need to sign up for an account at the [Toopher developers portal](https://dev.toopher.com) and create a "requester". When that process is complete, your requester is issued OAuth 1.0a credentials in the form of a consumer key and secret. Your key is used to identify your requester when Toopher interacts with your customers, and the secret is used to sign each request so that we know it is generated by you. This library properly formats each request with your credentials automatically.
13-
14-
### The Toopher Two-Step
15-
Interacting with the Toopher web service involves two steps: pairing, and authenticating.
16-
17-
#### Step 0: Create an API Object
18-
Using your consumer key and consumer secret, create a ToopherApi object which will be used to generate an authentication or user management url and process the postback data.
19-
20-
#### Step 1: Pair
21-
Before you can enhance your website's actions with Toopher, your customers will need to pair their phone's Toopher app with your website. To do this, they generate a unique, nonsensical "pairing phrase" from within the app on their phone. You will need to prompt them for a pairing phrase as part of the Toopher enrollment process. Once you have a pairing phrase, just send it to the Toopher web service and we'll return a pairing ID that you can use whenever you want to authenticate an action for that user.
12+
## ToopherApi Workflow
2213

23-
#### Step 2: Authenticate
24-
You have complete control over what actions you want to authenticate using Toopher (for example: logging in, changing account information, making a purchase, etc.). Just send us the user's pairing ID, a name for the terminal they're using, and a description of the action they're trying to perform and we'll make sure they actually want it to happen.
25-
26-
### Librarified
27-
This library makes it super simple to do the Toopher two-step. Check it out:
14+
### Step 1: Pair
15+
Before you can enhance your website's actions with Toopher, your customers will need to pair their mobile device's Toopher app with your website. To do this, they generate a unique pairing phrase from within the app on their mobile device. You will need to prompt them for a pairing phrase as part of the Toopher enrollment process. Once you have a pairing phrase, just send it to the Toopher web service and we'll return a pairing ID that you can use whenever you want to authenticate an action for that user.
2816

2917
```python
30-
from toopher import *
18+
import toopher
3119

32-
# Step 0 - Create an API Object Using Your Credentials
20+
# Create an API Object Using Your Credentials
3321
api = toopher.ToopherApi("<your consumer key>", "<your consumer secret>")
3422

35-
# Step 1 - Pair with their phone's Toopher app
36-
# With pairing phrase
23+
# Step 1 - Pair with their mobile device's Toopher app
3724
pairing = api.pair("username@yourservice.com", "pairing phrase")
38-
# With SMS (optional parameter: country_code)
39-
pairing = api.pair("username@yourservice.com", "555-555-5555", country_code="1")
40-
# With QR code
41-
pairing = api.pair("username@yourservice.com")
25+
```
26+
27+
### Step 2: Authenticate
28+
You have complete control over what actions you want to authenticate using Toopher (for example: logging in, changing account information, making a purchase, etc.). Just send us the user's pairing ID and a name for the terminal they're using and we'll make sure they actually want it to happen.
4229

30+
```python
4331
# Step 2 - Authenticate a log in
44-
# With pairing id and terminal name
45-
authentication_request = api.authenticate(pairing.id, "my computer")
46-
# With username and terminal name and/or requester_specified_id
47-
authentication_request = api.authenticate("username", terminal_name="terminal_name", requester_specified_id = "requester_specified_id")
32+
authentication_request = api.authenticate(pairing.id, "terminal name")
4833

4934
# Once they've responded you can then check the status
5035
authentication_request.refresh_from_server()
5136
if not authentication_request.pending and authentication_request.granted:
5237
# Success!
5338
```
54-
### Zero-Storage Usage Option
55-
Requesters can choose to integrate the Toopher API in a way does not require storing any per-user data such as Pairing ID and Terminal ID - all of the storage
56-
is handled by the Toopher API Web Service, allowing your local database to remain unchanged. If the Toopher API needs more data, it will `raise()` a specific
57-
error that allows your code to respond appropriately.
58-
59-
```python
60-
try:
61-
# Try to authenticate against Toopher API with username and a requester specified id,
62-
# which is typically a randomly generated secure browser cookie.
63-
# It does not need to be human-readable and will not be displayed to the user.
64-
authentication_request = api.authenticate("username", requester_specified_id="requester_specified_id")
65-
66-
# If you got here, you just need to check the status of the authentication request.
67-
if not authentication_request.pending and authentication_request.granted:
68-
#Success!
69-
70-
# There are four distinct errors ToopherAPI can return if it needs more data
71-
except UserDisabledError:
72-
# You have marked this user as Toopher disabled in the Toopher API.
73-
except UserUnknownError:
74-
# This user has not yet paired a mobile device with their account.
75-
# Pair them using api.pair() as described above, then re-try authentication
76-
except TerminalUnknownError:
77-
# This user has not assigned a "friendly name" to this terminal identifier.
78-
# Prompt them to enter a terminal name, then submit that "friendly name" to the Toopher API:
79-
api.advanced.user_terminals.create("username", "terminal_name", "requester_specified_id")
80-
# Afterwards, re-try authentication.
81-
except PairingDeactivatedError:
82-
# This user does not have an active pairing (typically because they deleted the pairing).
83-
# You can prompt the user to re-pair with a new mobile device.
84-
```
8539

86-
### Handling Errors
87-
If any request runs into an error a `ToopherApiError` will be thrown with more details on what went wrong.
40+
## ToopherIframe Workflow
41+
### Step 1: Embed a request in an IFRAME
42+
1. Generate an authentication URL by providing a username.
43+
2. Display a webpage to your user that embeds this URL within an `<iframe>` element.
8844

89-
### Dependencies
90-
This library uses the [Requests](http://docs.python-requests.org/en/latest/) library and [OAuthLib](https://oauthlib.readthedocs.org/en/latest/index.html) to handle OAuth signing and make the web requests.
45+
```python
46+
import toopher
9147

92-
Toopher uses [pip](https://pypi.python.org/pypi/pip) to install Python packages.
48+
# Create an API Object Using Your Credentials
49+
iframe_api = toopher.ToopherIframe("<your consumer key>", "<your consumer secret>")
9350

94-
To ensure all dependencies are up-to-date run:
95-
```shell
96-
$ pip install -r requirements.txt
97-
```
9851

99-
### Demo
100-
Check out `demo.py` for an example program that walks you through the whole process! Just download the contents of this repo, make sure you have the dependencies listed above installed, and then run it like-a-this:
101-
```shell
102-
$ python ./demo.py
103-
```
52+
auth_iframe_url = iframe_api.get_authentication_url(username);
10453

105-
### Tests
106-
To run tests using [nose](http://nose.readthedocs.org/en/latest/) enter:
107-
```shell
108-
$ nosetests test
54+
# Add an <iframe> element to your HTML:
55+
# <iframe id="toopher_iframe" src=auth_iframe_url />
10956
```
11057

111-
#Using the Toopher IFRAME
112-
Toopher's IFRAME-based flow is the simplest way for web developers to integrate Toopher Two-Factor Authentication into an application.
58+
### Step 2: Validate the postback data
11359

114-
### Toopher IFRAME Overview
60+
After the Toopher-IFRAME results are posted back to server, the postback data can be validated one of two ways:
11561

116-
The IFRAME-based flow works by inserting an `<iframe>` element into the HTML displayed to the user after a successful username/password validation (but before they are actually logged-in to the service). The IFRAME URL is generated by our library and its content is served from the Toopher API server.
62+
#### 1. Check the authentication request status
63+
1. Call `is_authentication_granted` to check if the authentication request was granted.
11764

118-
The Authentication IFRAME guides the user through the process of pairing (if the user is not paired already) and authenticating with Toopher. Once complete, the IFRAME will return the result of the authentication to your server by `POST`ing the response via HTML to an endpoint of your choice. Your server validates the cryptographic signature using our library which determines whether or not the user successfully authenticated.
119-
120-
The User Management IFRAME is available if you would like to manage users separately from the authentication process. Once complete, the IFRAME will return the result of the pairing to your server by POSTing the response via HTML to an endpoint of your choice. Your server validates the cryptographic signature using our library which determines whether or not the user successfully paired.
121-
122-
### HTML Markup
123-
There is no difference in the markup required for an authentication vs. a user management IFRAME request (the generated URL embeds all relevant information).
124-
125-
The IFRAME element must have an id of `toopher_iframe`. Pages that include the Toopher IFRAME must include the accompanying javascript library `toopher-web.js` (located in `/assets/js/` in this repository). Toopher's IFRAME content is designed for a minimum size of 400x300 px. In the example below, `{{IFRAME_REQUEST_URL}}` is the authentication or user management URL generated by the ToopherIframe library. `{{POSTBACK_URL}}` is the path on your server where the Toopher-Iframe will submit the result of the authentication when it is finished.
65+
```python
66+
# Returns boolean indicating if user should be granted access
67+
authentication_request_granted = iframe_api.is_authentication_granted(form_data)
12668

127-
```html
128-
<!-- toopher-web.js requires jQuery. uncomment the following line to source it from CDNJS if it is not already included in your page -->
129-
<!-- <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> -->
130-
<script src="/js/toopher-web.js"></script>
131-
<iframe id="toopher_iframe" src="{{IFRAME_REQUEST_URL}}" toopher_postback="{{POSTBACK_URL}}" style="display:inline-block; height:300px; width:100%;"></iframe>
69+
if authentication_request_granted:
70+
# Success!
13271
```
13372

134-
### Authentication IFRAME Workflow
135-
#### Primary Authentication
136-
We recommend using some form of primary authentication before initiating a Toopher authentication request. Typical primary authentication methods involve verifying that the user has a valid username and password to access the resource being protected.
137-
138-
#### Step 1: Embed a request in an IFRAME
139-
After verifying the user's primary authentication, but before assuming the user's primary authentication checks out, the next step is to kickoff Toopher authentication.
140-
141-
1. Generate an authentication URL by specifying the request parameters to the library as detailed below
142-
2. Display a webpage to your user that embeds this URL within an `<iframe>` element. The markup requirements for the IFRAME element are described in the "HTML Markup" section above.
73+
#### 2. Process the postback
74+
Additional information regarding the AuthenticationRequest is easily obtained by using `process_postback`.
14375

144-
#### Step 2: Validate the postback data
145-
146-
##### Option 1: Process the postback
147-
1. Toopher-IFRAME results posted back to server.
148-
2. Call `process_postback()` to verify that the result is valid. `process_postback()` returns one of the following:
76+
1. Call `process_postback()` to verify that the result is valid. `process_postback()` returns one of the following:
14977
* an AuthenticationRequest object if the signature is valid (authentication url)
15078
* a `UserDisabledError`, `SignatureValidationError` or `ToopherAPIError` if the server encounters an error while processing postback
151-
3. If no errors were returned, the result of the authentication can be checked by evaluating `not authentication_request.pending and authentication_request.granted`.
152-
153-
##### Option 2: Check the authentication request status
154-
1. Toopher-IFRAME results posted back to server.
155-
2. Call `ToopherIframe.is_authentication_granted` to check if the authentication request was granted.
156-
157-
158-
#### Examples
159-
160-
##### Generating an Authentication IFRAME URL
161-
Though it is not required, every Toopher Authentication session can include a unique `request_token` - a randomized string that is included in the signed request to the Toopher API and returned in the signed response from the Toopher IFRAME. To guard against potential replay attacks, your code should validate that the returned `request_token` is the same one used to create the request.
162-
163-
Here's an example of creating a random request token and storing it in the server-side session using Django:
164-
165-
```python
166-
import random, string
167-
request_token = ''.join(random.choice(string.lowercase + string.digits) for i in range(15))
168-
request.session['ToopherRequestToken'] = request_token
169-
```
170-
171-
The Toopher Authentication API provides the requester a rich set of controls over authentication parameters.
79+
2. If no errors were returned, the result of the authentication can be checked by evaluating `not authentication_request.pending and authentication_request.granted`.
17280

173-
```python
174-
# Optional parameters: reset_email, request_token, action_name, requester_metadata, automation_allowed, challenge_required, and ttl
175-
auth_iframe_url = iframe_api.get_authentication_url(username, reset_email='email', request_token='token', action_name='action', requester_metadata, automation_allowed=automation_allowed, challenge_required=challenge_required, ttl=ttl);
176-
```
177-
178-
For the simple case of authenticating a user at login, use `get_authentication_url()` in this simple way:
179-
180-
```python
181-
login_iframe_url = iframe_api.get_authentication_url(username)
182-
```
183-
184-
##### Validating Postback Data from Authentication IFRAME & Parsing Errors
185-
In this example, `data` is a `dict` of the form data POSTed to your server from the Toopher Authentication IFRAME. You should replace the commented blocks in the `except` with code appropriate for the condition described in the comment.
186-
187-
There are two ways to validate postback data from an authentication IFRAME:
188-
189-
######Process Postback
19081
```python
19182
try:
19283
# Try to process the postback from the Toopher IFRAME and receive an AuthenticationRequest object.
@@ -206,68 +97,27 @@ except toopher.ToopherApiError as e:
20697
# The postback resource type was not valid.
20798
```
20899

209-
######Check Authentication Request Status
210-
```python
211-
# Returns boolean indicating if user should be granted access
212-
authentication_request_granted = iframe_api.is_authentication_granted(form_data)
213-
214-
if authentication_request_granted:
215-
# Success!
216-
```
217-
218-
###User Management IFRAME Workflow
219-
#### Primary Authentication
220-
We recommend using some form of primary authentication before initiating a Toopher pairing. Typical primary authentication methods involve verifying that the user has a valid username and password to access the resource being protected.
221-
222-
#### Step 1: Embed a request in an IFRAME
223-
After verifying the user's primary authentication, the next step is to kickoff Toopher pairing.
224-
225-
1. Generate a user management URL by specifying the request parameters to the library as detailed below
226-
2. Display a webpage to your user that embeds this URL within an `<iframe>` element. The markup requirements for the IFRAME element are described in the "HTML Markup" section above.
227100

228-
#### Step 2: Validate the postback data
229-
1. Toopher-IFRAME results posted back to server.
230-
2. Call `process_postback()` to verify that the result is valid. `process_postback()` returns one of the following:
231-
* a Pairing or User object if the signature is valid (authentication url)
232-
* a `UserDisabledError`, `SignatureValidationError` or `ToopherAPIError` if the server encounters an error while processing postback
233-
3. If no errors were returned and you received a Pairing object, the result of the pairing can be checked by evaluating `pairing.enabled`.
234-
235-
#### Examples
236-
##### Generating a User Management IFRAME URL
237-
The Toopher Authentication API provides the requester a rich set of controls over user management parameters.
101+
### Handling Errors
102+
If any request runs into an error a `ToopherApiError` will be thrown with more details on what went wrong.
238103

239-
```python
240-
# Optional parameter: reset_email
241-
pair_iframe_url = iframe_api.get_user_management_url(username, 'email')
104+
### Demo
105+
Check out `demo.py` for an example program that walks you through the whole process! Just download the contents of this repo, make sure you have the dependencies listed above installed, and then run it like-a-this:
106+
```shell
107+
$ python demo.py
242108
```
243109

244-
For the simple case of pairing a user, use `get_user_management_url()` in this simple way:
110+
## Contributing
111+
### Dependencies
112+
This library uses the [Requests](http://docs.python-requests.org/en/latest/) library and [OAuthLib](https://oauthlib.readthedocs.org/en/latest/index.html) to handle OAuth signing and make the web requests.
245113

246-
```python
247-
pair_iframe_url = iframe_api.get_user_management_url(username)
114+
Toopher uses [pip](https://pypi.python.org/pypi/pip) to install Python packages. To ensure all dependencies are up-to-date run:
115+
```shell
116+
$ pip install -r requirements.txt
248117
```
249118

250-
##### Validating Postback Data from User Management IFRAME & Parsing Errors
251-
In this example, `data` is a `dict` of the form data POSTed to your server from the Toopher Pairing IFRAME. You should replace the commented blocks in the `except` with code appropriate for the condition described in the comment.
252-
253-
There is one way to validate postback data from a user management IFRAME:
254-
255-
######Process Postback
256-
```python
257-
try:
258-
# Try to process the postback from the Toopher IFRAME and receive a Pairing or User object.
259-
postback_object = iframe_api.process_postback(form_data)
260-
261-
# If you got here and you have a pairing object, you just need to check the status of the pairing.
262-
if postback_object.enabled:
263-
#Success!
264-
265-
# There are three distinct errors ToopherAPI can return if the postback is not valid.
266-
except toopher.UserDisableError as e:
267-
# You have marked this user as Toopher disabled in the Toopher API
268-
except toopher.SignatureValidationError as e:
269-
# The postback was not valid for one of the following reasons:
270-
# missing keys, incorrect session token, expired signature or invalid signature.
271-
except toopher.ToopherApiError as e:
272-
# The postback resource type was not valid.
119+
### Tests
120+
To run tests using [nose](http://nose.readthedocs.org/en/latest/) enter:
121+
```shell
122+
$ nosetests test
273123
```

0 commit comments

Comments
 (0)