refactor, implement next attribute, for forward, service need user approve berfore redirect
This commit is contained in:
parent
77962edd15
commit
5037fe4def
|
@ -144,9 +144,9 @@ def oidc_provider_init_app(name=None):
|
||||||
|
|
||||||
app.babel = Babel(app)
|
app.babel = Babel(app)
|
||||||
app.login_manager = LoginManager(app)
|
app.login_manager = LoginManager(app)
|
||||||
init_login_manager(app)
|
|
||||||
|
|
||||||
from .views import oidc_provider_views, auth_views, frontend_views
|
from .views import oidc_provider_views, auth_views, frontend_views, init_login_manager
|
||||||
|
init_login_manager(app)
|
||||||
app.register_blueprint(oidc_provider_views)
|
app.register_blueprint(oidc_provider_views)
|
||||||
app.register_blueprint(auth_views)
|
app.register_blueprint(auth_views)
|
||||||
app.register_blueprint(frontend_views)
|
app.register_blueprint(frontend_views)
|
||||||
|
@ -171,16 +171,3 @@ def oidc_provider_init_app(name=None):
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
def init_login_manager(app):
|
|
||||||
@app.login_manager.user_loader
|
|
||||||
def user_loader(username):
|
|
||||||
return model.User.query().by_username(username)
|
|
||||||
|
|
||||||
@app.login_manager.request_loader
|
|
||||||
def request_loader(request):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@app.login_manager.unauthorized_handler
|
|
||||||
def unauthorized():
|
|
||||||
return redirect(url_for('auth.login'))
|
|
||||||
|
|
|
@ -32,3 +32,7 @@ class TOTPForm(FlaskForm):
|
||||||
|
|
||||||
class TOTPDeleteForm(FlaskForm):
|
class TOTPDeleteForm(FlaskForm):
|
||||||
submit = SubmitField(gettext('Delete'))
|
submit = SubmitField(gettext('Delete'))
|
||||||
|
|
||||||
|
|
||||||
|
class OidcAuthenticationConfirm(FlaskForm):
|
||||||
|
submit = SubmitField(gettext('Continue'))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# pylint: disable=unused-import
|
# pylint: disable=unused-import
|
||||||
|
|
||||||
from .oidc import oidc_provider_views
|
from .oidc import oidc_provider_views
|
||||||
from .auth import auth_views
|
from .auth import auth_views, init_login_manager
|
||||||
from .frontend import frontend_views
|
from .frontend import frontend_views
|
||||||
|
|
|
@ -18,7 +18,8 @@ from flask import Blueprint, render_template, request, url_for
|
||||||
from flask_login import login_required, login_user, logout_user
|
from flask_login import login_required, login_user, logout_user
|
||||||
from werkzeug.utils import redirect
|
from werkzeug.utils import redirect
|
||||||
import logging
|
import logging
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
from base64 import b64decode, b64encode
|
||||||
|
|
||||||
from ..model import User, SecurityUser
|
from ..model import User, SecurityUser
|
||||||
from ..form.login import LoginForm
|
from ..form.login import LoginForm
|
||||||
|
@ -29,6 +30,19 @@ from .oidc import do_logout
|
||||||
auth_views = Blueprint('auth', __name__, url_prefix='')
|
auth_views = Blueprint('auth', __name__, url_prefix='')
|
||||||
|
|
||||||
|
|
||||||
|
def init_login_manager(app):
|
||||||
|
@app.login_manager.user_loader
|
||||||
|
def user_loader(username):
|
||||||
|
return User.query().by_username(username)
|
||||||
|
|
||||||
|
@app.login_manager.request_loader
|
||||||
|
def request_loader(request):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@app.login_manager.unauthorized_handler
|
||||||
|
def unauthorized():
|
||||||
|
return redirect(url_for('auth.login', next=b64encode(request.url.encode())))
|
||||||
|
|
||||||
@auth_views.route('/login', methods=['GET', 'POST'])
|
@auth_views.route('/login', methods=['GET', 'POST'])
|
||||||
def login():
|
def login():
|
||||||
form = LoginForm()
|
form = LoginForm()
|
||||||
|
@ -36,7 +50,7 @@ def login():
|
||||||
user = User.query().by_username(form.data['name'])
|
user = User.query().by_username(form.data['name'])
|
||||||
session['username'] = str(user.username)
|
session['username'] = str(user.username)
|
||||||
session['auth_providers'] = []
|
session['auth_providers'] = []
|
||||||
return redirect(url_for('auth.login_auth'))
|
return redirect(url_for('auth.login_auth', next=flask.request.args.get('next')))
|
||||||
return render_template('frontend/login.html.j2', form=form)
|
return render_template('frontend/login.html.j2', form=form)
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +58,7 @@ def login():
|
||||||
def login_auth():
|
def login_auth():
|
||||||
if 'username' not in session:
|
if 'username' not in session:
|
||||||
return redirect(url_for('auth.login'))
|
return redirect(url_for('auth.login'))
|
||||||
auth_forms = []
|
auth_forms = {}
|
||||||
user = User.query().by_username(session['username'])
|
user = User.query().by_username(session['username'])
|
||||||
for auth_provider in AUTH_PROVIDER_LIST:
|
for auth_provider in AUTH_PROVIDER_LIST:
|
||||||
form = auth_provider.get_form()
|
form = auth_provider.get_form()
|
||||||
|
@ -53,14 +67,20 @@ def login_auth():
|
||||||
session['auth_providers'].append(auth_provider.get_name())
|
session['auth_providers'].append(auth_provider.get_name())
|
||||||
|
|
||||||
if auth_provider.get_name() not in session['auth_providers']:
|
if auth_provider.get_name() not in session['auth_providers']:
|
||||||
auth_forms.append(form)
|
auth_forms[auth_provider.get_name()]=form
|
||||||
|
|
||||||
if len(session['auth_providers']) >= 2:
|
if len(session['auth_providers']) >= 2:
|
||||||
login_user(SecurityUser(session['username']))
|
login_user(SecurityUser(session['username']))
|
||||||
# TODO use this var
|
# TODO use this var
|
||||||
_next = request.args.get('next')
|
_next = None
|
||||||
return redirect(url_for('frontend.index'))
|
try:
|
||||||
print(auth_forms)
|
_next_url = urlparse(b64decode(request.args.get('next')).decode())
|
||||||
|
_host_url = urlparse(request.url)
|
||||||
|
if _next_url.scheme == _host_url.scheme and _next_url.netloc == _host_url.netloc :
|
||||||
|
_next = _next_url.geturl()
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
return redirect(_next or url_for('frontend.index'))
|
||||||
return render_template('frontend/login_auth.html.j2', forms=auth_forms)
|
return render_template('frontend/login_auth.html.j2', forms=auth_forms)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from urllib.parse import urlencode, parse_qs
|
from urllib.parse import urlencode, parse_qs
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import Blueprint, redirect
|
from flask import Blueprint, redirect, request
|
||||||
from flask import current_app, session
|
from flask import current_app, session
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
from flask.helpers import make_response
|
from flask.helpers import make_response
|
||||||
|
@ -14,6 +14,8 @@ from pyop.exceptions import InvalidAuthenticationRequest, InvalidAccessToken, In
|
||||||
InvalidSubjectIdentifier, InvalidClientRegistrationRequest
|
InvalidSubjectIdentifier, InvalidClientRegistrationRequest
|
||||||
from pyop.util import should_fragment_encode
|
from pyop.util import should_fragment_encode
|
||||||
|
|
||||||
|
from ..form.frontend import OidcAuthenticationConfirm
|
||||||
|
|
||||||
oidc_provider_views = Blueprint('oidc_provider', __name__, url_prefix='')
|
oidc_provider_views = Blueprint('oidc_provider', __name__, url_prefix='')
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,10 +31,17 @@ def registration_endpoint():
|
||||||
|
|
||||||
@oidc_provider_views.route('/authentication', methods=['GET'])
|
@oidc_provider_views.route('/authentication', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
|
def authentication_endpoint_confirm():
|
||||||
|
form = OidcAuthenticationConfirm()
|
||||||
|
return render_template('frontend/oidc_authentication.html.j2', form=form)
|
||||||
|
|
||||||
|
|
||||||
|
@oidc_provider_views.route('/authentication', methods=['POST'])
|
||||||
|
@login_required
|
||||||
def authentication_endpoint():
|
def authentication_endpoint():
|
||||||
# parse authentication request
|
# parse authentication request
|
||||||
print(flask.request)
|
print(request)
|
||||||
print(flask.request.headers)
|
print(request.headers)
|
||||||
try:
|
try:
|
||||||
auth_req = current_app.provider.parse_authentication_request(urlencode(flask.request.args),
|
auth_req = current_app.provider.parse_authentication_request(urlencode(flask.request.args),
|
||||||
flask.request.args)
|
flask.request.args)
|
||||||
|
@ -45,7 +54,7 @@ def authentication_endpoint():
|
||||||
# show error to user
|
# show error to user
|
||||||
return make_response('Something went wrong: {}'.format(str(e)), 400)
|
return make_response('Something went wrong: {}'.format(str(e)), 400)
|
||||||
|
|
||||||
# automagic authentication
|
# automatically authentication
|
||||||
authn_response = current_app.provider.authorize(auth_req, str(current_user.username))
|
authn_response = current_app.provider.authorize(auth_req, str(current_user.username))
|
||||||
response_url = authn_response.request(auth_req['redirect_uri'], should_fragment_encode(auth_req))
|
response_url = authn_response.request(auth_req['redirect_uri'], should_fragment_encode(auth_req))
|
||||||
return redirect(response_url, 303)
|
return redirect(response_url, 303)
|
||||||
|
|
|
@ -4,15 +4,8 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<form method="POST" action="/login">
|
|
||||||
{{ form.csrf_token }}
|
{{ render_form(form) }}
|
||||||
<div class="form-group row">
|
|
||||||
<label class="col-sm-2 col-form-label">{{ form.name.label }} </label>
|
|
||||||
<div class="col-sm-10">
|
|
||||||
{{ form.name(size=20) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ form.submit() }}
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,21 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
{% for form in forms %}
|
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||||
{{ render_form(form) }}
|
{% for auth_name in forms.keys() %}
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link{{' active' if loop.first else ''}}" id="home-tab" data-toggle="tab" href="#{{ auth_name }}" role="tab" aria-controls="home" aria-selected="true">{{ gettext(auth_name) }}</a>
|
||||||
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content" id="myTabContent">
|
||||||
|
{% for auth_name, form in forms.items() %}
|
||||||
|
<div class="tab-pane fade{{ ' show active' if loop.first else '' }}" id="{{ auth_name }}" role="tabpanel" aria-labelledby="{{ auth_name }}-tab">
|
||||||
|
|
||||||
|
{{ render_form(form) }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
17
templates/frontend/oidc_authentication.html.j2
Normal file
17
templates/frontend/oidc_authentication.html.j2
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{% extends 'frontend/base.html.j2' %}
|
||||||
|
|
||||||
|
{% block title %}{{ gettext('Oauth2 Request') }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<p>
|
||||||
|
A service ask for access to your account data.<br>
|
||||||
|
|
||||||
|
You can confirm this pressing "Continue"
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{{ render_form(form) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
Loading…
Reference in a new issue