# EAS Portal Login Bridge �� login_withForm.js Reference
Reference for `kdshrsso` skill. Describes how `eassso/login` interacts with SHR SSO (Option A or B).
## Context
EAS portal CAS flow sends unauthenticated users to:
```
/eassso/login?service=https://{shr-host}/shr/{path}?...
```
Loaded by `login_withForm.jsp`:
```jsp
```
Default behavior: show username/password form. Customizations intercept before `initLoginFormPattern()` runs.
---
## Pattern 1 �� Option B servlet bridge (YHPro)
**Goal:** Hide eassso login for SHR; redirect to `OAToSHR` with target URL in `service` or `redirect`.
```
eassso/login?service=SHR_TODO_URL
�� login_withForm.js IIFE (top of file)
�� /shr/api/oAToSHR?service=encodeURIComponent(SHR_TODO_URL)
�� OAToSHR puts target into OAuth state
�� IDM �� index2sso.jsp �� SHR_TODO_URL
```
### YHPro logic (simplified)
```javascript
var ENV_CONFIG = {
keepLoginPath: "/shr/home.do", // whitelist: show native login
shrRootPath: "/shr/",
test: { oaSsoUrl: "https://shr-test.example.com/shr/api/oAToSHR" }
};
var serviceParam = getUrlParam("service");
var originalPath = getOriginalPathFromService(serviceParam);
var isKeepLogin = originalPath === ENV_CONFIG.keepLoginPath
|| (serviceParam && serviceParam.includes(ENV_CONFIG.keepLoginPath));
var needRedirect = !isKeepLogin
&& (originalPath.includes("/shr/") || originalPath === ""
|| location.pathname.includes("/eassso/login"));
if (needRedirect) {
var callbackUrl = serviceParam || (shrBaseUrl + "/shr/");
location.replace(oaSsoUrl + "?service=" + encodeURIComponent(callbackUrl));
}
```
### Parameter choice
| Param to OAToSHR | OAToSHR reads | Recommendation |
|------------------|---------------|----------------|
| `redirect` | 1st priority | Preferred for portal direct links |
| `service` | 2nd priority | Used by eassso CAS bridge |
`state` in OAuth is **dynamic**: encoded value of redirect/service URL.
### UX additions (YHPro)
- Full-screen mask `#sso-jump-mask` before redirect (avoid login page flash)
- `window.onbeforeunload = null` �� prevent EAS blocking redirect
- `location.replace()` �� no back-button to login page
- 3s mask timeout �� fallback if redirect fails
---
## Pattern 2 �� Option A direct forward
**Goal:** Let SHR CAS filters handle OAuth; no servlet.
```javascript
if (isShrService(serviceParam) && !isKeepLogin) {
window.top.location.replace(serviceParam); // go to SHR URL directly
}
```
Flow:
```
eassso/login?service=https://shr/.../dynamic.do?...
�� JS replace �� SHR URL
�� KDPortalAuthenticationFilter (no assertion) �� IDM
�� /shr?code= �� validation �� target page
```
Portal menus can also link **directly** to SHR URLs, skipping eassso/login entirely.
---
## Pattern 3 �� Option A adsso button (GYPro / Azure)
`login_withForm.jsp` adds Office 365 button:
```javascript
onclick="window.location.href='https://{host}/shr?adsso'"
```
Filter treats `/adsso` as force-OAuth entry; stores original URL in session before IdP redirect.
---
## Whitelist local login
Keep emergency / admin path on native eassso form:
| Path | Typical purpose |
|------|-----------------|
| `/shr/home.do` | Local DB login bypass (YHPro) |
| Product default | Specific JSP paths in Filter `flag` (Option A) |
Implement whitelist by **exact pathname match**, not loose `includes()`.
---
## Recommended implementation (either pattern)
### Do
1. Put custom logic in **separate** `login_sso_redirect.js`; include it in JSP **before** `login_withForm.js`
2. Inject config from server:
```jsp
```
3. Keep source under project `src/` or overlay build �� not only `runtime/server/deploy/...`
4. Use one config file shared with Java (`OASSOConfig` / `adSsoConfig`)
### Do not
| Anti-pattern | Risk |
|--------------|------|
| Hardcode dev/test/prod URLs in JS | Prod misconfig; triple maintenance with Java |
| Edit 1500-line platform file in runtime war only | Lost on redeploy / upgrade |
| `needRedirect` when `service` is empty | Bare `/eassso/login` forced to SHR SSO |
| `serviceParam.includes(keepLoginPath)` | Loose match bypass |
| Prod placeholder URL (`��������OA�����¼��ַ`) | Production outage |
| Duplicate logout URLs in JS + Java + servlet | Inconsistent federated logout |
---
## logoutHR.js (Option B companion)
SHR logout extended for IDM federated logout:
```
logoutHR()
�� /eassso/logout + shr_loginout + easweb/logout (platform chain)
�� clear cookies / storage
�� redirect to idmLogoutUrl (or portal home)
```
IDM logout URL built per spec:
```
{idmBaseUrl}/token/code-logout?redirect_url={encodeURIComponent(authorizeUrlWithParams)}
```
**Prefer:** call `/shr/api/SHRToIDMLogout` servlet (server builds URL from properties) instead of rebuilding URL in JS.
YHPro `logoutHR.js` currently duplicates IDM URL logic in frontend �� refactor to servlet JSON response.
---
## File locations (typical)
| File | War | Role |
|------|-----|------|
| `common/js/login_withForm.js` | `sso_web.war` (eas.ear) | Portal login page logic |
| `login_withForm.jsp` | `sso_web.war` | Loads JS |
| `scripts/gui/logoutHR.js` | `shr_web.war` | SHR logout |
| `sso/ssoParamemter.properties` | `shr_web.war` | CAS UrlPattern exclusions |
---
## Test checklist
```
- [ ] Portal menu �� SHR todo: lands on todo after IDM login
- [ ] /shr/home.do (whitelist): shows eassso login form
- [ ] Direct /shr URL without session: OAuth (A) or needs portal link (B)
- [ ] Logout: SHR session cleared + IDM session cleared
- [ ] Upgrade sso_web.war: custom JS preserved via overlay
```