idm-servlet-reference.md 7.4 KB

IDM Portal SSO �� Servlet + LtpaToken Reference (YHPro)

Reference for kdshrsso skill Option B. Adapt paths, IdP URLs, and user-mapping field per project.

Related: portal-login-reference.md, migration-guide.md

Source layout (YHPro)

src/com/kingdee/eas/custom/sso/
������ OAToSHR.java              # SHR portal SSO entry servlet
������ SHRToIDMLogout.java       # Federated logout (returns idmLogoutUrl JSON)
������ OAToMBos.java             # Mobile MBOS SSO (separate config)
������ SsoUtil.java              # Config, HTTP, user lookup, bill validation
������ utils/ExpiringMapCache.java
������ filter/authentication/PortalAuthenticationFilter.java   # WIP �� not in web.xml
������ filter/validate/TicketValidationFilter.java             # WIP �� not in web.xml
������ validation/PortalServiceTicketValidator.java            # WIP validator

src/org/jasig/cas/client/Protocol.java   # Protocol.YH("code","redirect_uri")

runtime/server/properties/yuhu/OASSOConfig.properties
runtime/server/deploy/easweb.ear/shr_web.war/WEB-INF/web.xml
runtime/server/deploy/easweb.ear/shr_web.war/WEB-INF/sso/ssoParamemter.properties
runtime/server/deploy/eas.ear/sso_web.war/common/js/login_withForm.js   # portal bridge
runtime/server/deploy/easweb.ear/shr_web.war/scripts/gui/logoutHR.js    # SHR logout

web.xml (SHR servlets)

<!-- SSO ��ʼ -->
<servlet>
    <servlet-name>OAToSHR</servlet-name>
    <servlet-class>com.kingdee.eas.custom.sso.OAToSHR</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>OAToSHR</servlet-name>
    <url-pattern>/api/oAToSHR</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>SHRToIDMLogout</servlet-name>
    <servlet-class>com.kingdee.eas.custom.sso.SHRToIDMLogout</servlet-class>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>SHRToIDMLogout</servlet-name>
    <url-pattern>/api/SHRToIDMLogout</url-pattern>
</servlet-mapping>

CAS filters unchanged (casAuthenticationFilter / casTicketValidationFilter). Exclude in ssoParamemter.properties:

cas.client.UrlPattern=...;/index2sso.jsp;...;/api/oAToSHR;/api/SHRToIDMLogout;/api/oatombos;

Full call chain (with portal)

Portal CAS
  �� eassso/login?service=https://shr.../shr/dynamic.do?...&AssignmentId=...
  �� login_withForm.js intercept
  �� /shr/api/oAToSHR?service=encodeURIComponent(service)
       (portal may also use ?redirect= for direct links)

OAToSHR.doPost()
  ������ no code �� authorize()
  ��     dynamicRedirect = redirect | service | default homepage
  ��     state = URLEncoder.encode(dynamicRedirect)   �� dynamic, not fixed
  ��     302 �� IDM authorizePath?response_type=code&scope=server&client_id&state&redirect_uri=ssoUrl
  ������ code �� callBack()
        decode state �� redirectUrl
        GET getAccessTokenPath?code&client_id&client_secret&redirect_uri
        user_info.id �� checkUserExist(cfidmusercode) �� T_PM_USER.FNumber
        302 �� /shr/index2sso.jsp?username&password(Ltpa)&redirectTo

index2sso.jsp �� SHR session �� redirectUrl (todo / homepage)

Dynamic redirect (state)

Stage Behavior
Input redirect (1st) or service (2nd) on OAToSHR request
Authorize state = URLEncoder.encode(targetUrl) �� changes every request
Callback URLDecoder.decode(state) �� final redirectTo
Default {serverName}/shr/dynamic.do?uipk=shr.perself.homepage

Logout chain

logoutHR.js
  �� platform logout AJAX chain (/eassso/logout, shr_loginout, easweb/logout, ...)
  �� clear cookies / storage
  �� redirect to idmLogoutUrl (built in JS or from servlet �� prefer servlet)

SHRToIDMLogout (POST /shr/api/SHRToIDMLogout)
  �� build IDM authorize URL with state = portal home
  �� idmLogoutUrl = {idmBaseUrl}/token/code-logout?redirect_url={encoded authorize URL}
  �� session.invalidate()
  �� JSON { code:"1", idmLogoutUrl:"..." }

Improvement: have logoutHR.js call SHRToIDMLogout instead of duplicating IDM URL in JS.


Config template

Path: {EAS_HOME}/server/properties/yuhu/OASSOConfig.properties

authorizePath=https://idm-test.example.com/oauth2/authorize
getAccessTokenPath=https://idm-test.example.com/token/codeInfo
client_id=shr
client_secret=
response_type=code
ssoUrl=https://shr-test.example.com/shr/api/oAToSHR
serverName=https://shr-test.example.com
idmBaseUrl=https://idm-test.example.com
lastRedirectUrl=/shr/home.do

Production pitfall: sample file had redirect_uri1/2 for MBOS but OAToSHR requires ssoUrl (strict). Missing ssoUrl causes init/runtime errors.


User mapping SQL

SELECT uinfo.FNumber AS userNum
FROM T_bd_person person
LEFT JOIN T_PM_USER uinfo ON person.fid = uinfo.FPERSONID
WHERE uinfo.FIsDelete = '0'
  AND uinfo.FForbidden = '0'
  AND person.cfidmusercode = ?

IDM field: data.user_info.id from token response.


IDM token API

GET {getAccessTokenPath}?code=&client_id=&client_secret=&redirect_uri=

{ "code": "0", "data": { "access_token": "...", "user_info": { "id": "...", "username": "..." } } }

Portal login_withForm.js (YHPro bridge)

See portal-login-reference.md for full analysis.

Summary:

  • IIFE at top of login_withForm.js runs before login form renders
  • Whitelist /shr/home.do for native eassso login
  • Other SHR paths �� oaSsoUrl + "?service=" + encodeURIComponent(serviceParam)
  • Anti-patterns found: hardcoded ENV_CONFIG, runtime-only edit, prod URL placeholder, loose whitelist includes()

OAToMBos (mobile, separate)

Uses ExpiringMapCache �� state carries cache key not full URL:

state = ssoUrl + "?redirect=" + cacheKey

Do not confuse with OAToSHR direct URL-in-state pattern.


Deploy checklist

- [ ] Compile src/com/kingdee/eas/custom/sso/**
- [ ] Deploy to shr_web.war/WEB-INF/classes
- [ ] web.xml servlets + ssoParamemter.properties UrlPattern
- [ ] OASSOConfig.properties on server (include ssoUrl, idmBaseUrl)
- [ ] IDM redirect_uri = ssoUrl
- [ ] person.cfidmusercode for all SSO users
- [ ] login_withForm.js overlay in sso_web.war (src tracked, not runtime-only)
- [ ] logoutHR.js calls SHRToIDMLogout or shares config
- [ ] Test: portal todo, home.do whitelist, logout

Troubleshooting

Symptom Check
500 on servlet init OASSOConfig missing; ssoUrl empty
authorize fails authorizePath, client_id, IDM app registration
Token exchange fails GET API; redirect_uri must match authorize
User not found cfidmusercode vs user_info.id; duplicate rows
Login page flash mask + replace(); onbeforeunload cleared
index2sso loop UrlPattern excludes servlet + index2sso.jsp
Deep link wrong state decode; redirect vs service param
Logout 401 IDM idmLogoutUrl spec; redirect_url encoding

WIP filter code (not production)

PortalAuthenticationFilter + TicketValidationFilter + PortalServiceTicketValidator:

  • Mirror Option A structure but not wired in web.xml
  • Hardcoded test URLs; POST token vs GET in OAToSHR
  • Use only as reference for idm-filter-reference.md migration

Production login path: OAToSHR servlet only.