8000 A design pattern for using tokens · doismellburning/github3.py@b235a75 · GitHub
[go: up one dir, main page]

Skip to content

Commit b235a75

Browse files
committed
A design pattern for using tokens
I saw someone using plain-text username and password files to store user information in their application. It frankly made me cringe, so I thought I would add this to help them and others along. [ci skip]
1 parent 5171ad8 commit b235a75

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

docs/examples/oauth.rst

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
.. _oauth:
2+
3+
Using Tokens for Your Projects
4+
------------------------------
5+
6+
Let's say you're designing an application that uses github3.py. If your
7+
intention is to have users authenticate, you have a few options.
8+
9+
1. Ask the user to enter their credentials each time they start the
10+
application. (Or save the username somewhere, and just ask for the
11+
password.)
12+
2. Ask the user to supply their credentials once and store them somewhere for
13+
later use. (**VERY VERY BAD**)
14+
3. Ask the user to supply their credentials once, get an authorization token
15+
and store that for later use.
16+
17+
The first isn't a bad method at all, it just unfortunately may lead to unhappy
18+
users, this should always be an option though. The second (as I already noted)
19+
is a bad idea. Even if you obfuscate the username and password, they can still
20+
be discovered and no level of obfuscation is clever enough. (May I also take
21+
this moment to remind people that base64 is **not** encryption.) The last is
22+
probably the least objectionable of the evils. The token has scopes so there
23+
is only so much someone can do with it and it works well with github3.py.
24+
25+
Requesting a token
26+
------------------
27+
28+
If you're not doing a web application, you are more than welcome to use
29+
github3.py (otherwise work with redirects_). Let's say your application needs
30+
access to public and private repositories, and the users but not to gists.
31+
Your scopes_ should be ``['user', 'repo']``. I'm also assuming your
32+
application will not be deleting any repositories. The only things left to do
33+
are collect the username and password and give a good description for your
34+
application.
35+
36+
::
37+
38+
from github3 import authorize
39+
from getpass import getuser, getpass
40+
41+
user = getuser()
42+
password = ''
43+
44+
while not password:
45+
password = getpass('Password for {0}: '.format(user))
46+
47+
note = 'github3.py example app'
48+
note_url = 'http://example.com'
49+
scopes = ['user', 'repo']
50+
51+
auth = authorize(user, password, scopes, note, note_url)
52+
53+
with open(CREDENTIALS_FILE, 'w') as fd:
54+
fd.write(auth.token + '\n')
55+
fd.write(auth.id)
56+
57+
In the future, you can then read that token in without having to bother your
58+
user. If at some later point in the lifetime of your application you need more
59+
privileges, you simply do the following:
60+
61+
::
62+
63+
from github3 import login
64+
65+
token = id = ''
66+
with open(CREDENTIALS_FILE, 'r') as fd:
67+
token = fd.readline().strip() # Can't hurt to be paranoid
68+
id = fd.readline().strip()
69+
70+
gh = login(token=token)
71+
auth = gh.authorization(id)
72+
auth.update(add_scopes=['repo:status', 'gist'], rm_scopes=['user'])
73+
74+
# if you want to be really paranoid, you can then test:
75+
# token == auth.token
76+
# in case the update changes the token
77+
78+
Hopefully this helps someone.
79+
80+
.. _redirects: http://developer.github.com/v3/oauth/#redirect-urls
81+
.. _scopes: http://developer.github.com/v3/oauth/#scopes

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ More Examples
4444
.. toctree::
4545
:maxdepth: 2
4646

47+
examples/oauth
4748
examples/gist
4849
examples/github
4950
examples/issue

0 commit comments

Comments
 (0)
0