diff --git a/app/__init__.py b/app/__init__.py index 00c510c..3747067 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -3,7 +3,7 @@ from flask import Flask, request, session, redirect, url_for from flask_login import LoginManager from flask_sqlalchemy import SQLAlchemy as SA from flask_migrate import Migrate -from flask_oauthlib.client import OAuth +from authlib.flask.client import OAuth as AuthlibOAuth from sqlalchemy.exc import OperationalError # subclass SQLAlchemy to enable pool_pre_ping @@ -29,7 +29,7 @@ login_manager = LoginManager() login_manager.init_app(app) db = SQLAlchemy(app) # database migrate = Migrate(app, db) # flask-migrate -oauth_client = OAuth(app) # oauth +authlib_oauth_client = AuthlibOAuth(app) # authlib oauth if app.config.get('SAML_ENABLED') and app.config.get('SAML_ENCRYPT'): from app.lib import certutil diff --git a/app/models.py b/app/models.py index 116053f..fd540ed 100644 --- a/app/models.py +++ b/app/models.py @@ -1875,10 +1875,17 @@ class Setting(db.Model): 'google_oauth_enabled': False, 'google_oauth_client_id':'', 'google_oauth_client_secret':'', - 'google_token_url': 'https://accounts.google.com/o/oauth2/token', - 'google_token_params': {'scope': 'email profile'}, - 'google_authorize_url':'https://accounts.google.com/o/oauth2/auth', - 'google_base_url':'https://www.googleapis.com/oauth2/v1/', + 'google_token_url': 'https://oauth2.googleapis.com/token', + 'google_oauth_scope': 'openid email profile', + 'google_authorize_url':'https://accounts.google.com/o/oauth2/v2/auth', + 'google_base_url':'https://www.googleapis.com/oauth2/v3/', + 'oidc_oauth_enabled': False, + 'oidc_oauth_key': '', + 'oidc_oauth_secret': '', + 'oidc_oauth_scope': 'email', + 'oidc_oauth_api_url': '', + 'oidc_oauth_token_url': '', + 'oidc_oauth_authorize_url': '', 'forward_records_allow_edit': {'A': True, 'AAAA': True, 'AFSDB': False, 'ALIAS': False, 'CAA': True, 'CERT': False, 'CDNSKEY': False, 'CDS': False, 'CNAME': True, 'DNSKEY': False, 'DNAME': False, 'DS': False, 'HINFO': False, 'KEY': False, 'LOC': True, 'MX': True, 'NAPTR': False, 'NS': True, 'NSEC': False, 'NSEC3': False, 'NSEC3PARAM': False, 'OPENPGPKEY': False, 'PTR': True, 'RP': False, 'RRSIG': False, 'SOA': False, 'SPF': True, 'SSHFP': False, 'SRV': True, 'TKEY': False, 'TSIG': False, 'TLSA': False, 'SMIMEA': False, 'TXT': True, 'URI': False}, 'reverse_records_allow_edit': {'A': False, 'AAAA': False, 'AFSDB': False, 'ALIAS': False, 'CAA': False, 'CERT': False, 'CDNSKEY': False, 'CDS': False, 'CNAME': False, 'DNSKEY': False, 'DNAME': False, 'DS': False, 'HINFO': False, 'KEY': False, 'LOC': True, 'MX': False, 'NAPTR': False, 'NS': True, 'NSEC': False, 'NSEC3': False, 'NSEC3PARAM': False, 'OPENPGPKEY': False, 'PTR': True, 'RP': False, 'RRSIG': False, 'SOA': False, 'SPF': False, 'SSHFP': False, 'SRV': False, 'TKEY': False, 'TSIG': False, 'TLSA': False, 'SMIMEA': False, 'TXT': True, 'URI': False}, } diff --git a/app/oauth.py b/app/oauth.py index 17fd045..a578341 100644 --- a/app/oauth.py +++ b/app/oauth.py @@ -1,44 +1,44 @@ from ast import literal_eval from flask import request, session, redirect, url_for -from app import app, oauth_client +from app import app, authlib_oauth_client from app.models import Setting # TODO: -# - Replace Flask-OAuthlib by authlib # - Fix github/google enabling (Currently need to reload the flask app) def github_oauth(): if not Setting().get('github_oauth_enabled'): return None - github = oauth_client.remote_app( + def fetch_github_token(): + return session.get('github_token') + + github = authlib_oauth_client.register( 'github', - consumer_key = Setting().get('github_oauth_key'), - consumer_secret = Setting().get('github_oauth_secret'), + client_id = Setting().get('github_oauth_key'), + client_secret = Setting().get('github_oauth_secret'), request_token_params = {'scope': Setting().get('github_oauth_scope')}, - base_url = Setting().get('github_oauth_api_url'), + api_base_url = Setting().get('github_oauth_api_url'), request_token_url = None, - access_token_method = 'POST', access_token_url = Setting().get('github_oauth_token_url'), - authorize_url = Setting().get('github_oauth_authorize_url') + authorize_url = Setting().get('github_oauth_authorize_url'), + client_kwargs={'scope': Setting().get('github_oauth_scope')}, + fetch_token=fetch_github_token, ) @app.route('/github/authorized') def github_authorized(): session['github_oauthredir'] = url_for('.github_authorized', _external=True) - resp = github.authorized_response() - if resp is None: + token = github.authorize_access_token() + if token is None: return 'Access denied: reason=%s error=%s' % ( request.args['error'], request.args['error_description'] ) - session['github_token'] = (resp['access_token'], '') + session['github_token'] = (token) return redirect(url_for('.login')) - @github.tokengetter - def get_github_oauth_token(): - return session.get('github_token') return github @@ -47,31 +47,65 @@ def google_oauth(): if not Setting().get('google_oauth_enabled'): return None - google = oauth_client.remote_app( + def fetch_google_token(): + return session.get('google_token') + print("afkafna") + + google = authlib_oauth_client.register( 'google', - consumer_key=Setting().get('google_oauth_client_id'), - consumer_secret=Setting().get('google_oauth_client_secret'), - request_token_params=literal_eval(Setting().get('google_token_params')), - base_url=Setting().get('google_base_url'), + client_id=Setting().get('google_oauth_client_id'), + client_secret=Setting().get('google_oauth_client_secret'), + api_base_url=Setting().get('google_base_url'), request_token_url=None, - access_token_method='POST', access_token_url=Setting().get('google_token_url'), authorize_url=Setting().get('google_authorize_url'), + client_kwargs={'scope': Setting().get('google_oauth_scope')}, + fetch_token=fetch_google_token, ) @app.route('/google/authorized') def google_authorized(): - resp = google.authorized_response() - if resp is None: + session['google_oauthredir'] = url_for('.google_authorized', _external=True) + token = google.authorize_access_token() + if token is None: return 'Access denied: reason=%s error=%s' % ( request.args['error_reason'], request.args['error_description'] ) - session['google_token'] = (resp['access_token'], '') + session['google_token'] = (token) return redirect(url_for('.login')) - @google.tokengetter - def get_google_oauth_token(): - return session.get('google_token') - return google + +def oidc_oauth(): + if not Setting().get('oidc_oauth_enabled'): + return None + + def fetch_oidc_token(): + return session.get('oidc_token') + + oidc = authlib_oauth_client.register( + 'oidc', + client_id = Setting().get('oidc_oauth_key'), + client_secret = Setting().get('oidc_oauth_secret'), + api_base_url = Setting().get('oidc_oauth_api_url'), + request_token_url = None, + access_token_url = Setting().get('oidc_oauth_token_url'), + authorize_url = Setting().get('oidc_oauth_authorize_url'), + client_kwargs={'scope': Setting().get('oidc_oauth_scope')}, + fetch_token=fetch_oidc_token, + ) + + @app.route('/oidc/authorized') + def oidc_authorized(): + session['oidc_oauthredir'] = url_for('.oidc_authorized', _external=True) + token = oidc.authorize_access_token() + if token is None: + return 'Access denied: reason=%s error=%s' % ( + request.args['error'], + request.args['error_description'] + ) + session['oidc_token'] = (token) + return redirect(url_for('.login')) + + return oidc \ No newline at end of file diff --git a/app/templates/admin_setting_authentication.html b/app/templates/admin_setting_authentication.html index 8bb629b..9ad623f 100644 --- a/app/templates/admin_setting_authentication.html +++ b/app/templates/admin_setting_authentication.html @@ -52,6 +52,7 @@
  • LDAP
  • Google OAuth
  • Github OAuth
  • +
  • OpenID Connect OAuth
  • @@ -271,8 +272,8 @@
    - - + +
    @@ -352,8 +353,63 @@ Help

    Fill in all the fields in the left form.

    +
    + +
    +
    +
    +
    + +
    + GENERAL +
    + + +
    +
    + + + +
    +
    + + + +
    +
    +
    + ADVANCE +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    + +
    +
    +
    +
    + Help +

    Fill in all the fields in the left form.

    +
    -
    @@ -499,14 +555,14 @@ $('#google_oauth_client_id').prop('required', true); $('#google_oauth_client_secret').prop('required', true); $('#google_token_url').prop('required', true); - $('#google_token_params').prop('required', true); + $('#google_oauth_scope').prop('required', true); $('#google_authorize_url').prop('required', true); $('#google_base_url').prop('required', true); } else { $('#google_oauth_client_id').prop('required', false); $('#google_oauth_client_secret').prop('required', false); $('#google_token_url').prop('required', false); - $('#google_token_params').prop('required', false); + $('#google_oauth_scope').prop('required', false); $('#google_authorize_url').prop('required', false); $('#google_base_url').prop('required', false); } @@ -517,7 +573,7 @@ $('#google_oauth_client_id').prop('required', true); $('#google_oauth_client_secret').prop('required', true); $('#google_token_url').prop('required', true); - $('#google_token_params').prop('required', true); + $('#google_oauth_scope').prop('required', true); $('#google_authorize_url').prop('required', true); $('#google_base_url').prop('required', true); {% endif %} @@ -546,9 +602,8 @@ $('#github_oauth_authorize_url').prop('required', false); } }); - // init validation requirement at first time page load - {% if SETTING.get('google_oauth_enabled') %} + {% if SETTING.get('github_oauth_enabled') %} $('#github_oauth_key').prop('required', true); $('#github_oauth_secret').prop('required', true); $('#github_oauth_scope').prop('required', true); @@ -558,5 +613,38 @@ {% endif %} // END: Github tab js + // START: OIDC tab js + $('#oidc_oauth_enabled').iCheck({ + checkboxClass : 'icheckbox_square-blue', + increaseArea : '20%' + }).on('ifChanged', function(e) { + var is_enabled = e.currentTarget.checked; + if (is_enabled){ + $('#oidc_oauth_key').prop('required', true); + $('#oidc_oauth_secret').prop('required', true); + $('#oidc_oauth_scope').prop('required', true); + $('#oidc_oauth_api_url').prop('required', true); + $('#oidc_oauth_token_url').prop('required', true); + $('#oidc_oauth_authorize_url').prop('required', true); + } else { + $('#oidc_oauth_key').prop('required', false); + $('#oidc_oauth_secret').prop('required', false); + $('#oidc_oauth_scope').prop('required', false); + $('#oidc_oauth_api_url').prop('required', false); + $('#oidc_oauth_token_url').prop('required', false); + $('#oidc_oauth_authorize_url').prop('required', false); + } + }); + // init validation requirement at first time page load + {% if SETTING.get('oidc_oauth_enabled') %} + $('#oidc_oauth_key').prop('required', true); + $('#oidc_oauth_secret').prop('required', true); + $('#oidc_oauth_scope').prop('required', true); + $('#oidc_oauth_api_url').prop('required', true); + $('#oidc_oauth_token_url').prop('required', true); + $('#oidc_oauth_authorize_url').prop('required', true); + {% endif %} + //END: OIDC Tab JS + {% endblock %} diff --git a/app/templates/login.html b/app/templates/login.html index 54c24bc..46ae8c0 100644 --- a/app/templates/login.html +++ b/app/templates/login.html @@ -83,14 +83,17 @@ - {% if SETTING.get('google_oauth_enabled') or SETTING.get('github_oauth_enabled') %} + {% if SETTING.get('google_oauth_enabled') or SETTING.get('github_oauth_enabled') or SETTING.get('oidc_oauth_enabled') %}