Enterprise Authentication Integration
ID Cards and Key Cards — The Authentication Landscape
Summary
Authentication in SI is hard not because authentication is hard but because an authentication system already exists, and our system has to insert itself in between.
Why authentication is hard in SI
When you build one new system, authentication is not hard. You put the ID/password in a DB and you are done. In SI it is hard because an authentication system already exists.
The client company usually already has things like these.
- An HR system (the source of truth for people. Hiring, leaving, and department transfers start here)
- Active Directory or LDAP (PC login, file servers, mail)
- A groupware / portal (the real gateway of the company SSO)
- An old WebSSO product (something like SiteMinder. Running for 15 years)
- And a recently added Keycloak or cloud IdP
The system you build has to fit in between these. So a one-line requirement, "please add login," becomes two months of work.
Do not confuse these four
| Name | What it is | One-line analogy |
|---|---|---|
| LDAP | A directory protocol holding user and organization information | A phone book |
| SAML 2.0 | An XML-based authentication federation (SSO) protocol | A paper ID card |
| OIDC | An authentication federation protocol built on top of OAuth 2.0 | A digital ID card |
| OAuth 2.0 | An authorization (delegation of permissions) framework | A hotel key card |
The most important distinction is the last two.
OIDC / SAML is issuing an ID, and OAuth 2.0 is a hotel key card. A key card only says "this card can open room 305 and the gym door"; it does not say who the holder is.
This gives rise to a famous anti-pattern: judging login by an access token.
An access token has no, or only a loose, basis for verifying "who it was issued to" (aud).
A token substitution attack is possible where a token issued for another app passes when you paste it in.
Login decisions must be made with the ID token.
Is LDAP an authentication protocol
Only half right. LDAP is a directory lookup protocol, and it can verify a password with the bind operation.
That is why the phrase "LDAP authentication" holds. But that is
a method where the application receives the password itself and asks LDAP.
In other words, it is not SSO. Every app has its own login screen.
In practice you combine them like this.
[사용자] --로그인--> [IdP(Keycloak 등)] --bind/조회--> [AD / LDAP]
| |
|<---- ID 토큰 --------|
v
[우리 시스템] ← 토큰만 검증. 비밀번호를 절대 보지 않는다
Our system not seeing the password is the key benefit. If you do not see the password, you do not become a party to a leak incident.
Legacy header authentication — the reality of large Korean enterprise and financial intranets
A 15-year-old WebSSO product (of the SiteMinder family) works like this. An agent is installed on the web server, and when authentication finishes it stuffs user information into HTTP headers and passes the request to the backend application.
SM_USER: jdoe
SM_USERDN: uid=jdoe,ou=people,dc=example,dc=com
SM_USERGROUPS: hr-staff^payroll-admin
The backend Java app reads request.getHeader("SM_USER") in a filter and processes the login.
It is simple, it needs almost no app changes, and that is why hundreds of apps are attached this way.
The problem is clear. The app trusting the header unconditionally means that if there is even one path that reaches the app directly, bypassing the agent, it is immediately an authentication bypass.
curl -H "SM_USER: ceo" -H "SM_USERGROUPS: payroll-admin" \
http://hr-app.internal:8080/hr/payroll/list
Systems where this one line works really exist. So three controls are needed.
- Network isolation — the app port is unreachable except from the gateway
- Strip the header at the edge — unconditionally delete any
SM_*header that arrives from outside and fill it in fresh - Mutual authentication between gateway and app — mTLS or a shared secret
And this is not an old story. Modern reverse-proxy authentication (oauth2-proxy and others) has exactly the same structure. The same requirement attaches to every configuration that passes identity in headers.
As an appendix, the header approach has parsing pitfalls too.
The delimiter of SM_USERGROUPS is a caret (^). Code that parses it assuming commas
sees it as a single group, and the permissions vanish entirely. When you build a migration inventory,
you must survey not just the header names but the format of the values.
What to use when
| Situation | Choice |
|---|---|
| A new web/mobile app where we can control the IdP | OIDC (Authorization Code + PKCE) |
| The counterpart is a large enterprise/public institution that already has a SAML IdP | SAML 2.0 |
| You only need to look up in-house account information and decide groups | LDAP lookup (authentication delegated to the IdP) |
| Server-to-server communication (batch, integration) | OAuth 2.0 client_credentials |
| 100 fifteen-year-old apps that cannot be fixed right now | Proxy-based header injection + the three controls above |
The last row is the reality of SI. The ideal answer is always OIDC, but you need an answer that actually works in a situation where you cannot fix the apps. In that case you use a configuration where a proxy handles the SSO on their behalf and passes it to the app in headers. However, you must always apply the three controls above along with it.
Finally, do not forget batch jobs and service accounts
There is an incident that repeatedly blows up in SSO migration projects. Authentication failures that occur only at month-end/quarter-end.
The cause is usually this: a nightly batch or integration program was passing authentication by imitating a person on the login screen. If you take only human accounts as migration targets, you miss this. And since it is a batch that runs only at month-end, it blows up after 3 weeks of no problems following the switch.
There is a question that must go into the inventory survey.
"Is there anything that is not a person that passes through this authentication?"
If the answer is "no," nine times out of ten it means you have not found it yet.
What it looks like in the field
The process by which a one-line requirement "please add login" becomes two months of work usually goes like this.
First, where to attach it has not been decided. The HR system is the source of people but login is handled by AD, the real gateway is the groupware, and there is also a separate recently added IdP. Each owner answers differently what "our company account" refers to.
Next you meet legacy header authentication. It is a method where the front-end WebSSO product carries the user ID in an HTTP header, and it has been running for 15 years so it cannot be changed. There is one thing you must check here — whether that header can be put in directly from outside. If the proxy does not overwrite the header, anyone can come in with someone else's ID.
Finally, batch jobs and service accounts get missed. You design only for human accounts and launch, and only then decide under what credentials the nightly batch will connect.