Last active
January 28, 2016 05:54
-
-
Save emilyhorsman/9c640038a278490085e9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if (qs('oauth_token') && qs('oauth_verifier')) { | |
var url = '/auth/callback/twitter?' + window.location.search.substring(1); | |
fetch(url, { credentials: 'same-origin' }) | |
.then(function(res) { | |
return res.json(); | |
}) | |
.then(function(json) { | |
console.log(json); | |
if (json['status'] === 'success') { | |
whoami(); | |
} | |
}) | |
; | |
} else { | |
fetch('/auth/twitter', { credentials: 'same-origin' }) | |
.then(function(res) { | |
return res.json(); | |
}) | |
.then(function(json) { | |
window.location.replace(json['redirect']) | |
}) | |
; | |
} | |
function whoami() { | |
var url = '/whoami'; | |
fetch(url, { credentials: 'same-origin' }) | |
.then(function(res) { | |
return res.json(); | |
}) | |
.then(function(json) { | |
console.log(json); | |
}) | |
; | |
} | |
function qs(key) { | |
var query = window.location.search.substring(1); | |
var vars = query.split("&"); | |
for (var i = 0; i < vars.length; i++) { | |
var pair = vars[i].split("="); | |
if (pair[0] === key) { | |
return pair[1]; | |
} | |
} | |
return false; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import os | |
from urllib.parse import parse_qsl, quote | |
import oauth2 | |
import jwt | |
from flask import ( | |
Flask, request, current_app, | |
make_response, jsonify | |
) | |
import nightshades | |
nightshades.load_dotenv() | |
app = Flask(__name__) | |
twitter_consumer = oauth2.Consumer( | |
key = os.environ.get('NIGHTSHADES_TWITTER_CONSUMER_KEY'), | |
secret = os.environ.get('NIGHTSHADES_TWITTER_CONSUMER_SECRET')) | |
facebook_consumer = oauth2.Consumer( | |
key = os.environ.get('NIGHTSHADES_FACEBOOK_APP_ID'), | |
secret = os.environ.get('NIGHTSHADES_FACEBOOK_APP_SECRET')) | |
facebook_callback_url = quote('http://api.nightshades.xyz:5000/auth/callback/facebook') | |
@app.route('/auth/facebook') | |
def start_facebook_flow(): | |
url = 'https://www.facebook.com/dialog/oauth?client_id={}&redirect_uri={}' | |
url = url.format(facebook_consumer.key, facebook_callback_url) | |
return jsonify({ 'redirect': url }) | |
@app.route('/auth/callback/facebook') | |
def complete_facebook_flow(): | |
client = oauth2.Client(facebook_consumer) | |
code = request.args.get('code', False) | |
url = 'https://graph.facebook.com/v2.5/oauth/access_token?client_id={}&redirect_uri={}&client_secret={}&code={}' | |
url = url.format(facebook_consumer.key, facebook_callback_url, facebook_consumer.secret, code) | |
resp, content = client.request(url, 'GET') | |
res = json.loads(content.decode('utf-8')) | |
access_token = res.get('access_token') | |
url = 'https://graph.facebook.com/debug_token?input_token={}&access_token={}' | |
url = url.format(access_token, access_token) | |
resp, content = client.request(url, 'GET') | |
res = json.loads(content.decode('utf-8')) | |
user_id = res.get('data', {}).get('user_id') | |
url = 'https://graph.facebook.com/v2.5/{}?access_token={}' | |
url = url.format(user_id, access_token) | |
resp, content = client.request(url, 'GET') | |
res = json.loads(content.decode('utf-8')) | |
name = res.get('name') | |
resp = make_response(jsonify({ 'status': 'success' })) | |
payload = { | |
'user_id': user_id, | |
'name': name | |
} | |
token = jwt.encode(payload, current_app.secret_key) | |
resp.set_cookie('jwt', token) | |
return resp | |
@app.route('/whoami') | |
def whoami(): | |
payload = request.cookies.get('jwt') | |
try: | |
payload = jwt.decode(payload, current_app.secret_key) | |
return jsonify({ 'name': payload['name'] }) | |
except: | |
abort(400) | |
@app.route('/auth/twitter') | |
def start_twitter_flow(): | |
client = oauth2.Client(twitter_consumer) | |
# Get a unique oauth_token and oauth_token_secret to begin our OAuth flow. | |
url = 'https://api.twitter.com/oauth/request_token' | |
resp, content = client.request(url, 'GET') | |
if resp.status != 200: | |
abort(400) | |
oauth_values = dict(parse_qsl(content.decode('utf-8'))) | |
oauth_token = oauth_values.get('oauth_token') | |
oauth_token_secret = oauth_values.get('oauth_token_secret') | |
if not oauth_token or not oauth_token_secret: | |
abort(400) | |
url = 'https://api.twitter.com/oauth/authenticate?oauth_token={}' | |
url = url.format(oauth_token) | |
# The fetch API `redirect: manual` doesn't seem to work right now, so | |
# return the URL the client will need to hit to get back an oauth_verifier | |
resp = make_response(jsonify({ 'redirect': url })) | |
# Set a JSON web token containing the oauth_token_secret | |
payload = { | |
'oauth_flow': { | |
'token_secret': oauth_token_secret | |
} | |
} | |
token = jwt.encode(payload, current_app.secret_key) | |
resp.set_cookie('jwt', token, httponly=True) | |
return resp | |
@app.route('/auth/callback/twitter') | |
def twitter_callback(): | |
# Query string from Twitter contains token and verifier | |
oauth_verifier = request.args.get('oauth_verifier') | |
oauth_token = request.args.get('oauth_token') | |
if not oauth_verifier or not oauth_token: | |
abort(400) | |
# Our JSON web token in the request cookies contains the token secret from | |
# the flow initiation. | |
payload = request.cookies.get('jwt') | |
try: | |
payload = jwt.decode(payload, current_app.secret_key) | |
oauth_token_secret = payload['oauth_flow']['token_secret'] | |
except: | |
abort(400) | |
token = oauth2.Token(oauth_token, oauth_token_secret) | |
token.set_verifier(oauth_verifier) | |
# Grab the OAuth access token and user ID from the provider | |
url = 'https://api.twitter.com/oauth/access_token' | |
client = oauth2.Client(twitter_consumer, token) | |
resp, content = client.request(url, 'POST') | |
if resp.status != 200: | |
abort(400) | |
provider_user = dict(parse_qsl(content.decode('utf-8'))) | |
resp = make_response(jsonify({ 'status': 'success' })) | |
# Set a JSON web token with the user_id from the provider | |
payload = { | |
'user_id': provider_user.get('user_id'), | |
'name': provider_user.get('screen_name') | |
} | |
token = jwt.encode(payload, current_app.secret_key) | |
resp.set_cookie('jwt', token) | |
return resp | |
@app.route('/') | |
def index(): | |
return app.send_static_file('index.html') | |
@app.route('/index.js') | |
def indexjs(): | |
return app.send_static_file('index.js') | |
app.debug = True | |
app.secret_key = os.urandom(24) | |
app.run(host='0.0.0.0') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment