IdP认证对接及属性定义(OAuth2)(ova第3/6步,手动第3/9步)

        本文档介绍了采用CARSI IdP标准安装包对接OAuth2认证和属性定义的配置步骤,适用于本地采用oauth2认证的情况。下一步:配置eduPersonTargetedID属性定义

关于详细的OAuth2对接细节,可同时参考:Shibboleth-IdP 的 OAuth2 对接方案详解(感谢华东师范大学冯骐老师提供)

OAuth2认证需要采用标准的授权码(Authorization Code)方式,简单过程如下:

(1)IdP跳转到OAuth2认证页面,用GET方式传递response_type、client_id、state、redirect_uri四个参数;

(2)认证通过后,OAuth2回调到redirect_uri上并带上code参数;

(3)IdP获取code,向OAuth2获取token,用POST方式传递,grant_type=authorization_code、code、client_id、client_secret、redirect_uri;

(4)OAuth2验证后,返回token;

(5)IdP获取token后,向OAuth2请求资源,用POST方式传递token;

(6)OAuth2返回IdP相应的资源。

        需要OAuth2管理员提供:

              OAuth2认证页面URL、OAuth2用code获取token的URL、OAuth2用token获取资源的URL、IdP认证在OAuth2上的client_id、client_secret

        向OAuth2管理员提供:

              redirect_uri=https://xxx.xxx.edu.cn/idp/Authn/ExtOauth2?conversation=e1s1


具体配置:

(1)新建文件夹并拷贝相关文件:

[root@www ~]# mkdir /opt/shibboleth-idp/flows/authn/Shiboauth2

        把 3.2.4-oauth-bundle.zip 中shibcas-authn-beans.xml、shibcas-authn-flow.xml放入文件夹中。

        把附件中的no-conversation-state.jsp放入/opt/shibboleth-idp/edit-webapp中。

        把附件中的shib-cas-authenticator-3.2.4-oauth.jar 、cas-client-core-3.4.1.jar放入/opt/shibboleth-idp/edit-webapp/WEB-INF/lib中。

(2)配置web.xml:

[root@www ~]# cp /opt/shibboleth-idp/dist/webapp/WEB-INF/web.xml /opt/shibboleth-idp/edit-webapp/WEB-INF/web.xml
[root@www ~]# vi /opt/shibboleth-idp/edit-webapp/WEB-INF/web.xml
#在<!-- Servlets and servlet mappings -->后加上

<!-- Servlet for receiving a callback from an external CAS Server and continues the IdP login flow -->
     <servlet>
         <servlet-name> ShibOauth2 Auth Servlet</servlet-name>
         <servlet-class>net.unicon.idp.externalauth.ShibcasAuthServlet</servlet-class>
         <load-on-startup>2</load-on-startup>
     </servlet>
     <servlet-mapping>
         <servlet-name> ShibOauth2 Auth Servlet</servlet-name>
         <url-pattern>/Authn/ExtOauth2/*</url-pattern>
     </servlet-mapping>

(3)配置idp.properties:

注意 shibcas.oauth2principalname  必须配置为 oauth 释放的属性中,表示为用户名的那个字段(即用于映射 princleName 的那个)

[root@www ~]# vi /opt/shibboleth-idp/conf/idp.properties
#修改
idp.authn.flows = Shiboauth2

#新增
shibcas.oauth2UrlPrefix = http://xxx.xxx.xxx.xxx
#OAuth2服务器域名
shibcas.oauth2LoginUrl = ${shibcas.oauth2UrlPrefix}/xxx?response_type=code&client_id=xxx&state=xyz
#OAuth2认证页面以及需要传递的参数,state可以配置成任意字符串
shibcas.serverName = https://xxx.xxx.xxx.xxx
#IdP的域名
shibcas.oauth2TokenUrl = http://xxx.xxx.xxx.xxx/xxx
# OAuth2用code获取token的URL
shibcas.oauth2ResourceUrl = http://xxx.xxx.xxx.xxx/xxx
# OAuth2用token获取资源的URL
shibcas.oauth2clientid = testclient
shibcas.oauth2clientsecret = testpass
shibcas.oauth2redirecturi = https://xxx.xxx.xxx/idp/Authn/ExtOauth2?conversation=e1s1

# 新增

shibcas.oauth2redirecturiBase = https://xxx.xxx.xxx.xxx/idp/Authn/ExtOauth2
shibcas.oauth2principalname =  uid
# oauth 释放属性中,作为用户名输入的那个字段。这个字段必须存在,不然会报错

(4)配置general-authn.xml:

[root@www ~]# vi /opt/shibboleth-idp/conf/authn/general-authn.xml
#在<util:list id="shibboleth.AvailableAuthenticationFlows">后新增

<bean id="authn/Shiboauth2" parent="shibboleth.AuthenticationFlow"
                 p:passiveAuthenticationSupported="true"
                 p:forcedAuthenticationSupported="true"
                 p:nonBrowserSupported="false" />

(5)配置属性释放,用以下内容替换/opt/shibboleth-idp/conf/attribute-resolver.xml文件:

xsi:type="SubjectDerivedAttribute" 的 AttributeDefinition 标识从插件中获取属性的配置

例如下面的示例表示,从 OAuth 中获取的 role 属性,映射为 shibboleth 中的 eduPersonScopedAffiliation,从 OAuth 中获取的 uid 属性,映射为 shibboleth 中的 eduPersonPrincipalName

<?xml version="1.0" encoding="UTF-8"?>
<AttributeResolver
         xmlns="urn:mace:shibboleth:2.0:resolver"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">

  <AttributeDefinition xsi:type="ScriptedAttribute" id="eduPersonScopedAffiliation">
        <InputAttributeDefinition ref="usertype" />
        <Script><![CDATA[
        var localpart = "";
	    if(typeof(usertype)=="undefined"){
        	localpart = "member";
    	}else{
        	if(usertype.getValues().get(0)=="staf") localpart = "staff";
        	else if(usertype.getValues().get(0)=="std") localpart = "student";
        	else localpart = "member";
    	}
        if(usertype.getValues().get(0)=="staf") localpart = "staff";
        else if(usertype.getValues().get(0)=="std") localpart = "student";
        else localpart = "member";
        eduPersonScopedAffiliation.addValue(localpart + "@%{idp.scope}");
            ]]></Script>
        <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonScopedAffiliation" encodeType="false" />
        <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" friendlyName="eduPersonScopedAffiliation" encodeType="false" />
    </AttributeDefinition>

    <AttributeDefinition xsi:type="SubjectDerivedAttribute" id="usertype" principalAttributeName="role"></AttributeDefinition>

     <AttributeDefinition id="eduPersonPrincipalName" xsi:type="Scoped" scope="%{idp.scope}">
         <InputAttributeDefinition ref="PrincipalName" />
         <AttributeEncoder xsi:type="SAML1ScopedString" name="urn:mace:dir:attribute-def:eduPersonPrincipalName" encodeType="false" />
         <AttributeEncoder xsi:type="SAML2ScopedString" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" friendlyName="eduPersonPrincipalName" encodeType="false" />
     </AttributeDefinition>

 <AttributeDefinition xsi:type="SubjectDerivedAttribute" id="PrincipalName" principalAttributeName="uid"></AttributeDefinition>

<AttributeDefinition id="eduPersonEntitlement" xsi:type="Simple">
    <InputDataConnector ref="staticAttributes" attributeNames="eduPersonEntitlement" />
    <AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:eduPersonEntitlement" encodeType="false"/>
    <AttributeEncoder xsi:type="SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" friendlyName="eduPersonEntitlement" encodeType="false"/>
</AttributeDefinition>

<DataConnector id="staticAttributes" xsi:type="Static">
    <Attribute id="eduPersonEntitlement">
        <Value>urn:mace:dir:entitlement:common-lib-terms</Value>
    </Attribute>
</DataConnector>

</AttributeResolver>

(6)重新编译war文件,并且重启tomcat:

[root@www ~]# cd /opt/shibboleth-idp/bin
[root@www ~]# ./build.sh

Installation Directory: [/opt/shibboleth-idp] #enter

Rebuilding /opt/shibboleth-idp/war/idp.war ...

...done

BUILD SUCCESSFUL

Total time: 3 seconds

[root@www ~]# systemctl restart tomcat

OAuth 服务端备注:

OAuth 服务端需要提供一个资源属性接口,支持 POST 方式请求。为了便于标准化属性的获取,接口应该避免层级嵌套。(参考 https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)。并讲表示用户名的字段,填入配置文件的 shibcas.oauth2principalname 中

例如如下的返回中,如果用户名是 666666,那么 shibcas.oauth2principalname = uid 

# curl -X POST -d "access_token=e4d051380887c2ead8a5faa4fc2cee75" https://oauth.xxx.edu.cn/userinfo

{
	"cn": "我是名字",
	"eduPersonAffiliation": "student",
	"uid": "666666"
}

        下一步:配置eduPersonTargetedID属性定义


版权所有©北京大学计算中心