Skip to content

Commit

Permalink
Replace SAML with OIDC
Browse files Browse the repository at this point in the history
  • Loading branch information
cc-a committed Jul 2, 2024
1 parent f203166 commit acfe9be
Show file tree
Hide file tree
Showing 9 changed files with 819 additions and 737 deletions.
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ FROM registry.cern.ch/inveniosoftware/almalinux:1

COPY site ./site
COPY Pipfile Pipfile.lock ./
RUN yum install -y libtool-ltdl-devel xmlsec1-openssl && yum clean all
RUN pipenv install --deploy --system

COPY ./docker/uwsgi/ ${INVENIO_INSTANCE_PATH}
Expand Down
2 changes: 0 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ pytest-invenio = "*"
[packages]
invenio-app-rdm = {extras = ["postgresql", "opensearch2"], version = "~=11.0.0"}
ic-data-repo = {editable="True", path="./site"}
invenio-saml = {}

uwsgi = ">=2.0"
uwsgitop = ">=0.11"
uwsgi-tools = ">=1.1.1"
Expand Down
1,429 changes: 742 additions & 687 deletions Pipfile.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions docker-services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ services:
- "INVENIO_SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://ic-data-repo:ic-data-repo@db/ic-data-repo"
- "INVENIO_WSGI_PROXIES=2"
- "INVENIO_RATELIMIT_STORAGE_URL=redis://cache:6379/3"
- "ICL_OAUTH_CLIENT_ID"
- "ICL_OAUTH_CLIENT_SECRET"
- "ICL_OAUTH_WELL_KNOWN_URL"
frontend:
build: ./docker/nginx/
image: ic-data-repo-frontend
Expand Down
1 change: 1 addition & 0 deletions site/ic_data_repo/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Authentication module."""
43 changes: 43 additions & 0 deletions site/ic_data_repo/auth/oauth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Implement OAuth handlers."""

import jwt
import requests
from flask import current_app


def info_handler(remote_app, response_data):
"""Extract account info from authorisation response.
Extracts and validates the id_token returned as part of the OIDC workflow using
metadata from the OpenId provider. Claims from the JWT are then returned in the
expected structure for user sign-up process.
Requires the following claims to be present in the id_token: email,
preferred_username, name and oid.
"""
oidc_config = requests.get(current_app.config["ICL_OAUTH_WELL_KNOWN_URL"]).json()
signing_algos = oidc_config["id_token_signing_alg_values_supported"]
jwks_client = jwt.PyJWKClient(oidc_config["jwks_uri"])

id_token = response_data["id_token"]
signing_key = jwks_client.get_signing_key_from_jwt(id_token)

data = jwt.api_jwt.decode(
id_token,
key=signing_key.key,
algorithms=signing_algos,
audience=remote_app.consumer_key,
)

return dict(
user=dict(
email=data["email"],
profile=dict(
username=data["preferred_username"].rstrip("@ic.ac.uk"),
full_name=data["name"],
),
),
external_id=data["oid"],
external_method="icl_sso",
active=True,
)
2 changes: 0 additions & 2 deletions site/ic_data_repo/config/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,4 @@
SITE_UI_URL = f"https://{APP_ALLOWED_HOSTS[0]}"
SITE_API_URL = f"https://{APP_ALLOWED_HOSTS[0]}/api"

SSO_SAML_IDPS["icl"]["settings"]["debug"] = False # noqa: F405

ACCOUNTS_LOCAL_LOGIN_ENABLED = False
62 changes: 30 additions & 32 deletions site/ic_data_repo/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
https://inveniordm.docs.cern.ch/reference/configuration/.
"""

import os
from datetime import datetime

from invenio_oauthclient.views.client import auto_redirect_login
from invenio_saml.handlers import acs_handler_factory, default_sls_handler

# Flask
# =====
Expand Down Expand Up @@ -170,14 +170,41 @@
SECURITY_LOGIN_WITHOUT_CONFIRMATION = (
False # require users to confirm email before being able to login
)
SECURITY_LOGIN_USER_TEMPLATE = "ic_data_repo/login_user.html"
SECURITY_LOGIN_USER_TEMPLATE = "invenio_accounts/login_user.html"

# Invenio-OAuthclient
# -------------------
# See:
# https://github.com/inveniosoftware/invenio-oauthclient/blob/master/invenio_oauthclient/config.py

OAUTHCLIENT_REMOTE_APPS = {} # configure external login providers
OAUTHCLIENT_REMOTE_APPS = dict()

ICL_OAUTH_CLIENT_ID = os.getenv("ICL_OAUTH_CLIENT_ID")
ICL_OAUTH_CLIENT_SECRET = os.getenv("ICL_OAUTH_CLIENT_SECRET")
ICL_OAUTH_WELL_KNOWN_URL = os.getenv("ICL_OAUTH_WELL_KNOWN_URL")

if ICL_OAUTH_CLIENT_ID and ICL_OAUTH_CLIENT_SECRET and ICL_OAUTH_WELL_KNOWN_URL:
OAUTHCLIENT_REMOTE_APPS["icl"] = dict(
title="Imperial College Single Sign On",
description="Authentication via membership of Imperial College",
icon="",
params=dict(
request_token_params=dict(scope="openid profile"),
base_url="",
request_token_url=None,
access_token_url="https://login.microsoftonline.com/2b897507-ee8c-4575-830b-4f8267c3d307/oauth2/v2.0/token", # noqa: E501
access_token_method="POST",
authorize_url="https://login.microsoftonline.com/2b897507-ee8c-4575-830b-4f8267c3d307/oauth2/v2.0/authorize", # noqa: E501
consumer_key=ICL_OAUTH_CLIENT_ID,
consumer_secret=ICL_OAUTH_CLIENT_SECRET,
),
authorized_handler="invenio_oauthclient.handlers:authorized_signup_handler",
disconnect_handler="invenio_oauthclient.handlers:disconnect_handler",
signup_handler=dict(
info="ic_data_repo.auth.oauth:info_handler",
),
signup_options=dict(auto_confirm=True, send_register_msg=False),
)

ACCOUNTS_LOGIN_VIEW_FUNCTION = (
auto_redirect_login # autoredirect to external login if enabled
Expand All @@ -204,32 +231,3 @@
SEARCH_INDEX_PREFIX = "ic-data-repo-"

THEME_SHOW_FRONTPAGE_INTRO_SECTION = False

SSO_SAML_IDPS = dict(
icl=dict(
sp_cert_file="app_data/certificates/saml.cert",
sp_key_file="app_data/certificates/saml.key",
settings_url="https://login.microsoftonline.com/2b897507-ee8c-4575-830b-4f8267c3d307/federationmetadata/2007-06/federationmetadata.xml", # noqa: E501
settings=dict(
strict=True,
debug=True,
idp=dict(
x509cert="",
),
sp=dict(
NameIDFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
entityId="api://06ccf553-edc8-4ab1-8958-30088a2eb0b7",
),
security=dict(requestedAuthnContext=False),
),
mappings=dict(
email="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
surname="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
external_id="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
),
acs_handler=acs_handler_factory("icl"),
sls_handler=default_sls_handler,
auto_confirm=True,
)
)
13 changes: 0 additions & 13 deletions templates/ic_data_repo/login_user.html

This file was deleted.

0 comments on commit acfe9be

Please sign in to comment.