第1部分。Liberty Profile中的OIDC支持
OpenID Connect 1.0(OIDC)是基于OAuth 2.0的简单身份协议。 OIDC正在成为公认的Internet SSO协议,并且可以与云,移动和本机应用程序很好地协同工作。 OIDC允许客户端应用程序(例如云或移动应用程序)以标准化的,类似于REST的方式请求用户身份作为ID令牌。 此外,客户端应用程序可以使用访问令牌来访问类似REST的服务。
Liberty Profile中的OIDC提供程序是作为OAuth 2.0扩展实现的,可以用作发布OAuth 2.0访问令牌并支持所有OAuth 2.0授予类型的普通OAuth 2.0授权提供程序。
本教程的先决条件
- 对OIDC和OAuth 2.0协议有基本了解。 尽管执行配置步骤不需要了解这一点,但是为了评估OIDC在您的企业中的安全影响,它是必需的。
- 对Liberty Profile的基本了解,包括熟悉安装,创建服务器和更新服务器配置。
- Liberty Profile V8.5.5.4或更高版本,按照说明安装了OIDC功能。 转到<liberty_root> / bin文件夹,然后发出以下两个命令:
featureManager install openidConnectServer-1.0 --when-file-exists=ignore featureManager install openidConnectClient-1.0 --when-file-exists=ignore
OIDC架构
OIDC的关键术语包括最终用户,依赖方(RP)和OIDC提供商(OP),如图1所示:
图1. OIDC关键术语
Liberty Profile V8.5.5.4引入了两个重要的高级配置选项:
- Liberty OIDC提供程序 –可以将专用的Liberty实例配置为OIDC提供程序(OP)和SSO服务器。 任何客户端应用程序都可以调用OP托管的RESTful安全服务来请求或验证最终用户身份和用户配置文件。
- Liberty OIDC依赖方 –可以将Liberty实例配置为OIDC依赖方,以利用Web SSO并将OIDC提供程序用作身份提供程序。 然后,Liberty安全容器可以调用OIDC OP来验证最终用户的身份,而不是让Liberty安全容器来处理用户验证。
WebSphere Application Server Full Profile V8.5.5.3还添加了对OIDC依赖方的支持,并且可以与OIDC提供程序一起参与Web SSO。
Web SSO和可选的身份传播方案
下面的图2显示了使用OIDC的典型Web SSO和身份传播方案,在三个安全域中具有三个Liberty Profile服务器。 这些服务器可以代表各个业务部门或独立的公司。 服务器RP向SSO服务器OP请求用户身份。 服务器RP使用已认证的身份进一步请求服务器RS的资源,服务器RS验证服务器OP的呼叫者身份。 然后,服务器RP和RS使用OP中的ID令牌或JSON对象创建一个JAAS主题,该主题代表用户并提供资源访问。
服务器OP是SSO服务器,因此用户只需登录一次OP。 使用OP进行身份验证后,用户可以从参与OP的SSO的多个安全RP服务器请求授权访问。
图2. Liberty Profile中的OIDC流程

OIDC功能
- 端点:Liberty Profile中的OIDC提供程序被实现为OAuth 2.0扩展。 除了提供所有OIDC功能之外,OIDC提供程序还支持所有OAuth 2.0功能。 Liberty OIDC提供程序支持以下端点:
- 授权端点
- 令牌端点
- 自省端点
- UserInfo端点
- 发现端点
- 覆盖图端点
- 注册端点
图3. Liberty Profile中的OIDC 1.0和OAuth 2.0端点
- 授予类型:自由OIDC支持所有OAuth 2.0授予类型,包括:
- 授权码
- 隐含的
- refresh_token
- client_credentials
- 密码
- urn:ietf:params:oauth:grant-type:jwt-bearer
- 多租户:Liberty Profile服务器支持多个OIDC提供程序实例,并且每个提供程序实例都有其自己的端点URL,同意表,登录表以及对自己的客户端和令牌的管理。
- 灵活的身份验证:除了使用LDAP用户注册表进行直接身份验证外,Liberty OIDC还可以配置为通过以下方式将用户身份验证委派给第三方身份验证服务,例如社交网站,SPNEGO服务器或SAML身份提供程序自定义TAI。 借助Liberty OIDC,您可以轻松地将OIDC与现有的企业标识服务集成。
- 信任和完整性:Liberty OIDC提供者使用客户端自己的密钥或提供者的私钥对ID令牌进行数字签名,并且ID令牌始终带有访问令牌。
- 管理和保护动态客户端注册。
- 高度可定制的提供程序:Liberty OIDC提供程序提供了定制的同意书,登录表,令牌中介和授权中介。
- ID令牌:ID令牌具有足够的声明来重新创建JAAS主题,并且可以扩展以提供自定义声明。 以下JSON是Liberty OP创建的典型ID令牌:
Liberty中的样本ID令牌
{ "iss":"https://acme.com/oidc/endpoint/idp", "sub":"marissa", "aud":"voting_application", "iat":1385062578, "exp":1385066178 "at_hash":”6820876yree” , “realmName”: “ldap://acme.com:389”, "uniqueSecurityName": "cn=malissa, o=acme", “groupIds”: [ “cn=board member, o=acme”, “cn=executive member, o=acme” ] , }
- 存储库:OIDC提供程序有两种类型的存储库:
- localStore-已注册的客户端存储在localStore元素内的server.xml中。 ID令牌,访问令牌和刷新令牌位于内存中,并且用户同意被缓存在HTTP会话中。 在localStore模式下,客户端注册端点仅支持读取操作。
- databaseStore-注册的客户端,访问令牌,ID令牌,刷新令牌和用户同意存储在数据库中。 令牌和用户同意是持久性的,即使在OP重新启动后也会自动恢复。 客户端注册端点的全部功能-包括创建,读取,更新和删除-仅在databaseStore模式下可用。
Liberty Profile已实现完整的OIDC规范。 有关OIDC的更多信息,请访问OpenID Connect网站 。 有关在Liberty Profile中配置OIDC的更多信息,请参阅WebSphere Application Server知识中心中的主题OpenID Connect 。
第2部分。Liberty Profile OIDC Web SSO示例
第2部分将向您展示如何使用Liberty Profile设置基本的OIDC Web SSO场景。
图4. OIDC Web SSO场景

设置OIDC提供程序
为OIDC提供程序创建一个Liberty服务器实例:转到<liberty_root> / bin文件夹并运行server create <server_name>。 本示例使用服务器名称oidcServer。 在<liberty_root> / usr / servers / oidcServer / server.xml中找到server.xml文件,在编辑器中将其打开,然后进行以下更改:
- 在<featureManager>部分中,添加服务器定义中缺少的以下所有功能。 这些更新将启用OIDC提供程序所需的功能:
所需的Liberty功能列表
<featureManager> <feature>openidConnectServer-1.0</feature> <feature>ssl-1.0</feature> <feature>appSecurity-2.0</feature> <feature>servlet-3.0</feature> </featureManager>
如果要使用LDAP用户注册表进行用户身份验证,则可以添加<feature> ldapRegistry-3.0 </ feature>;如果要使用OIDC useriInfo端点,则必须使用LDAP。
- 使用机器主机名更新httpEndpoint以处理远程测试请求,并确保定义了https端口:
<httpEndpoint id="defaultHttpEndpoint" host="op.example.com" httpPort="80" httpsPort="443" />
- 添加密钥库以启用SSL:
<keyStore id="defaultKeyStore" password="keypass" />
- 如果未配置LDAP注册表,请添加一些示例用户进行测试:
<basicRegistry id="basic" realm=" OpBasicRealm "> <user name="user1" password="security" /> </basicRegistry>
定义OAuth提供程序
OIDC建立在OAuth 2.0协议的基础上,您必须配置有效的OAuth服务提供商,包括适当的oauth-roles和oauthProvider元素。
创建oauth-role :任何有权使用OIDC的用户都必须具有oauth-role。 为了说明起见,此示例将oauth-role分配给所有经过身份验证的用户:
<oauth-roles>
<authenticated>
<special-subject type="ALL_AUTHENTICATED_USERS" />
</authenticated>
</oauth-roles>
创建oauthProvider元素 :该元素定义自定义登录页面,自定义同意表单,各种超时参数,客户端存储等。 Liberty OIDC为大多数必需的参数提供默认值,并且唯一需要的配置是定义客户端存储。 此示例使用localStore:
<oauthProvider id="Oauth" >
<localStore
</localStore>
</oauthProvider>
注册客户端 :Liberty OIDC提供程序要求所有客户端都必须注册并存储在localStore或databaseStore中。 每个注册的客户端都包含名称,机密,显示名称,重定向,范围,preAuthorizedScope和其他一些属性。 客户端将稍后注册。 这是localStore中的示例客户端:
<client name="oidcclient" secret="{xor}LDo8LTor"
displayname="sample client"
redirect="https://client.example.com:443/oauthclient/redirect.jsp"
scope="openid profile scope1 email phone address"
preAuthorizedScope="openid profile"
enabled="true"/>
定义OIDC提供者
下一步是创建一个openidConnectProvider元素,分配一个ID值,并创建对先前创建的oauthProvider的引用。
ID值很重要。 例如,如果您使用id =“ OP”将openidConnectProvider元素ID值设置为“ OP”,则在OIDC端点URL中使用“ OP”字符串,并且您的授权端点是https:// <主机名>:<端口号> / oidc / endpoint / OP / authorize,令牌端点为https:// <主机名>:<端口号> / oidc / endpoint / OP / token。
您可以更改ID值以定义不同的OIDC端点。 这是一个简单的OIDC提供程序配置,将授权端点定义为https://op.example.com:443/oidc/endpoint/OP/authorize:
<openidConnectProvider id="OP" oauthProviderRef="Oauth" >
</openidConnectProvider>
OIDC提供者样本:
<openidConnectProvider id="OP" oauthProviderRef="Oauth" >
</openidConnectProvider>
<oauthProvider id="Oauth" >
<localStore>
<client name="oidcclient" secret="{xor}LDo8LTor"
displayname="client001"
redirect="https://client.example.com:443/oauthclient/redirect.jsp"
scope="openid profile scope1 email phone address"
preAuthorizedScope="openid profile"
enabled="true"/>
</localStore>
</oauthProvider>
<oauth-roles>
<authenticated>
<special-subject type="ALL_AUTHENTICATED_USERS" />
</authenticated>
</oauth-roles>
OIDC提供程序设置已完成。 这是提供OIDC服务的示例server.xml文件:
具有虚拟客户端的Liberty OP配置
<server>
<featureManager>
<feature>openidConnectServer-1.0</feature>
<feature>ssl-1.0</feature>
<feature>appSecurity-2.0</feature>
<feature>servlet-3.0</feature>
</featureManager>
<basicRegistry id="basic" realm="OpBasicRealm">
<user name="user1" password="security" />
<user name="user2" password="security" />
</basicRegistry>
<keyStore id="defaultKeyStore" password="keyspass" />
<httpEndpoint host="op.example.com" httpPort="80" httpsPort="443"
id="defaultHttpEndpoint"/>
<oauth-roles>
<authenticated>
<special-subject type="ALL_AUTHENTICATED_USERS" />
</authenticated>
</oauth-roles>
<openidConnectProvider id="OP" oauthProviderRef="Oauth" >
</openidConnectProvider>
<oauthProvider id="Oauth" >
<localStore>
<client name="dummy" secret="{xor}LDo8LTor"
displayname="dummy"
redirect="https://localhost:8020/oauthclient/redirect.jsp"
scope="openid profile scope1 email phone address"
preAuthorizedScope="openid"
enabled="true"/>
</localStore>
</oauthProvider>
</server>
成立OIDC依赖方
在Liberty Profile中创建新服务器:转到<libertyroot> / bin文件夹,然后运行server create <server_name>。 本示例使用服务器名称oidcRP。 在<liberty_root> / usr / servers / <server_name> /server.xml中找到server.xml文件,在编辑器中将其打开,然后进行以下更改:
- 在<featureManager>部分中,添加服务器定义中缺少的以下所有功能。 这些更新将启用OIDC依赖方所需的功能:
Liberty RP中的功能列表
<featureManager> <feature>ssl-1.0</feature> <feature>jsp-2.2</feature> <feature>servlet-3.0</feature> <feature>appSecurity-2.0</feature> <feature>openidConnectClient-1.0</feature> </featureManager>
除非依赖方要验证RP注册表中是否存在OIDC提供程序的id_token中的用户名,否则不需要<feature> ldapRegistry-3.0 </ feature>。
- 使用计算机主机名更新httpEndpoint以处理远程测试请求,并确保定义了https端口。 如果在同一服务器上创建OIDC提供程序和依赖方,请确保它们使用不同的httpPort和httpsPort。
<httpEndpoint id="defaultHttpEndpoint" host="rp.example.com" httpPort="80" httpsPort="443" />
- 添加密钥库以启用SSL:<keyStore id =“ defaultKeyStore” password =“ keypass” />。 默认的密钥库和信任库位于<liberty_root> / usr / servers / <server_name> /resources/security/key.jks中。 确保将OIDC提供程序证书导入信任库,因为RP接收来自OpenID提供程序的令牌是必需的。
- 创建一个openidConnectClient元素以包含OIDC提供程序信息。 这是openidConnectClient元素的示例:
<openidConnectClient id="oidcRP" clientId="rp" clientSecret="{xor}LDo8LTor" authorizationEndpointUrl="https://op.example.com:443/oidc/endpoint/OP/authorize" tokenEndpointUrl="https://op.example.com:443/oidc/endpoint/OP/token"> </openidConnectClient>
在openidConnectClient内部,必须定义“ clientId”和“ clientSecret”,这是“ client_id”和“ client_secret”,这是OAuth 2.0客户端元数据中定义的OP中的客户端凭据。 根据RP和OP之间的安排,这两个值可以由RP或OP提供。 它们将在以后进行编辑。
Liberty OIDC RP为其redirect_url和请求的范围提供了默认值。 默认情况下,Liberty OP请求“打开的配置文件”范围,并且管理员可以使用属性“作用域”来修改所需的范围。 “ redirect_url”的计算方式为https://<host name>:<ssl port>/oidcclient/redirect/oidcRP
,其中oidcclient / redirect是固定的,其他部分也可以更改。 / oidcRP必须是openidConnectClient组件的ID值,并且主机名和ssl端口都在Web容器中计算。
在OP中注册RP
为了接受来自RP的授权请求,OP必须将RP注册为OAuth客户端:
- 准备RP注册数据:作为客户端,RP注册数据包括名称,机密,显示名称,重定向,作用域,preAuthorizedScope和其他属性。 通常,RP在注册过程中会提供到OP的重定向,而OP会分配所有其他重定向,但这取决于OP和RP之间的协商。 假设RP仅提供重定向,如https://rp.example.com:443/oidcclient/redirect/oidcRP。
- 将RP添加到OP客户端存储localStore。 禁用OP会分配RP的客户端数据(重定向除外),其名称为name =“ rp_1”,displayname =“ test RP”,Secret =“ RP的机密”和scope =“打开的配置文件电子邮件地址电话”,则RP的客户端条目为:
<client name="RP_1" secret="RP's secret" displayname="test RP" redirect=" https://rp.example.com:443/oidcclient/redirect/oidcRP " scope="openid profile email phone address" enabled="true"/>
- 编辑RP server.xml中的openidConnectClient元素以修改clientId和clientSecret。 RP的server.xml中的openidConnectClient元素定义为:
<openidConnectClient id="oidcRP" clientId="RP_1" clientSecret="RP's secret" authorizationEndpointUrl="https://op.example.com:443/oidc/endpoint/OP/authorize" tokenEndpointUrl="https://op.example.com:443/oidc/endpoint/OP/token"> </openidConnectClient>
交换证书
OIDC RP必须将OIDC OP证书导入RP的信任存储中,以便RP向OP请求令牌。 本示例对OP和RP使用相同的SSL密钥文件。
将应用程序部署到RP
- 在本教程的底部下载示例Web应用程序testpage.war 。 通过将应用程序复制到<liberty_root> / usr / servers / <server_name> / apps /来安装。 您可以使用定义了安全性约束和角色的任何Web应用程序。
- 配置Web应用程序以进行安全访问,如下所示:
<application type="war" id="testpage" name="testpage" location="${server.config.dir}/apps/testpage.war"> <application-bnd> <security-role name="All Role"> <special-subject type="ALL_AUTHENTICATED_USERS" /> </security-role> </application-bnd> </application>
验证OIDC Web SSO方案
- 启动OIDC提供程序:<liberty_root> / bin / server start oidcOP
- 启动OIDC RP:<liberty_root> / bin / server启动oidcRP
- 将网络浏览器指向:https://rp.example.com:443/testpage/
- 按照说明进行操作。 最后,您应该看到:
图5
样本RP server.xml
<server>
<featureManager>
<feature>ssl-1.0</feature>
<feature>jsp-2.2</feature>
<feature>servlet-3.0</feature>
<feature>appSecurity-2.0</feature>
<feature>openidConnectClient-1.0</feature>
</featureManager>
<openidConnectClient id="RP"
scope="openid profile email photo"
clientId="rp"
clientSecret="secret"
authorizationEndpointUrl="https://op.example.com:443/oidc/endpoint/OP/authorize"
tokenEndpointUrl="https://op.example.com:443/oidc/endpoint/OP/token" >
</openidConnectClient>
<keyStore id="defaultKeyStore" password="keyspass" />
<httpEndpoint host="rp.example.com" httpPort="80" httpsPort="443"
id="defaultHttpEndpoint"/>
<application type="war" id="testpage" name="testpage"
location="${server.config.dir}/apps/testpage.war">
<application-bnd>
<security-role name="All Role">
<special-subject type="ALL_AUTHENTICATED_USERS" />
</security-role>
</application-bnd>
</application>
</server>
示例OP server.xml
<server>
<featureManager>
<feature>openidConnectServer-1.0</feature>
<feature>ssl-1.0</feature>
<feature>appSecurity-2.0</feature>
<feature>servlet-3.0</feature>
</featureManager>
<basicRegistry id="basic" realm="OpBasicRealm">
<user name="testuser" password="testuserpwd" />
<user name="user1" password="security" />
<user name="user2" password="security" />
</basicRegistry>
<keyStore id="defaultKeyStore" password="keyspass" />
<httpEndpoint host="op.example.com" httpPort="80" httpsPort="443" id="defaultHttpEndpoint"/>
<oauth-roles>
<authenticated>
<special-subject type="ALL_AUTHENTICATED_USERS" />
</authenticated>
</oauth-roles>
<openidConnectProvider id="OP" oauthProviderRef="Oauth" >
</openidConnectProvider>
<oauthProvider id="Oauth" >
<localStore>
<client name="rp" secret="{xor}LDo8LTor"
displayname="rp"
redirect="https://rp.example.com:443/oidcclient/redirect/RP"
scope="openid profile scope1 email phone address"
enabled="true"/>
</localStore>
</oauthProvider>
</server>
翻译自: https://www.ibm.com/developerworks/websphere/library/techarticles/1502_odonnell/1502_odonnell.html