From 47e898713958b094ce885d9649da4064936a15cb Mon Sep 17 00:00:00 2001 From: Mart van Santen <mart@greenhost.nl> Date: Fri, 19 Nov 2021 12:07:24 +0100 Subject: [PATCH] Removed old panels and update gitlab ci to stop building those --- .gitlab-ci.yml | 33 ------ .gitmodules | 3 - consent_provider/Dockerfile | 22 ---- consent_provider/app.py | 67 ----------- consent_provider/db.py | 84 -------------- consent_provider/requirements.txt | 3 - consent_provider/templates/base.html | 11 -- consent_provider/templates/consent.html | 15 --- docker-compose.yml | 29 ----- ...al_dev_remote_kratos.md => development.md} | 0 docs/index.rst | 8 +- docs/usage.md | 28 ----- login_provider/.envrc.example | 6 - login_provider/Dockerfile | 20 ---- login_provider/README.md | 22 ---- login_provider/app.py | 106 ------------------ login_provider/db.py | 76 ------------- login_provider/forms.py | 10 -- login_provider/requirements.txt | 7 -- login_provider/templates/login.html | 18 --- login_provider/templates/skip.html | 14 --- logout_provider/Dockerfile | 22 ---- logout_provider/app.py | 44 -------- logout_provider/requirements.txt | 2 - user-panel | 1 - 25 files changed, 4 insertions(+), 647 deletions(-) delete mode 100644 consent_provider/Dockerfile delete mode 100644 consent_provider/app.py delete mode 100644 consent_provider/db.py delete mode 100644 consent_provider/requirements.txt delete mode 100644 consent_provider/templates/base.html delete mode 100644 consent_provider/templates/consent.html rename docs/{local_dev_remote_kratos.md => development.md} (100%) delete mode 100644 docs/usage.md delete mode 100644 login_provider/.envrc.example delete mode 100644 login_provider/Dockerfile delete mode 100644 login_provider/README.md delete mode 100644 login_provider/app.py delete mode 100644 login_provider/db.py delete mode 100644 login_provider/forms.py delete mode 100644 login_provider/requirements.txt delete mode 100644 login_provider/templates/login.html delete mode 100644 login_provider/templates/skip.html delete mode 100644 logout_provider/Dockerfile delete mode 100644 logout_provider/app.py delete mode 100644 logout_provider/requirements.txt delete mode 160000 user-panel diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a4e8cbb..b43d4df 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,39 +9,6 @@ stages: - application-test - integration-test -consent_provider: - stage: build - variables: - KANIKO_CONTEXT: "consent_provider" - KANIKO_BUILD_IMAGENAME: $CI_JOB_NAME - extends: .kaniko_build - only: - changes: - - consent_provider/**/* - - .gitlab-ci.yml - -logout_provider: - stage: build - variables: - KANIKO_CONTEXT: "logout_provider" - KANIKO_BUILD_IMAGENAME: $CI_JOB_NAME - extends: .kaniko_build - only: - changes: - - logout_provider/**/* - - .gitlab-ci.yml - -login_provider: - stage: build - variables: - KANIKO_CONTEXT: "login_provider" - KANIKO_BUILD_IMAGENAME: $CI_JOB_NAME - extends: .kaniko_build - only: - changes: - - login_provider/**/* - - .gitlab-ci.yml - integration_test_app: stage: build-test-images variables: diff --git a/.gitmodules b/.gitmodules index 88b746c..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "user-panel"] - path = user-panel - url = https://open.greenhost.net/stackspin/user-panel.git diff --git a/consent_provider/Dockerfile b/consent_provider/Dockerfile deleted file mode 100644 index 7d5437e..0000000 --- a/consent_provider/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM python:3.9-alpine - -RUN apk add gcc libc-dev libffi-dev - -WORKDIR /usr/src/app - -COPY requirements.txt ./ -RUN pip install --no-cache-dir -r requirements.txt - -COPY . . - -ARG FLASK_PORT=5001 - -EXPOSE $FLASK_PORT - -ENV FLASK_ENV production -ENV FLASK_RUN_PORT $FLASK_PORT -ENV FLASK_RUN_HOST 0.0.0.0 -ENV HYDRA_ADMIN_URL http://localhost:4445 - - -CMD [ "flask", "run" ] diff --git a/consent_provider/app.py b/consent_provider/app.py deleted file mode 100644 index 95a49f7..0000000 --- a/consent_provider/app.py +++ /dev/null @@ -1,67 +0,0 @@ -from flask import abort, Flask, redirect, request -from flask.views import View -from os import urandom, environ -from hydra_client import HydraAdmin -import hydra_client -from db import User, BackendConnectionError -import logging - -HYDRA_ADMIN_URL = environ['HYDRA_ADMIN_URL'] -HYDRA = HydraAdmin(HYDRA_ADMIN_URL) - -app = Flask(__name__) -app.logger.setLevel(logging.INFO) - -@app.route('/consent', methods=['GET']) -def home(): - """Checks user app permission - - Checks user app permission by loading a consent object via the Hydra admin API and - validating that the user triggering the request has sufficient permissions by querying - the GraphQL API. If the user is allowed to use the app the request is accepted and openID - claims are sent to Hydra. - - Args: - consent_challenge: Reference to a consent challenge object in form of an alphanumeric - String. Can be used to retrieve the consent challenge object via the Hydra Admin API (GET) - - Returns: - Redirect to the url that is provided by the consent challenge object. - """ - challenge = request.args.get("consent_challenge") - if not challenge: - abort(403) - try: - consent_request = HYDRA.consent_request(challenge) - except hydra_client.exceptions.NotFound: - app.logger.error("Not Found. Consent request not found. challenge={0}".format(challenge)) - abort(404) - except hydra_client.exceptions.HTTPError: - app.logger.error("Conflict. Consent request has been used already. challenge={0}".format(challenge)) - abort(503) - app_name = consent_request.client.client_name - username = consent_request.subject - try: - user = User(username) - except BackendConnectionError as error: - app.logger.error( - "Retrieving user object from GraphQL server failed {0}".format(error)) - return redirect(consent_request.reject( - "Permission denied", - error_description="Login request was denied due to an internal server error")) - access_granted = user.has_app_permission(app_name) - if access_granted: - app.logger.info("{0} was granted access to {1}".format(username, app_name)) - session = user.get_oauth_session() - return redirect(consent_request.accept( - grant_scope=consent_request.requested_scope, - grant_access_token_audience=consent_request.requested_access_token_audience, - session=session, - )) - app.logger.info("{0} was denied access to {1}".format(username, app_name)) - return redirect(consent_request.reject( - "Permission denied", - error_description="Login request was denied due to missing application permission")) - -if __name__ == '__main__': - app.run() diff --git a/consent_provider/db.py b/consent_provider/db.py deleted file mode 100644 index fa994ef..0000000 --- a/consent_provider/db.py +++ /dev/null @@ -1,84 +0,0 @@ -from os import environ -from hydra_client import HydraAdmin -from graphqlclient import GraphQLClient -import urllib -import json - -GRAPHQL_URL = environ['GRAPHQL_URL'] -GRAPHQL_CLIENT = GraphQLClient(GRAPHQL_URL) - - -class User(): - def __init__(self, username): - self.username = username - try: - self._load_remote_user_info() - except urllib.error.HTTPError as error: - raise BackendConnectionError( - error.code, - error.headers, - ("Error during retrieval of userdata - " + error.reason)) - - def _load_remote_user_info(self): - querystring = '''{{ - getUser(username: "{0}"){{ - email, - applications{{ - edges{{ - node{{ - name - }} - }} - }}, - roles{{ - edges{{ - node{{ - name - }} - }} - }} - }}}}'''.format(self.username) - result = json.loads(GRAPHQL_CLIENT.execute(querystring)) - data = result["data"]["getUser"] - self.applications = list(map(lambda x: x["node"]["name"], - data["applications"]["edges"])) - self.roles = list(map(lambda x: x["node"]["name"], - data["roles"]["edges"])) - self.email = data["email"] - - def has_app_permission(self, appname): - return appname in self.applications - - def get_oauth_session(self): - """Create openID Connect token - - Use the userdata stored in the user object to create an OpenID Connect token. - The token will be passed to Hydra, which will store it and serve it to all OpenID Connect - Clients, that successfully query the /userinfo endpoint. Every field in the "id_token" - dictionary can be accessed through standard scopes and claims. - See https://openid.net/specs/openid-connect-core-1_0.html#Claims - - Returns: - OpenID Connect token of type dict - """ - return { - "id_token": { - "name": self.username, - "preferred_username": self.username, - "email" : self.email, - "stackspin_roles": self.roles} - } - - -class BackendConnectionError(Exception): - """Raised when requests to the backend server fail - - Attributes: - code -- http response code - headers -- http response headers - reason -- reson for the error - """ - def __init__(self, code, headers, reason): - self.code = code - self.headers = headers - self.reason = reason diff --git a/consent_provider/requirements.txt b/consent_provider/requirements.txt deleted file mode 100644 index 00c8039..0000000 --- a/consent_provider/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -Flask -hydra-client -graphqlclient diff --git a/consent_provider/templates/base.html b/consent_provider/templates/base.html deleted file mode 100644 index 26e9f45..0000000 --- a/consent_provider/templates/base.html +++ /dev/null @@ -1,11 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <title>{%block title %}python-login-consent{% endblock %}</title> -</head> -<body> - {% block content %} - <h1>Welcome to the Python login/consent app for Hydra</h1> - {% endblock %} -</body> -</html> diff --git a/consent_provider/templates/consent.html b/consent_provider/templates/consent.html deleted file mode 100644 index db91dd3..0000000 --- a/consent_provider/templates/consent.html +++ /dev/null @@ -1,15 +0,0 @@ -{% extends "base.html" %} -{% block title %}Consent{% endblock %} - -{% block content %} -<dl> - <dt>User</dt> - <dd>{{ user }}</dd> - <dt>Client</dt> - <dd>{{ client }}</dd> -</dl> -<form method="POST" action="/consent"> - {{ form.hidden_tag() }} - {{ form.accept }} -</form> -{% endblock %} diff --git a/docker-compose.yml b/docker-compose.yml index 76747c6..2b72fd2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,23 +27,6 @@ services: - LOG_LEVEL=debug - LOG_LEAK_SENSITIVE_VALUES=true restart: unless-stopped - consent: - build: consent_provider/ - environment: - - HYDRA_ADMIN_URL=http://hydra:4445 - - GRAPHQL_URL=http://backend:5000/graphql - - FLASK_ENV=development - ports: - - "5001:5001" - restart: unless-stopped - logout: - build: logout_provider/ - environment: - - HYDRA_ADMIN_URL=http://hydra:4445 - - FLASK_ENV=development - ports: - - "5002:5002" - restart: unless-stopped login: build: login_provider/ environment: @@ -53,18 +36,6 @@ services: ports: - "5000:5000" restart: unless-stopped - backend: - build: user-panel/backend/ - environment: - - DEBUG=True - - HYDRA_ADMIN_URL=http://hydra:4445 - - DATABASE_USER=postgres - - DATABASE_PASSWORD=secret - - DATABASE_NAME=postgres - - DATABASE_HOST=psql - ports: - - "5003:5000" - restart: unless-stopped psql: image: postgres:11 environment: diff --git a/docs/local_dev_remote_kratos.md b/docs/development.md similarity index 100% rename from docs/local_dev_remote_kratos.md rename to docs/development.md diff --git a/docs/index.rst b/docs/index.rst index 8b46d87..c446f44 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,13 +7,13 @@ Welcome to single-sign-on's documentation! ========================================== This project provides a single sign on solution based on -[hydra](https://github.com/ory/hydra) and in combination with a [user -panel](https://open.greenhost.net/stackspin/user-panel). +[hydra](https://github.com/ory/hydra), [kratos](https://github.com/ory/kratos) +and in combination with a [login panel](https://open.greenhost.net/stackspin/single-sign-on). .. toctree:: :maxdepth: 2 :caption: Contents: - usage helmchart - local_development + development + diff --git a/docs/usage.md b/docs/usage.md deleted file mode 100644 index 2d7c5cb..0000000 --- a/docs/usage.md +++ /dev/null @@ -1,28 +0,0 @@ -# Usage - -## Installlation instructions - -Clone the repo and make sure to also fetch the submodules. -``` -git submodule update --init -``` - -Installation should be done via the helm using the helmchart contained in -`./helmchart`. Make sure to edit the values in -`./helmchart/single-sign-on/values.yaml` according to your needs. To install the -helm chart, make sure Helm is properly set up in your Kubernetes cluster, then: - -``` -cd helmchart # Enter the helm chart directory -helm dep update # Download helm charts this chart relies on -helm install . # Run the installation command -``` - -For Details on how to configure the chart. Refer to [the Helm chart -chapter](helmchart) - -### Managing users - -`single-sign-on` includese a simple `user-panel` to manage users. To read more -about this, see the [user panel -documentation](https://docs.stackspin.net/projects/user-panel/) diff --git a/login_provider/.envrc.example b/login_provider/.envrc.example deleted file mode 100644 index 54c318b..0000000 --- a/login_provider/.envrc.example +++ /dev/null @@ -1,6 +0,0 @@ -export FLASK_SECRET_KEY="CHANGEME" -export FLASK_RUN_HOST="0.0.0.0" -export FLASK_RUN_PORT="5000" -export GRAPHQL_URL="http://localhost:5002/graphql" -export HYDRA_ADMIN_URL="http://localhost:4445" -export FLASK_ENV=development diff --git a/login_provider/Dockerfile b/login_provider/Dockerfile deleted file mode 100644 index 8c70d93..0000000 --- a/login_provider/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM python:3.9-alpine - -RUN apk add gcc libc-dev libffi-dev g++ - -WORKDIR /usr/src/app - -COPY requirements.txt ./ -RUN pip install --no-cache-dir -r requirements.txt - -COPY . . - -EXPOSE 5000 - -ENV FLASK_ENV production -ENV FLASK_RUN_HOST 0.0.0.0 -ENV FLASK_RUN_PORT 5000 -ENV HYDRA_ADMIN_URL http://localhost:4445 -ENV GRAPHQL_URL http://localhost:5002/graphql - -CMD [ "flask", "run" ] diff --git a/login_provider/README.md b/login_provider/README.md deleted file mode 100644 index f04d92e..0000000 --- a/login_provider/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Configuration - -To enable the `debug` mode, set the environment variable `FLASK_ENV` to `development`. - -``` -export FLASK_ENV=development -# or -docker login-provider:latest build . && docker run -e FLASK_ENV=development login-provider -``` - -You can do the same with the following variables. - - * **FLASK_SECRET_KEY** A secret key that will be used for securely signing the session cookie. - * **FLASK_RUN_HOST** IP Address that the server will open a socket on. - *Default*: 0.0.0.0 - * **FLASK_RUN_PORT** Port of the socket that the server will listen on. - *Default*: 5000 - * **GRAPHQL_URL** URL to the server that runs the graphql backend API - *Default*: http://localhost:5002/graphql - * **HYDRA_ADMIN_URL** URl to the Hydra admin server - *Default*: http://localhost:4445 - diff --git a/login_provider/app.py b/login_provider/app.py deleted file mode 100644 index 67ccce1..0000000 --- a/login_provider/app.py +++ /dev/null @@ -1,106 +0,0 @@ -from flask import abort, Flask, redirect, request, render_template -from os import urandom, environ -from hydra_client import HydraAdmin -import hydra_client -from db import User, BackendConnectionError -from forms import LoginForm -import logging - -HYDRA_ADMIN_URL = environ['HYDRA_ADMIN_URL'] -HYDRA = HydraAdmin(HYDRA_ADMIN_URL) - -app = Flask(__name__) -app.config['SECRET_KEY'] = urandom(16) -app.debug = True if "FLASK_ENV" in environ and environ["FLASK_ENV"] == "development" else False -app.logger.setLevel(logging.INFO) - -@app.route('/login', methods=['GET', 'POST']) -def login(): - """Provides login form and handles login attempt - - Args: - login_form: contains login data submitted by a user (POST) - challenge: id that identifies the request from oauth client. passed by hydra - - Returns: - Error page if no challenge id is present - or Login Form if user hasn't authenticated - or redirect to callback url provided by hydra if login was successful - """ - login_form = LoginForm() - redirect_to = None - - # Retrieve the challenge id from the request. Depending on the method it is saved in the - # form (POST) or in a GET variable. - if request.method == 'GET': - challenge = request.args.get("login_challenge") - if not challenge: - return abort(400) - elif login_form.validate_on_submit(): - challenge = login_form.challenge.data - - # Now that we have the challenge id, we can request the challenge object from the hydra - # admin API - try: - login_request = HYDRA.login_request(challenge) - except hydra_client.exceptions.NotFound: - app.logger.error("Not Found. Login request not found. challenge={0}".format(challenge)) - abort(404) - except hydra_client.exceptions.HTTPError: - app.logger.error("Conflict. Login request has been used already. challenge={0}".format(challenge)) - abort(503) - - # We need to decide here whether we want to accept or decline the login request. - # if a login form was submitted, we need to confirm that the userdata, the agent - # send us via POST is valid - if login_form.validate_on_submit(): - try: - user = User(login_form.username.data) - except BackendConnectionError as error: - app.logger.error( - "Retrieving user object from GraphQL server failed {0}".format(error)) - return redirect(login_request.reject( - "Login denied", - error_description="Login request was denied due to an internal server error")) - if user.authenticate(login_form.password.data): - redirect_to = login_request.accept( - user.username, - remember=login_form.remember.data, - # Remember session for 12h - remember_for=60*60*12) - app.logger.info("{0} logged in successfully".format(user.username)) - else: - redirect_to = login_request.reject( - "Login denied", - error_description="Invalid username or password") - app.logger.info("{0} failed to login".format(user.username)) - return redirect(redirect_to) - - # Skip, if true, let's us know that Hydra has already successfully authenticated - # the user. we don't need to check anything and we can accept the request right away. - elif login_request.skip: - skip = request.args.get("skip") - logout = request.args.get("logout") - if skip: - app.logger.info("{0} is already logged in. Skip authentication".format(login_request.subject)) - return redirect(login_request.accept(login_request.subject)) - elif logout: - login_form.challenge.data = challenge - HYDRA.invalidate_login_sessions(login_request.subject); - return redirect(login_request.reject( - "Login cancelled", - error_description="Login was cancelled and user session was terminated")) - else: - return render_template('skip.html', challenge=challenge, logo=login_request.client.logo_uri, application_name=login_request.client.client_name, username=login_request.subject) - - - - # If Skip is not true and the user has not submitted any data via a form, we need - # to display a login form for the user to type in their username and password. - # as a reference we save the challenge id in a hidden field of the form. - else: - login_form.challenge.data = challenge - return render_template('login.html', login_form=login_form, logo=login_request.client.logo_uri, application_name=login_request.client.client_name) - -if __name__ == '__main__': - app.run() diff --git a/login_provider/db.py b/login_provider/db.py deleted file mode 100644 index bf4de35..0000000 --- a/login_provider/db.py +++ /dev/null @@ -1,76 +0,0 @@ -from os import environ -from hydra_client import HydraAdmin -from flask_login import UserMixin -from graphqlclient import GraphQLClient -import urllib -import json - -GRAPHQL_URL = environ['GRAPHQL_URL'] -graphql_client = GraphQLClient(GRAPHQL_URL) - - -class User(UserMixin): - def __init__(self, username): - self.id = username - self.username = username - self.active = False - try: - self._load_remote_user_info() - except urllib.error.HTTPError as error: - raise BackendConnectionError( - error.code, - error.headers, - ("Error during retrieval of userdata - " + error.reason)) - - def _load_remote_user_info(self): - """Loads userdata from remote GraphQL API""" - querystring = '''{{ - getUser(username: "{0}"){{ - email, - active - }}}}'''.format(self.username) - result = json.loads(graphql_client.execute(querystring)) - if "data" in result and result["data"]["getUser"] is not None: - self.active = result["data"]["getUser"]["active"] - self.email = result["data"]["getUser"]["email"] - - def _verify_password(self, password): - """Verifies cleartext password - - Sends the cleartext `password` to the GraphQL API - which verifies the password by hashing it and comparing it to a stored password - hash. - - Args: - password: cleartext password - - Returns: - Boolean result of password verification - """ - password = password.replace('"', '\\"') - querystring = '''{{ - verifyPassword( - username: "{0}", - password: "{1}") - }}'''.format(self.username, password) - result = json.loads(graphql_client.execute(querystring)) - verified = False - if "data" in result: - verified = result["data"]["verifyPassword"] - return verified - - def authenticate(self, password): - return self.active and self._verify_password(password) - -class BackendConnectionError(Exception): - """Raised when requests to the backend server fail - - Attributes: - code -- http response code - headers -- http response headers - reason -- reson for the error - """ - def __init__(self, code, headers, reason): - self.code = code - self.headers = headers - self.reason = reason diff --git a/login_provider/forms.py b/login_provider/forms.py deleted file mode 100644 index ed80ed0..0000000 --- a/login_provider/forms.py +++ /dev/null @@ -1,10 +0,0 @@ -from wtforms import SubmitField, StringField, PasswordField, BooleanField, HiddenField, validators -from flask_wtf import FlaskForm - - -class LoginForm(FlaskForm): - username = StringField("Username", validators=[validators.input_required()],) - password = PasswordField("Password", validators=[validators.input_required()]) - challenge = HiddenField("challenge") - remember = BooleanField("Remember me") - submit = SubmitField("Sign in") diff --git a/login_provider/requirements.txt b/login_provider/requirements.txt deleted file mode 100644 index 3c617cd..0000000 --- a/login_provider/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -Flask -flask-wtf -flask-login -hydra-client -Flask-SQLAlchemy -bcrypt -graphqlclient diff --git a/login_provider/templates/login.html b/login_provider/templates/login.html deleted file mode 100644 index 912d0bf..0000000 --- a/login_provider/templates/login.html +++ /dev/null @@ -1,18 +0,0 @@ -<!doctype html> -<title>Stackspin authentication service</title> -<div style='margin: 0 auto ; width: 350px; padding:20px; border-style:solid; border-color:#6c757d; border-width: 1px; background-color: #f8f9fa; font-family: "Segoe UI", Roboto; font-family: "Helvetica Neue", Arial; font-family: "Noto Sans", sans-serif;'> - {% if logo %} - <div style="position:relative; width: 350px; height:100px"> - <img style="overflow: auto; top: 0; left: 0; bottom: 0; right: 0; position: absolute; margin: auto;max-width: 300px; max-height: 100px" src="{{logo}}" alt="Logo of application"></img> - </div> - {% endif %} - <h1>Log in to {{ application_name }}</h1> - <form method="POST" action="/login"> - {{ login_form.csrf_token }} - {{ login_form.challenge }} - {{ login_form.username(placeholder="Username", autofocus=true) }}<br> - <div style="margin-top:5px">{{ login_form.password(placeholder="Password") }}</div> <br> - {{ login_form.remember }}{{ login_form.remember.label }} <br> - <div style="margin-top:5px">{{ login_form.submit }}</div> - </form> -</div> diff --git a/login_provider/templates/skip.html b/login_provider/templates/skip.html deleted file mode 100644 index 8effa54..0000000 --- a/login_provider/templates/skip.html +++ /dev/null @@ -1,14 +0,0 @@ -<!doctype html> -<title>Stackspin authentication service</title> -<div style='margin: 0 auto ; width: 350px; padding:20px; border-style:solid; border-color:#6c757d; border-width: 1px; background-color: #f8f9fa; font-family: "Segoe UI", Roboto; font-family: "Helvetica Neue", Arial; font-family: "Noto Sans", sans-serif;'> - {% if logo %} - <div style="position:relative; width: 350px; height:100px"> - <img style="overflow: auto; top: 0; left: 0; bottom: 0; right: 0; position: absolute; margin: auto;max-width: 300px; max-height: 100px" src="{{logo}}" alt="Logo of application"></img> - </div> - {% endif %} - <h1>Log in to {{ application_name }}</h1> - <div style="width: 100%; margin-bottom: 5px; overflow: auto"> - <div style="width:60%; float:left"><button id="continue" onclick="window.location.href = '/login?login_challenge={{ challenge }}&skip=true';">Continue with {{ username }}</button></div> - <div style="width:40%; float:left;"><button id="logout" onclick="window.location.href = '/login?login_challenge={{ challenge }}&logout=true';">Logout</button></div> - </div> -</div> diff --git a/logout_provider/Dockerfile b/logout_provider/Dockerfile deleted file mode 100644 index 1312fc3..0000000 --- a/logout_provider/Dockerfile +++ /dev/null @@ -1,22 +0,0 @@ -FROM python:3.9-alpine - -RUN apk add gcc libc-dev libffi-dev - -WORKDIR /usr/src/app - -COPY requirements.txt ./ -RUN pip install --no-cache-dir -r requirements.txt - -COPY . . - -ARG FLASK_PORT=5002 - -EXPOSE $FLASK_PORT - -ENV FLASK_ENV production -ENV FLASK_RUN_PORT $FLASK_PORT -ENV FLASK_RUN_HOST 0.0.0.0 -ENV HYDRA_ADMIN_URL http://localhost:4445 - - -CMD [ "flask", "run" ] diff --git a/logout_provider/app.py b/logout_provider/app.py deleted file mode 100644 index e17cebc..0000000 --- a/logout_provider/app.py +++ /dev/null @@ -1,44 +0,0 @@ -from flask import abort, Flask, redirect, request -from flask.views import View -from hydra_client import HydraAdmin -import hydra_client -import logging -from os import environ - -HYDRA_ADMIN_URL = environ['HYDRA_ADMIN_URL'] -HYDRA = HydraAdmin(HYDRA_ADMIN_URL) - -app = Flask(__name__) -app.logger.setLevel(logging.INFO) - -@app.route('/logout', methods=['GET']) -def home(): - """Handles the OpenID Connect Logout flow - - Communicates with the hydra server to start the logout flow which uses backchannel and - frontchannel logout methods to log out the user from all applications they have - access to. - - Args: - logout_challenge: Reference to a logout challenge object in form of an alphanumeric - String. Can be used to retrieve the LogoutRequest object via the Hydra Admin API (GET) - - Returns: - Redirect to the url that is provided by the LogoutRequest object. - """ - challenge = request.args.get("logout_challenge") - app.logger.info("Logout request: challenge={0}".format(challenge)) - if not challenge: - abort(403) - try: - logout_request = HYDRA.logout_request(challenge) - except hydra_client.exceptions.NotFound: - app.logger.error("Not Found. Logout request not found. challenge={0}".format(challenge)) - abort(404) - except hydra_client.exceptions.HTTPError: - app.logger.error("Conflict. Logout request has been used already. challenge={0}".format(challenge)) - abort(503) - return redirect(logout_request.accept(subject=logout_request.subject)) - -if __name__ == '__main__': - app.run() diff --git a/logout_provider/requirements.txt b/logout_provider/requirements.txt deleted file mode 100644 index 435993d..0000000 --- a/logout_provider/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -Flask -hydra-client diff --git a/user-panel b/user-panel deleted file mode 160000 index 9a16055..0000000 --- a/user-panel +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9a16055973a2b36acf361e853eb55b4cfbd0c6f4 -- GitLab