Skip to content

Instantly share code, notes, and snippets.

@emilyhorsman
Last active January 28, 2016 05:54
Show Gist options
  • Save emilyhorsman/9c640038a278490085e9 to your computer and use it in GitHub Desktop.
Save emilyhorsman/9c640038a278490085e9 to your computer and use it in GitHub Desktop.
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;
}
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