Поставщик услуг SAML 2.0 в Python

Я ищу для внедрения поставщика услуг на базе SAML 2.0 в Python.

Мои веб-приложения в настоящее время являются всеми флеш-приложениями. Я планирую сделать дизайн / декоратор Flask, который позволяет мне отбрасывать возможности единого входа в существующие ранее приложения.

Я широко изучил python-saml и, к сожалению, есть проблемы с зависимостями, которые не могут быть решены, поскольку у меня слишком много ранее существовавших серверов / приложений, чья среда не будет совместима.

PySAML2 выглядит так, как будто он может работать, однако документации мало, и какая документация доступна. У меня проблемы с пониманием. В приложении Flask нет примеров PySAML2.

У Identity Provider у меня есть Okta. У меня Okta настроен так, что после входа в Okta я перенаправлен в свое приложение.

Может ли кто-нибудь предложить какие-либо советы по использованию PySAML2 или, возможно, советы о том, как лучше всего аутентифицировать пользователя, использующего SAML 2.0, который посещает мое приложение?

  • Вход в сервер аутентификации SAML / Shibboleth с использованием python
  • One Solution collect form web for “Поставщик услуг SAML 2.0 в Python”

    Обновление: подробное объяснение использования PySAML2 с Okta теперь находится на developer.okta.com.

    Ниже приведен пример кода для реализации SAML SP в Python / Flask. Этот пример кода демонстрирует несколько вещей:

    1. Поддержка нескольких IdP.
    2. Использование Flask-Login для управления пользователями.
    3. Использование «URL-адреса единого входа» в качестве ограничения аудитории (для упрощения конфигурации на IdP).
    4. Простое предоставление времени пользователям («SAML JIT»)
    5. Передача дополнительной информации о пользователе в отчетах атрибутов.

    То, что не продемонстрировано, – это инициированные SP запросы проверки подлинности – я последую за этим позже.

    В какой-то момент я надеюсь создать обертку вокруг pysaml2, у которой есть утомленные умолчания.

    Наконец, как и python-saml, библиотека pysaml2 использует xmlsec1 файл xmlsec1 . Это может также вызвать проблемы с зависимостями в средах вашего сервера. Если это так, вам нужно взглянуть на замену xmlsec1 на библиотеку signxml .

    Все в примере ниже должно работать со следующей настройкой:

     $ virtualenv venv $ source venv/bin/activate $ pip install flask flask-login pysaml2 

    Наконец, вам нужно будет сделать что-то на стороне Okta, чтобы это работало.

    Во-первых: На вкладке « Общие » вашей конфигурации приложения Okta настройте приложение для отправки утверждений «FirstName» и «LastName». Добавление утверждений атрибута в приложение Okta

    Второе: на вкладке «Единый вход» вашей конфигурации приложения Okta возьмите URL-адрес и поместите его в файл с именем example.okta.com.metadata . Вы можете сделать это с помощью команды, подобной приведенной ниже.

     $ curl [the metadata url for your Okta application] > example.okta.com.metadata 

    Где найти URL-адрес метаданных для приложения Okta

    Вот что вам понадобится для приложения Python / Flask для обработки инициированных IdP запросов SAML:

     # -*- coding: utf-8 -*- import base64 import logging import os import urllib import uuid import zlib from flask import Flask from flask import redirect from flask import request from flask import url_for from flask.ext.login import LoginManager from flask.ext.login import UserMixin from flask.ext.login import current_user from flask.ext.login import login_required from flask.ext.login import login_user from saml2 import BINDING_HTTP_POST from saml2 import BINDING_HTTP_REDIRECT from saml2 import entity from saml2.client import Saml2Client from saml2.config import Config as Saml2Config # PER APPLICATION configuration settings. # Each SAML service that you support will have different values here. idp_settings = { u'example.okta.com': { u"metadata": { "local": [u'./example.okta.com.metadata'] } }, } app = Flask(__name__) app.secret_key = str(uuid.uuid4()) # Replace with your secret key login_manager = LoginManager() login_manager.setup_app(app) logging.basicConfig(level=logging.DEBUG) # Replace this with your own user store user_store = {} class User(UserMixin): def __init__(self, user_id): user = {} self.id = None self.first_name = None self.last_name = None try: user = user_store[user_id] self.id = unicode(user_id) self.first_name = user['first_name'] self.last_name = user['last_name'] except: pass @login_manager.user_loader def load_user(user_id): return User(user_id) @app.route("/") def main_page(): return "Hello" @app.route("/saml/sso/<idp_name>", methods=['POST']) def idp_initiated(idp_name): settings = idp_settings[idp_name] settings['service'] = { 'sp': { 'endpoints': { 'assertion_consumer_service': [ (request.url, BINDING_HTTP_REDIRECT), (request.url, BINDING_HTTP_POST) ], }, # Don't verify that the incoming requests originate from us via # the built-in cache for authn request ids in pysaml2 'allow_unsolicited': True, 'authn_requests_signed': False, 'logout_requests_signed': True, 'want_assertions_signed': True, 'want_response_signed': False, }, } spConfig = Saml2Config() spConfig.load(settings) spConfig.allow_unknown_attributes = True cli = Saml2Client(config=spConfig) try: authn_response = cli.parse_authn_request_response( request.form['SAMLResponse'], entity.BINDING_HTTP_POST) authn_response.get_identity() user_info = authn_response.get_subject() username = user_info.text valid = True except Exception as e: logging.error(e) valid = False return str(e), 401 # "JIT provisioning" if username not in user_store: user_store[username] = { 'first_name': authn_response.ava['FirstName'][0], 'last_name': authn_response.ava['LastName'][0], } user = User(username) login_user(user) # TODO: If it exists, redirect to request.form['RelayState'] return redirect(url_for('user')) @app.route("/user") @login_required def user(): msg = u"Hello {user.first_name} {user.last_name}".format(user=current_user) return msg if __name__ == "__main__": port = int(os.environ.get('PORT', 5000)) if port == 5000: app.debug = True app.run(host='0.0.0.0', port=port) 
    Python - лучший язык программирования в мире.