test sso flows

This commit is contained in:
Daniel Tsvetkov 2021-05-09 17:07:34 +02:00
parent b1b7b4017b
commit 55742c2104
6 changed files with 19 additions and 13 deletions

View File

@ -8,12 +8,13 @@ PaaS - creates easily deployable declarative web applications with (moslty) file
* Frontend niceties such chosen.js, datatables.js and lightbox.js - but apps should still work without JS. * Frontend niceties such chosen.js, datatables.js and lightbox.js - but apps should still work without JS.
* Off-request worker based on a file-system persistence and streaming intermediary results (if js is supported, or upon refresh) * Off-request worker based on a file-system persistence and streaming intermediary results (if js is supported, or upon refresh)
* Whooshalchemy search * Whooshalchemy search
* SSO Sign in through [pi2-sso]()
* Installation with gunicorn, generates nginx config and letsencrypt certificate * Installation with gunicorn, generates nginx config and letsencrypt certificate
* Based on [Flask](), [Sqlalchemy](), [TWW](https://gitlab.com/pisquared/tww) and others * Based on [Flask](), [Sqlalchemy](), [TWW](https://gitlab.com/pisquared/tww) and others
## TODO ## TODO
* [ ] [list] pagination of many items * [X] [list] pagination of many items
* [ ] [prod_install] Download sensitive prompt * [ ] [prod_install] Download sensitive prompt
* [ ] [vm_gen] Auto generate dependency graph for `view_models/_process_order` * [ ] [vm_gen] Auto generate dependency graph for `view_models/_process_order`
* [ ] [auto_dns] Start and test `auto_dns.service` * [ ] [auto_dns] Start and test `auto_dns.service`

View File

@ -26,3 +26,5 @@ MAKEDIRS = [
APP_BASE_URL = "http://localhost:5000" APP_BASE_URL = "http://localhost:5000"
SECURITY_ENABLED = True SECURITY_ENABLED = True
SSO_BASE_URL = 'https://sso.localhost:5008'
SSO_CLIENT_ID = APP_BASE_URL

View File

@ -1,2 +1,2 @@
SSO_CLIENT_ID = '123456' SSO_CLIENT_ID = '123456'
SSO_CLIENT_SECRET = 'secret' SSO_CLIENT_SECRET = 'secret'

View File

@ -1,9 +1,8 @@
<a href="{{ url_for('home') }}">{{ _("Home") }}</a> |
<div class="pull-right"> <div class="pull-right">
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
<a href="#">{{ current_user.email }}</a> | <a href="{{ config.SSO_BASE_URL }}">{{ current_user.username }}</a> |
<a href="{{ url_for('security.logout') }}">{{ _("Logout") }}</a> | <a href="{{ url_for('security.logout') }}">{{ _("Logout") }}</a> |
{% else %} {% else %}
<a href="{{ url_for('security.login') }}">{{ _("SSO Login") }}</a> | <a href="{{ url_for('security.login') }}">{{ _("Login SSO") }}</a>
{% endif %} {% endif %}
</div> </div>

View File

@ -6,8 +6,8 @@ from flask_security import login_user
from oshipka.util.strings import random_string_generator from oshipka.util.strings import random_string_generator
from oshipka.webapp import oshipka_bp, app from oshipka.webapp import oshipka_bp, app
from config import MEDIA_DIR, APP_BASE_URL, SECURITY_ENABLED from config import MEDIA_DIR, APP_BASE_URL, SECURITY_ENABLED, SSO_BASE_URL, SSO_CLIENT_ID
from sensitive import SSO_CLIENT_ID, SSO_CLIENT_SECRET from sensitive import SSO_CLIENT_SECRET
# TODO: VULNZ - EVERYONE HAS ACCESS TO THIS # TODO: VULNZ - EVERYONE HAS ACCESS TO THIS
@ -15,9 +15,11 @@ from sensitive import SSO_CLIENT_ID, SSO_CLIENT_SECRET
def get_media(filepath): def get_media(filepath):
return send_from_directory(MEDIA_DIR, filepath) return send_from_directory(MEDIA_DIR, filepath)
if SECURITY_ENABLED: if SECURITY_ENABLED:
from oshipka.persistance import User, db from oshipka.persistance import User, db
SSO_BASE_URL = 'http://sso.localhost:5008' app.config['SSO_BASE_URL'] = SSO_BASE_URL
SSO_AUTH_URL = '/oidc/auth' SSO_AUTH_URL = '/oidc/auth'
SSO_TOKEN_URL = '/oidc/token' SSO_TOKEN_URL = '/oidc/token'
SSO_USERINFO_URL = "/endpoints/userinfo" SSO_USERINFO_URL = "/endpoints/userinfo"
@ -27,7 +29,7 @@ if SECURITY_ENABLED:
@oshipka_bp.route('/sso') @oshipka_bp.route('/sso')
def sso(): def sso():
callback_url = APP_BASE_URL + url_for('oshipka_bp.oidc_callback') callback_url = APP_BASE_URL + url_for('oshipka_bp.oidc_callback')
state = request.referrer or url_for('home') state = request.referrer or url_for('home') + "|" + random_string_generator()
session['oidc_state'] = state session['oidc_state'] = state
params = urllib.parse.urlencode({ params = urllib.parse.urlencode({
'redirect_uri': callback_url, 'redirect_uri': callback_url,
@ -58,6 +60,7 @@ if SECURITY_ENABLED:
'client_secret': SSO_CLIENT_SECRET, 'client_secret': SSO_CLIENT_SECRET,
'grant_type': 'authorization_code' 'grant_type': 'authorization_code'
}, },
verify=False,
) )
if response.status_code == 200: if response.status_code == 200:
response_json = response.json() response_json = response.json()
@ -67,6 +70,7 @@ if SECURITY_ENABLED:
headers={ headers={
'Authorization': "Bearer {}".format(access_token) 'Authorization': "Bearer {}".format(access_token)
}, },
verify=False,
) )
if response.status_code == 200: if response.status_code == 200:
response_json = response.json() response_json = response.json()
@ -74,12 +78,12 @@ if SECURITY_ENABLED:
user = User.query.filter_by(username=username).first() user = User.query.filter_by(username=username).first()
redirect_uri = url_for('home') redirect_uri = url_for('home')
if not user: if not user:
user = User(username=username) user = User(username=username, token=access_token)
db.session.add(user) db.session.add(user)
db.session.commit() db.session.commit()
login_user(user) login_user(user)
if 'oidc_state' in session: if 'oidc_state' in session:
redirect_uri = session['oidc_state'] redirect_uri = session['oidc_state'].split('|')[0] or url_for('home')
del session['oidc_state'] del session['oidc_state']
return redirect(redirect_uri) return redirect(redirect_uri)
return response.json() return response.text

View File

@ -11,7 +11,7 @@
<div class="pull-right"> <div class="pull-right">
{% if current_user.is_authenticated %} {% if current_user.is_authenticated %}
<a href="#">{{ current_user.username }}</a> | <a href="{{ config.SSO_BASE_URL }}">{{ current_user.username }}</a> |
<a href="{{ url_for('security.logout') }}">{{ _("Logout") }}</a> | <a href="{{ url_for('security.logout') }}">{{ _("Logout") }}</a> |
{% else %} {% else %}
<a href="{{ url_for('security.login') }}">{{ _("Login SSO") }}</a> <a href="{{ url_for('security.login') }}">{{ _("Login SSO") }}</a>