diff --git a/basic_auth/__init__.py b/basic_auth/__init__.py index db5746d..d9f0179 100644 --- a/basic_auth/__init__.py +++ b/basic_auth/__init__.py @@ -4,6 +4,7 @@ from flask_sqlalchemy import SQLAlchemy from basic_auth.exceptions import BaseExceptions, SessionExpired, MissingSessionID from basic_auth.config import config +from flask_oauthlib.client import OAuth import os @@ -18,6 +19,7 @@ api = swagger.docs(Api(app), apiVersion='0.1', api_spec_url='/spec', description="basic authentications") db = SQLAlchemy(app) +oauth = OAuth(app) from basic_auth.resources.auth import AuthAPI diff --git a/basic_auth/config.py b/basic_auth/config.py index 41d4e51..305c74b 100644 --- a/basic_auth/config.py +++ b/basic_auth/config.py @@ -10,10 +10,14 @@ class BaseConfig(object): APP_SECRET = "basic_auth" SQLALCHEMY_DATABASE_URI = '' + GOOGLE_ID = "cloud.google.com/console and get your ID" + GOOGLE_SECRET = "cloud.google.com/console and get the secret" class DevelopmentConfig(BaseConfig): SQLALCHEMY_DATABASE_URI = 'mysql+mysqldb://basic_auth:eJTy5mn7shrHmU9c@localhost/basic_auth' + GOOGLE_ID = "898576985793-1oaem52t1huruq0k1s6hirvc91ulpm5k.apps.googleusercontent.com" + GOOGLE_SECRET = "dflBTM76uotZw6NZh0rhQP-z" class TestingConfig(BaseConfig): diff --git a/basic_auth/exceptions.py b/basic_auth/exceptions.py index 4df2381..2983e6e 100644 --- a/basic_auth/exceptions.py +++ b/basic_auth/exceptions.py @@ -46,16 +46,23 @@ class UnAuthorized(BaseExceptions): extra_fields = ['expected_type'] +class InvalidGoogleAUTH(BaseExceptions): + message = "user is not valid" + code = 103 + status_code = 401 + extra_fields = ['expected_type'] + + class SessionExpired(BaseExceptions): message = "session has expired" - code = 103 + code = 104 status_code = 401 extra_fields = ['message'] class UserNotFound(BaseExceptions): message = "UnAuthorized User" - code = 104 + code = 105 status_code = 404 extra_fields = ['message'] diff --git a/basic_auth/resources/auth.py b/basic_auth/resources/auth.py index f9262fb..b146b30 100644 --- a/basic_auth/resources/auth.py +++ b/basic_auth/resources/auth.py @@ -1,9 +1,10 @@ +from flask import current_app from flask_restful import Resource, reqparse, marshal_with from flask_restful_swagger import swagger -from basic_auth.schemes import Auth, UserAuth -from basic_auth.models.users import get_user, get_session_by_id, generate_session, update_session -from basic_auth.exceptions import UnAuthorized - +from basic_auth.schemes import Auth, UserAuth, OAuth2 +from basic_auth.models.users import get_user, get_session_by_user_id, generate_session, update_session +from basic_auth.exceptions import UnAuthorized, InvalidGoogleAUTH +from basic_auth import oauth auth_parser = reqparse.RequestParser() auth_parser.add_argument('username', type=str, required=True) @@ -43,7 +44,7 @@ def post(self): user = get_user(username) if user is not None: if user.bcrypt_password == password: - session = get_session_by_id(user.user_id) + session = get_session_by_user_id(user.user_id) if session is None: session = generate_session(user.user_id) if session.is_expired: diff --git a/basic_auth/schemes.py b/basic_auth/schemes.py index feb68db..8df6892 100644 --- a/basic_auth/schemes.py +++ b/basic_auth/schemes.py @@ -22,6 +22,15 @@ class UserAuth(object): required = ['username', 'password'] +@swagger.model +class OAuth2(object): + + resource_fields = { + 'user_info': fields.Raw() + } + required = [] + + @swagger.model class User(object): """docstring for User""" diff --git a/tests/google.py b/tests/google.py new file mode 100644 index 0000000..9ead751 --- /dev/null +++ b/tests/google.py @@ -0,0 +1,70 @@ +""" + google example + ~~~~~~~~~~~~~~ + This example is contributed by Bruno Rocha + GitHub: https://github.com/rochacbruno +""" +from flask import Flask, redirect, url_for, session, request, jsonify +from flask_oauthlib.client import OAuth + +app = Flask(__name__) +app.config['GOOGLE_ID'] = "898576985793-1oaem52t1huruq0k1s6hirvc91ulpm5k.apps.googleusercontent.com" +app.config['GOOGLE_SECRET'] = "dflBTM76uotZw6NZh0rhQP-z" +app.debug = True +app.secret_key = 'development' +oauth = OAuth(app) + +google = oauth.remote_app( + 'google', + consumer_key=app.config.get('GOOGLE_ID'), + consumer_secret=app.config.get('GOOGLE_SECRET'), + request_token_params={ + 'scope': 'email' + }, + base_url='https://www.googleapis.com/oauth2/v1/', + request_token_url=None, + access_token_method='POST', + access_token_url='https://accounts.google.com/o/oauth2/token', + authorize_url='https://accounts.google.com/o/oauth2/auth', +) + + +@app.route('/') +def index(): + if 'google_token' in session: + me = google.get('userinfo') + return jsonify({"data": me.data}) + return redirect(url_for('login')) + + +@app.route('/login') +def login(): + return google.authorize(callback=url_for('authorized', _external=True)) + + +@app.route('/logout') +def logout(): + session.pop('google_token', None) + return redirect(url_for('index')) + + +@app.route('/login/authorized') +def authorized(): + resp = google.authorized_response() + if resp is None: + return 'Access denied: reason=%s error=%s' % ( + request.args['error_reason'], + request.args['error_description'] + ) + session['google_token'] = (resp['access_token'], '') + me = google.get('userinfo') + return jsonify({"data": me.data}) + + +@google.tokengetter +def get_google_oauth_token(): + return session.get('google_token') + + +if __name__ == '__main__': + app.run() \ No newline at end of file