SAML 集成介绍

介绍

SAML协议

SAML( Security Assertion Markup Language)是一种标准化的身份认证协议,主要用于在不同的域(比如不同服务)之间安全地交换身份验证和授权数据。其技术文档可以在 OASIS(结构化信息标准促进组织)官方网站查看。

简要流程如下:

SAML协议中的概念

SP(Service Provider)

服务提供商(SP)是一个提供服务的实体,比如一个网站或应用。用户希望通过SP访问资源。在SAML身份认证过程中,SP是请求和接收关于用户身份信息的一方。

IDP(Identity Provider)

身份提供商(IDP)是负责认证用户身份并将这些信息提供给服务提供商的系统。在SAML流程中,当用户试图登录服务提供商提供的服务时,IDP负责验证用户的身份,并向SP发送断言来确认这一身份。

Metadata(元数据)

在SAML中,元数据是用来描述IDP(身份提供商)和SP(服务提供商)的配置信息的XML文档。它包括了以下几类重要信息:

  • 实体描述符 (md:IDPSSODescriptor/md:SPSSODescriptor):标识实体(IDP或SP)并包括关于实体的信息,如实体ID和服务位置。
  • 服务终点 (md:xxxxService ):提供服务地址,比如哪里可以发送SAML请求(如认证请求)或哪里可以接收SAML响应(如认证响应)。
  • 密钥信息 (md:KeyDescriptor):用于签名和加密消息的公开密钥信息,确保信息的安全性。
  • ID格式 (md:NameIDFormat):说明实体支持用户ID格式。

元数据的交换在SP和IDP之间建立信任关系和技术配置时进行。例如,在配置过程中,SP和IDP会相互提供自己的元数据,从而确保双方都有正确的信息来安全地发送和接收SAML消息。

SAML断言

SAML断言是由IDP创建并发送给SP的一种消息,它包含了验证用户身份的信息。断言通常包括以下几个部分:

  • 断言ID (saml:Assertion ID):一个唯一标识符,用于区分不同的断言。
  • 发行者 (saml:Issuer):创建断言的IDP的标识。
  • 主题 (saml:Subject):关于用户的信息,通常包括用户的唯一标识符和可能的会话索引。
  • 条件 (saml:Conditions):定义断言有效性的时间窗口和接收断言的SP的约束。
  • 属性声明 (saml:AttributeStatement):具体的用户属性,如用户名、邮箱、角色等。
  • 身份验证声明 (saml:AuthnStatement):包含用户身份验证成功的时间和方法的信息。

在实际应用中,当用户尝试访问SP的资源时,SP会将用户重定向到IDP进行身份验证。用户在IDP成功认证后,IDP会创建一个SAML断言,包含用户的身份和属性信息,并将其发送回SP。SP接收到断言后,会验证断言的签名,确认其来自可信的IDP,并根据断言中的信息决定是否授权用户访问请求的资源。

流程图

验证

为了便于验证 SAML 协议,我们将使用 Docker 来搭建环境,keycloak的作为IDP,WordPress作为SP,用来演示SAML登陆流程。在生产环境下,应该根据实际情况配置和准备环境。

准备Docker镜像

准备docker-compose,并创建sp和idp需要的相关文件。

  • 参考https://docs.docker.com/compose/install/ 安装你的docker-compose环境,安装完成后使用docker-compose -v检查docker-compose是否安装成功

    1
    2
    $ sudo docker-compose -v
    docker-compose version 1.29.2, build unknown
  • 创建一个demoiam文件夹,按照下面结构创建文件,也可以直接从 https://github.com/lich-wang/demoiam 获取配置好的文件

    1
    2
    3
    4
    5
    6
    $ tree ~/demoiam/
    demoiam/
    ├── testidp
    │ └── docker-compose.yml
    └── testsp
    └── docker-compose.yml
    • 配置testidp/docker-compose.yml 如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    version: '3'
    services:
    keycloak:
    image: keycloak/keycloak
    ports:
    - "20000:8080"
    environment:
    KEYCLOAK_ADMIN: admin
    KEYCLOAK_ADMIN_PASSWORD: admin
    command:
    - start-dev
    volumes:
    - keycloak_data:/opt/jboss/keycloak/standalone/data

    volumes:
    keycloak_data:
    • 配置testspdocker-compose.yml 如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    version: '3'
    services:

    wordpress:
    image: wordpress
    restart: always
    ports:
    - 20001:80
    environment:
    WORDPRESS_DB_HOST: db
    WORDPRESS_DB_USER: exampleuser
    WORDPRESS_DB_PASSWORD: examplepass
    WORDPRESS_DB_NAME: exampledb
    volumes:
    - wordpress:/var/www/html

    db:
    image: mysql:8.0
    restart: always
    environment:
    MYSQL_DATABASE: exampledb
    MYSQL_USER: exampleuser
    MYSQL_PASSWORD: examplepass
    MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
    - db:/var/lib/mysql

    volumes:
    wordpress:
    db:

初始化IDP

  • 进入IDP路径,启动环境

    1
    2
    3
    4
    5
    $ cd ~/demoiam/testidp/
    $ sudo docker-compose up -d
    Creating network "testidp_default" with the default driver
    Creating volume "testidp_keycloak_data" with default driver
    Creating testidp_keycloak_1 ... done
  • 进入控制台,创建一个新用户

    • 打开 http://localhost:20000/ 输入 用户名admin密码admin,进入控制台
      login
    • 从左侧导航进入Users页面,点击Add User创建一个新用户
      add user
      • Username后输入用户名test1,点击Create创建用户
        creat user
      • 创建成功后,点击test1用户的credentials标签,点击Set Password 为用户创建密码
        set password
      • PasswordPassword confirmation分别输入test1作为密码,然后点击Save为用户保存密码
        finish passwrod
        finish passwrod
  • 导出IDP的SAML元数据
    在左侧导航栏点击Realm Settings下划到最后,右键点击SAML 2.0 Identity Provider Metadata另存链接为IDP.xml
    export idp xml

初始化SP

  • 进入IDP路径,启动环境

    1
    2
    3
    4
    5
    6
    7
    $ cd ~/demoiam/testsp/
    $ sudo docker-compose up -d
    Creating network "testsp_default" with the default driver
    Creating volume "testsp_wordpress" with default driver
    Creating volume "testsp_db" with default driver
    Creating testsp_db_1 ... done
    Creating testsp_wordpress_1 ... done
  • 完成SP 初始化,并启用SAML集成

    • 打开 http://localhost:20001/ 选择语言简体中文后,点击```继续``完成配置
      inital sp
    • 设置用户名admin密码w0rd@Press邮箱admin@admin.com后,点击安装WordPress
      inital sp
    • 点击登陆,在登陆页面输入刚才设置的用户名admin密码w0rd@Press后,点击登陆
      login sp
      login sp
    • 登陆后,添加SAML插件启用SAML登陆
      • 点击左侧导航页插件下的添加插件,在右侧搜索输入SAML选择SAML Single Sign On – SSO Login安装,并启用
        enable saml
        enable saml
      • 刷新页面页面后,在左侧导航栏新出现的SAML Single Sign On – SSO Login下点击Service Provider Metadata页签
        export sp xml
      • 点击Metadata XML File 下的DownLoad下载SP元数据,并将下载后的文件修改为sp.xml

配置SAML元数据

  • SP 导入IDP元数据
    • 打开 http://localhost:20001/wp-admin 用之前设置用户名admin密码w0rd@Press登陆
      improt idp xml
    • 从左侧导航栏的SAML Single Sign On – SSO Login进入Service Provider Setup页签
    • Configure Service Provider下选择Upload IDP Metadata
      • Identity Provider Name :输入testidp
      • Upload Metadata :选择之前下的idp.xml
      • 点击upload上传
        improt idp xml
  • IDP导入SP元数据
    • 打开 http://localhost:20000/ 输入 用户名admin密码admin,进入控制台
      import sp xml
    • 点击左侧Clients页签,选择Import client
      import sp xml
      • Resource file右侧点击Browse...选择之前下载的sp.xml,后点击Save
        import sp xml

使用SAMLTrace进行调试跟踪

为方便后续调整,这里举例使用Edge浏览器并安装SAMLTrace扩展,使用隐私模式进行SAML验证

  • 安装SAMLTrace
  • 使用Edge的隐私模式进行SAML验证
    • 在Edge浏览器右侧...设置列表内找到新建Inprivate窗口或者按下快捷键Ctrl+Shift+N
    • 在隐私模式下访问 http://localhost:20001/wp-login.php ,并点击 Login with testdip
      test login
      • 页面跳转到 IDP登录页面
      • 在IDP登录页输入之前配置的用户名test1密码test1并登录
        test login
      • 在IDP登录重置初始密码为test2
        test login
      • 页面跳回SP,并登录成功
        test login
    • 点击地址栏右侧扩展图标,点击打开SAMLTrace可以查看相关SAML请求
      check log
      check log