├── .gitignore ├── README.md ├── templates ├── home.html └── authorize.html ├── client.py └── app.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | *.pyc 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Example for OAuth 1 Server 2 | 3 | This is an example of OAuth 1 Server. 4 | 5 | Find more details on 6 | -------------------------------------------------------------------------------- /templates/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {% if user %} 9 |

You are {{ user.username }}

10 | {% else %} 11 |

You are not authenticated

12 | {% endif %} 13 | 14 |

Type any username:

15 |
16 | 17 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /templates/authorize.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Authorization 6 | 7 | 8 |

Client: {{ client.client_key }}

9 |

User: {{ user.username }}

10 |
11 |

Allow access?

12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /client.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from flask import Flask, session, url_for, request, jsonify 4 | from flask_oauthlib.client import OAuth 5 | 6 | 7 | app = Flask(__name__) 8 | app.debug = True 9 | app.secret_key = 'secret' 10 | 11 | # TODO: fill them 12 | CLIENT_KEY = '' 13 | CLIENT_SECRET = '' 14 | 15 | oauth = OAuth(app) 16 | remote = oauth.remote_app( 17 | 'remote', 18 | consumer_key=CLIENT_KEY, 19 | consumer_secret=CLIENT_SECRET, 20 | base_url='http://127.0.0.1:5000/api/', 21 | request_token_url='http://127.0.0.1:5000/oauth/request_token', 22 | access_token_method='GET', 23 | access_token_url='http://127.0.0.1:5000/oauth/access_token', 24 | authorize_url='http://127.0.0.1:5000/oauth/authorize', 25 | ) 26 | 27 | 28 | @app.route('/') 29 | def home(): 30 | if 'example_oauth' in session: 31 | resp = remote.get('me') 32 | return jsonify(resp.data) 33 | return remote.authorize(callback=url_for('authorized', _external=True)) 34 | 35 | 36 | @app.route('/authorized') 37 | @remote.authorized_handler 38 | def authorized(resp): 39 | if resp is None: 40 | return 'Access denied: error=%s' % ( 41 | request.args['error'] 42 | ) 43 | if 'oauth_token' in resp: 44 | session['example_oauth'] = resp 45 | return jsonify(resp) 46 | return str(resp) 47 | 48 | 49 | @remote.tokengetter 50 | def example_oauth_token(): 51 | if 'example_oauth' in session: 52 | resp = session['example_oauth'] 53 | return resp['oauth_token'], resp['oauth_token_secret'] 54 | 55 | 56 | import logging 57 | logger = logging.getLogger('flask_oauthlib') 58 | logger.addHandler(logging.StreamHandler()) 59 | logger.setLevel(logging.DEBUG) 60 | 61 | 62 | if __name__ == '__main__': 63 | app.run(port=8000) 64 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from flask import Flask 4 | from flask import session, request 5 | from flask import render_template, redirect 6 | from flask import jsonify 7 | from flask_sqlalchemy import SQLAlchemy 8 | from werkzeug.security import gen_salt 9 | from flask_oauthlib.provider import OAuth1Provider 10 | 11 | 12 | app = Flask(__name__, template_folder='templates') 13 | app.debug = True 14 | app.secret_key = 'secret' 15 | app.config.update({ 16 | 'SQLALCHEMY_DATABASE_URI': 'sqlite:///db.sqlite', 17 | }) 18 | db = SQLAlchemy(app) 19 | 20 | app.config.update({ 21 | 'OAUTH1_PROVIDER_ENFORCE_SSL': False, 22 | 'OAUTH1_PROVIDER_KEY_LENGTH': (10, 100), 23 | }) 24 | oauth = OAuth1Provider(app) 25 | 26 | 27 | class User(db.Model): 28 | id = db.Column(db.Integer, primary_key=True) 29 | username = db.Column(db.String(40), unique=True) 30 | 31 | 32 | class Client(db.Model): 33 | client_key = db.Column(db.String(40), primary_key=True) 34 | client_secret = db.Column(db.String(55), index=True, nullable=False) 35 | 36 | # creator of the client 37 | user_id = db.Column(db.ForeignKey('user.id')) 38 | user = db.relationship('User') 39 | _realms = db.Column(db.Text) 40 | _redirect_uris = db.Column(db.Text) 41 | 42 | @property 43 | def redirect_uris(self): 44 | if self._redirect_uris: 45 | return self._redirect_uris.split() 46 | return [] 47 | 48 | @property 49 | def default_redirect_uri(self): 50 | return self.redirect_uris[0] 51 | 52 | @property 53 | def default_realms(self): 54 | if self._realms: 55 | return self._realms.split() 56 | return [] 57 | 58 | 59 | class RequestToken(db.Model): 60 | id = db.Column(db.Integer, primary_key=True) 61 | user_id = db.Column( 62 | db.Integer, db.ForeignKey('user.id', ondelete='CASCADE') 63 | ) 64 | user = db.relationship('User') 65 | 66 | client_key = db.Column( 67 | db.String(40), db.ForeignKey('client.client_key'), 68 | nullable=False, 69 | ) 70 | client = db.relationship('Client') 71 | 72 | token = db.Column(db.String(255), index=True, unique=True) 73 | secret = db.Column(db.String(255), nullable=False) 74 | 75 | verifier = db.Column(db.String(255)) 76 | 77 | redirect_uri = db.Column(db.Text) 78 | _realms = db.Column(db.Text) 79 | 80 | @property 81 | def realms(self): 82 | if self._realms: 83 | return self._realms.split() 84 | return [] 85 | 86 | 87 | class Nonce(db.Model): 88 | id = db.Column(db.Integer, primary_key=True) 89 | 90 | timestamp = db.Column(db.Integer) 91 | nonce = db.Column(db.String(40)) 92 | client_key = db.Column( 93 | db.String(40), db.ForeignKey('client.client_key'), 94 | nullable=False, 95 | ) 96 | client = db.relationship('Client') 97 | request_token = db.Column(db.String(50)) 98 | access_token = db.Column(db.String(50)) 99 | 100 | 101 | class AccessToken(db.Model): 102 | id = db.Column(db.Integer, primary_key=True) 103 | client_key = db.Column( 104 | db.String(40), db.ForeignKey('client.client_key'), 105 | nullable=False, 106 | ) 107 | client = db.relationship('Client') 108 | 109 | user_id = db.Column( 110 | db.Integer, db.ForeignKey('user.id'), 111 | ) 112 | user = db.relationship('User') 113 | 114 | token = db.Column(db.String(255)) 115 | secret = db.Column(db.String(255)) 116 | 117 | _realms = db.Column(db.Text) 118 | 119 | @property 120 | def realms(self): 121 | if self._realms: 122 | return self._realms.split() 123 | return [] 124 | 125 | 126 | def current_user(): 127 | if 'id' in session: 128 | uid = session['id'] 129 | return User.query.get(uid) 130 | return None 131 | 132 | 133 | @app.route('/', methods=('GET', 'POST')) 134 | def home(): 135 | if request.method == 'POST': 136 | username = request.form.get('username') 137 | user = User.query.filter_by(username=username).first() 138 | if not user: 139 | user = User(username=username) 140 | db.session.add(user) 141 | db.session.commit() 142 | session['id'] = user.id 143 | return redirect('/') 144 | user = current_user() 145 | return render_template('home.html', user=user) 146 | 147 | 148 | @app.route('/client') 149 | def client(): 150 | user = current_user() 151 | if not user: 152 | return redirect('/') 153 | item = Client( 154 | client_key=gen_salt(40), 155 | client_secret=gen_salt(50), 156 | _redirect_uris='http://127.0.0.1:8000/authorized', 157 | user_id=user.id, 158 | ) 159 | db.session.add(item) 160 | db.session.commit() 161 | return jsonify( 162 | client_key=item.client_key, 163 | client_secret=item.client_secret 164 | ) 165 | 166 | 167 | @oauth.clientgetter 168 | def load_client(client_key): 169 | return Client.query.get(client_key) 170 | 171 | 172 | @oauth.grantgetter 173 | def load_request_token(token): 174 | return RequestToken.query.filter_by(token=token).first() 175 | 176 | 177 | @oauth.grantsetter 178 | def save_request_token(token, request): 179 | if hasattr(oauth, 'realms') and oauth.realms: 180 | realms = ' '.join(request.realms) 181 | else: 182 | realms = None 183 | grant = RequestToken( 184 | token=token['oauth_token'], 185 | secret=token['oauth_token_secret'], 186 | client=request.client, 187 | redirect_uri=request.redirect_uri, 188 | _realms=realms, 189 | ) 190 | db.session.add(grant) 191 | db.session.commit() 192 | return grant 193 | 194 | 195 | @oauth.verifiergetter 196 | def load_verifier(verifier, token): 197 | return RequestToken.query.filter_by( 198 | verifier=verifier, token=token 199 | ).first() 200 | 201 | 202 | @oauth.verifiersetter 203 | def save_verifier(token, verifier, *args, **kwargs): 204 | tok = RequestToken.query.filter_by(token=token).first() 205 | tok.verifier = verifier['oauth_verifier'] 206 | tok.user = current_user() 207 | db.session.add(tok) 208 | db.session.commit() 209 | return tok 210 | 211 | 212 | @oauth.noncegetter 213 | def load_nonce(client_key, timestamp, nonce, request_token, access_token): 214 | return Nonce.query.filter_by( 215 | client_key=client_key, timestamp=timestamp, nonce=nonce, 216 | request_token=request_token, access_token=access_token, 217 | ).first() 218 | 219 | 220 | @oauth.noncesetter 221 | def save_nonce(client_key, timestamp, nonce, request_token, access_token): 222 | nonce = Nonce( 223 | client_key=client_key, 224 | timestamp=timestamp, 225 | nonce=nonce, 226 | request_token=request_token, 227 | access_token=access_token, 228 | ) 229 | db.session.add(nonce) 230 | db.session.commit() 231 | return nonce 232 | 233 | 234 | @oauth.tokengetter 235 | def load_access_token(client_key, token, *args, **kwargs): 236 | return AccessToken.query.filter_by( 237 | client_key=client_key, token=token 238 | ).first() 239 | 240 | 241 | @oauth.tokensetter 242 | def save_access_token(token, request): 243 | tok = AccessToken( 244 | client=request.client, 245 | user=request.user, 246 | token=token['oauth_token'], 247 | secret=token['oauth_token_secret'], 248 | _realms=token['oauth_authorized_realms'], 249 | ) 250 | db.session.add(tok) 251 | db.session.commit() 252 | 253 | 254 | @app.route('/oauth/request_token') 255 | @oauth.request_token_handler 256 | def request_token(): 257 | return {} 258 | 259 | 260 | @app.route('/oauth/access_token') 261 | @oauth.access_token_handler 262 | def access_token(): 263 | return {} 264 | 265 | 266 | @app.route('/oauth/authorize', methods=['GET', 'POST']) 267 | @oauth.authorize_handler 268 | def authorize(*args, **kwargs): 269 | user = current_user() 270 | if not user: 271 | return redirect('/') 272 | if request.method == 'GET': 273 | client_key = kwargs.get('resource_owner_key') 274 | client = Client.query.filter_by(client_key=client_key).first() 275 | kwargs['client'] = client 276 | kwargs['user'] = user 277 | return render_template('authorize.html', **kwargs) 278 | confirm = request.form.get('confirm', 'no') 279 | return confirm == 'yes' 280 | 281 | 282 | @app.route('/api/me') 283 | @oauth.require_oauth() 284 | def me(req): 285 | user = req.user 286 | return jsonify(username=user.username) 287 | 288 | 289 | import logging 290 | logger = logging.getLogger('flask_oauthlib') 291 | logger.addHandler(logging.StreamHandler()) 292 | logger.setLevel(logging.DEBUG) 293 | 294 | 295 | if __name__ == '__main__': 296 | db.create_all() 297 | app.run() 298 | --------------------------------------------------------------------------------