2020-05-09 18:00:07 +00:00
|
|
|
|
|
|
|
from urllib.parse import urlencode, parse_qs
|
|
|
|
|
|
|
|
import flask
|
|
|
|
from flask import Blueprint, redirect
|
|
|
|
from flask import current_app, session
|
|
|
|
from flask.templating import render_template
|
2020-05-26 20:55:37 +00:00
|
|
|
from flask_babel import gettext
|
2020-05-09 18:00:07 +00:00
|
|
|
|
2020-05-26 20:55:37 +00:00
|
|
|
from flask import request, url_for
|
2020-05-09 18:00:07 +00:00
|
|
|
from flask_login import login_required, login_user, logout_user
|
|
|
|
import logging
|
2020-05-13 15:04:22 +00:00
|
|
|
from urllib.parse import urlparse
|
|
|
|
from base64 import b64decode, b64encode
|
2020-05-21 11:20:27 +00:00
|
|
|
import http
|
2020-05-09 18:00:07 +00:00
|
|
|
|
|
|
|
from ..model import User, SecurityUser
|
2020-05-21 11:20:27 +00:00
|
|
|
from ..model_db import db, User as DbUser
|
2020-05-26 20:55:37 +00:00
|
|
|
from ..form.auth import ConsentForm, LoginForm
|
2020-05-09 18:00:07 +00:00
|
|
|
from ..auth_providers import AUTH_PROVIDER_LIST
|
|
|
|
|
|
|
|
|
2020-05-21 11:20:27 +00:00
|
|
|
auth_views = Blueprint('auth', __name__, url_prefix='/auth')
|
2020-05-09 18:00:07 +00:00
|
|
|
|
2020-05-26 20:55:37 +00:00
|
|
|
|
2020-05-21 11:20:27 +00:00
|
|
|
@auth_views.route('/consent', methods=['GET', 'POST'])
|
|
|
|
def consent():
|
|
|
|
"""Always grant consent."""
|
|
|
|
# DUMMPY ONLY
|
2020-05-09 18:00:07 +00:00
|
|
|
|
2020-05-26 20:55:37 +00:00
|
|
|
form = ConsentForm()
|
|
|
|
remember_for = 60*60*24*7 # remember for 7 days
|
2020-05-13 15:04:22 +00:00
|
|
|
|
2020-05-26 20:55:37 +00:00
|
|
|
consent_request = current_app.hydra_api.get_consent_request(
|
|
|
|
request.args['consent_challenge'])
|
2020-05-21 11:20:27 +00:00
|
|
|
requested_scope = consent_request.requested_scope
|
2020-05-26 20:55:37 +00:00
|
|
|
requested_audiences = consent_request.requested_access_token_audience
|
|
|
|
|
|
|
|
if form.validate_on_submit() or consent_request.skip:
|
|
|
|
resp = current_app.hydra_api.accept_consent_request(
|
|
|
|
consent_request.challenge, body={
|
|
|
|
'grant_scope': requested_scope,
|
|
|
|
'grant_access_token_audience': requested_audiences,
|
|
|
|
'remember': form.data['remember'],
|
|
|
|
# 'remember_for': remember_for,
|
|
|
|
})
|
|
|
|
return redirect(resp.redirect_to)
|
|
|
|
return render_template(
|
|
|
|
'auth/consent.html.j2',
|
|
|
|
form=form,
|
|
|
|
client=consent_request.client,
|
|
|
|
requested_scope=requested_scope,
|
|
|
|
requested_audiences=requested_audiences)
|
|
|
|
|
2020-05-13 15:04:22 +00:00
|
|
|
|
2020-05-09 18:00:07 +00:00
|
|
|
@auth_views.route('/login', methods=['GET', 'POST'])
|
|
|
|
def login():
|
2020-05-21 11:20:27 +00:00
|
|
|
login_challenge = request.args.get('login_challenge')
|
|
|
|
login_request = current_app.hydra_api.get_login_request(login_challenge)
|
|
|
|
|
|
|
|
if login_request.skip:
|
|
|
|
resp = current_app.hydra_api.accept_login_request(
|
|
|
|
login_challenge,
|
|
|
|
body={'subject': login_request.subject})
|
|
|
|
return redirect(resp.redirect_to)
|
2020-05-09 18:00:07 +00:00
|
|
|
form = LoginForm()
|
|
|
|
if form.validate_on_submit():
|
|
|
|
user = User.query().by_username(form.data['name'])
|
2020-05-13 18:08:28 +00:00
|
|
|
if user:
|
|
|
|
session['username'] = str(user.username)
|
|
|
|
else:
|
|
|
|
session['user'] = None
|
2020-05-09 18:00:07 +00:00
|
|
|
session['auth_providers'] = []
|
2020-05-26 20:55:37 +00:00
|
|
|
return redirect(
|
|
|
|
url_for('auth.login_auth', login_challenge=login_challenge))
|
|
|
|
return render_template('auth/login.html.j2', form=form)
|
2020-05-09 18:00:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
@auth_views.route('/login/auth', methods=['GET', 'POST'])
|
|
|
|
def login_auth():
|
2020-05-21 11:20:27 +00:00
|
|
|
login_challenge = request.args.get('login_challenge')
|
|
|
|
login_request = current_app.hydra_api.get_login_request(login_challenge)
|
2020-05-09 18:00:07 +00:00
|
|
|
if 'username' not in session:
|
|
|
|
return redirect(url_for('auth.login'))
|
2020-05-13 15:04:22 +00:00
|
|
|
auth_forms = {}
|
2020-05-09 18:00:07 +00:00
|
|
|
user = User.query().by_username(session['username'])
|
|
|
|
for auth_provider in AUTH_PROVIDER_LIST:
|
|
|
|
form = auth_provider.get_form()
|
|
|
|
if auth_provider.get_name() not in session['auth_providers'] and\
|
|
|
|
auth_provider.check_auth(user, form):
|
|
|
|
session['auth_providers'].append(auth_provider.get_name())
|
|
|
|
|
|
|
|
if auth_provider.get_name() not in session['auth_providers']:
|
2020-05-13 15:04:22 +00:00
|
|
|
auth_forms[auth_provider.get_name()]=form
|
2020-05-09 18:00:07 +00:00
|
|
|
|
|
|
|
if len(session['auth_providers']) >= 2:
|
2020-05-21 11:20:27 +00:00
|
|
|
remember_me = True
|
|
|
|
db_user = DbUser.query.filter(DbUser.username == session['username']).one_or_none()
|
|
|
|
if db_user is None:
|
|
|
|
db_user = DbUser(username=session['username'])
|
|
|
|
db.session.add(db_user)
|
|
|
|
db.session.commit()
|
|
|
|
|
|
|
|
subject = db_user.id
|
|
|
|
|
|
|
|
resp = current_app.hydra_api.accept_login_request(
|
|
|
|
login_challenge, body={
|
|
|
|
'subject': subject,
|
|
|
|
'remember': remember_me})
|
|
|
|
return redirect(resp.redirect_to)
|
|
|
|
|
2020-05-09 18:00:07 +00:00
|
|
|
login_user(SecurityUser(session['username']))
|
|
|
|
# TODO use this var
|
2020-05-13 15:04:22 +00:00
|
|
|
_next = None
|
|
|
|
try:
|
|
|
|
_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()
|
2020-05-13 18:08:28 +00:00
|
|
|
except TypeError:
|
|
|
|
_next = None
|
2020-05-13 15:04:22 +00:00
|
|
|
return redirect(_next or url_for('frontend.index'))
|
2020-05-26 20:55:37 +00:00
|
|
|
return render_template('auth/login_auth.html.j2', forms=auth_forms)
|
2020-05-09 18:00:07 +00:00
|
|
|
|
|
|
|
|
|
|
|
@auth_views.route("/logout")
|
|
|
|
def logout():
|
2020-05-21 11:20:27 +00:00
|
|
|
logout_challenge = request.args.get('logout_challenge')
|
|
|
|
logout_request = current_app.hydra_api.get_logout_request(logout_challenge)
|
|
|
|
resp = current_app.hydra_api.accept_logout_request(logout_challenge)
|
2020-05-26 20:55:37 +00:00
|
|
|
logout_user()
|
2020-05-21 11:20:27 +00:00
|
|
|
return redirect(resp.redirect_to)
|
|
|
|
|
2020-05-09 18:00:07 +00:00
|
|
|
|