TeamcenterKnowledge

Skills

Polarion Authentication

Skill polarion-authentication. Configure Polarion 2606 authentication - the authentication.xml contract, SSO via Teamcenter Security Services (tcss) or OIDC (oauth2), and the traps that make a wrong config look right. Covers the built-in editor being the only supported edit surface, the schema-vs-runtime contradiction that makes password and tcss mutually exclusive, the JVM truststore Polarion needs before it can call TcSS at all, and the TcSS Application Registry check that fires on the return leg only so a clean outbound redirect proves nothing. Use for any Polarion SSO, LDAP, OIDC or "my authentication config will not save" work.

Provenance is marked throughout. EXERCISED came back from a real call or a real save on this estate (Polarion 2606 at D:\Polarion on MARTINI-GAMING, TcSS on TC2606/siemensdc, Keycloak 24 realm xcelerator, 2026-08-19). DERIVED was read out of the shipped 2606 documentation and has not been run. Do not promote a DERIVED line without running it.

Related: tc-sso-keycloak (the Teamcenter half, and the three-truststore problem this extends).

0. The one-paragraph version

All Polarion authentication lives in one file, authentication.xml, and you edit it through Global Administration > User Management > Authentication, not on disk. Polarion serves its own authoritative XSD and the editor genuinely enforces it. Adopting Teamcenter SSO means the <tcss> authenticator, which cannot coexist with local password login, needs a CA in Polarion's own JVM truststore, and needs Polarion registered in TcSS's Application Registry on the Teamcenter side.

1. Where the config lives, and why not to touch the file

EXERCISED. The supported surface is the built-in editor:

Global Administration (or Administration in the Default Repository) then User Management > Authentication > Create XML configuration

Buttons: Default Template (known-good starter), Import from File, Cancel.

Siemens' own guidance, quoted: "We recommend that you only update the authentication.xml file via the built-in editor. (Do not edit the authentication.xml file directly with an external editor.)" and a Warning that a direct file edit means you "will have to reindex the coordinator."

The editor validates on save and applies immediately across all nodes with no service restart. A direct file edit needs a restart. So the editor is both safer and faster.

  • com.siemens.polarion.security.auth.file in polarion.properties relocates the file. DERIVED.
  • Cluster/multi-instance default lives on the Coordinator under $POLARION_DATA/workspace/cluster-data; com.siemens.polarion.security.auth.cluster.folder overrides. DERIVED.
  • authentication.xmlReload.enabled=true plus a GET on <server>/polarion/authentication-reload refreshes an on-disk edit without a restart. DERIVED. Note it cannot create or remove the initial file, and setting the property needs a working login, so it is not a lockout recovery.

WARNING. Do not go hunting for authentication.xml on disk to find out whether one exists. A recursive filename search on this install returned eight hits, all 122 bytes, all ...\plugins\...\templates\<tpl>\.polarion\tracker\categories\authentication.xml, which are work-item category definitions named "Authentication" and have nothing to do with SSO. The real SSO file did not exist at all. Exclude \plugins\ and \templates\ before drawing any conclusion.

2. The schema is authoritative, published, and enforced

EXERCISED, and this is the highest-value item here. Polarion serves its own XSD:

http://<polarion-host>/polarion/authentication.xsd
(about 22 KB, namespace http://polarion.com/PolarionAuthentication)

Validating locally against that file predicted the editor's verdict exactly, on both a pass and a fail. So you can author and check offline with lxml and be confident before pasting.

WARNING. /polarion/<anything> returns HTTP 200 on this server, including nonsense paths. A bogus .xsd path returned 200 as readily as the real one. Status code is not evidence here; check the content. This is the classic "limit that behaves like success" shape.

Root element and child order (xs:sequence, so order matters):

<authentication>
    password?      (0..1)
    ldap*          (0..n)
    saml*          (0..n)
    oauth2*        (0..n)
    tcss?          (0..1)
    basic?         (0..1)
    jwt*           (0..n)
</authentication>

Which types carry id and default is NOT uniform, and the prose misleads. The docs say "id: Required, String. Must be unique across whole XML" in the general authenticator section. That applies only to the types that declare it:

Type id default other attributes
oauth2 required optional forceLdapEsignatures, usage
ldap required none allowWebServices, syncUserGroups, usage
saml required optional
password none optional usage
tcss none none forceLdapEsignatures, usage
basic none none allowOslc, usage

The base authenticator type is literally empty (<xs:complexType name="authenticator"/>), so nothing is inherited. Writing <tcss id="..." default="true"> from the general prose fails.

3. password and tcss cannot coexist. There is no valid configuration.

EXERCISED, proven in both directions against the live editor. This is a planning constraint, not a detail, because it means adopting Teamcenter SSO removes local login from Polarion.

<password default="true"/> + <tcss>    ->  XSD passes, RUNTIME rejects:
    "Multiple authenticators must have exactly one default authenticator.
     Please set the "default" attribute to configuration."

<tcss default="true"> + <password/>    ->  RUNTIME rejects on SCHEMA:
    "cvc-complex-type.3.2.2: Attribute 'default' is not allowed to appear in element 'tcss'."

The runtime demands exactly one default among multiple authenticators; the schema forbids default on tcss; and <password default="true"/> does not satisfy the runtime's check. Both constraints cannot be met at once.

So <tcss> alone is the documented and working shape. The migration topic shows exactly that as the complete replacement for the pre-22R1 polarion.properties settings.

And decide the lockout story before you save. On a system whose only account is the default admin, saving a tcss-only config with SSO not yet fully working leaves the current browser session as the sole way in.

Rollback is one click

EXERCISED. The Authentication page's Default Template button regenerates <password default="true" /> with the other providers commented out. Save applies immediately, no restart, local login restored. This is far cheaper than an elevated rename-the-file-and-restart script, and it needs no admin rights on the host. Reach for it first.

4. <tcss>: the element, and finding its real URLs

<tcss>
    <loginUrl>https://TCSS-HOST:PORT/login/sa</loginUrl>
    <serviceUrl>https://TCSS-HOST:PORT/identity</serviceUrl>
    <!-- optional -->
    <paramAppUserId>APP_USER_ID</paramAppUserId>
    <paramSessionKey>SESSION_KEY</paramSessionKey>
    <autocreate><enabled>true</enabled></autocreate>
</tcss>

autocreate is type createAccount: required <enabled>, optional <globalRoles><role>...</role></globalRoles>. Still untested here - the federated user already existed, so it never had an account to create. Do not describe it as working.

★★★ The documented defaults for the parameter names are WRONG, and the symptom misleads

EXERCISED, and this was the single hardest thing in the whole exercise. The docs give paramAppUserId a default of APP_USER_ID and paramSessionKey a default of SESSION_KEY. This TcSS posts neither. Captured from the real return POST body:

TCSSO_APP_USER_ID        = ed
TCSSO_SESSION_KEY        = eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...   (a JWT)
IS_TCSSO_APP_TOKEN       = true
TCSSO_LOCALE             = en_us
tcsso.behind_sso_gateway = false
TCSSONOAPPLETS           = true
iss                      = https://<idp>/realms/<realm>
x-siemens-session-id / x-correlation-id

So set them explicitly:

<paramAppUserId>TCSSO_APP_USER_ID</paramAppUserId>
<paramSessionKey>TCSSO_SESSION_KEY</paramSessionKey>

The symptom points at the wrong thing. Leaving the defaults produces [AUTH-0002] ... Reason: The supplied token is invalid, which reads as a broken or expired token and sends you into TcSS, Keycloak, certificates and clocks. It is none of those. The tell is that Polarion rejects in ~40 ms and TcSS logs NO validateAppToken at all - Polarion never contacts the identity service, because it never found a session key to validate. When TcSS's log is silent for an attempt, the failure is client-side parameter extraction, not the token.

Get the names by capturing the POST, not by reading the docs. DevTools > Network > the POST to /polarion/ > Payload. Every hypothesis formed before that capture (log4j config, origin mismatch, SameSite on a cross-site POST, clock skew, certificate trust) was wrong, and each cost a config change and a restart to disprove.

Probe for the real service names rather than trusting a written-down value. On this estate the SsoSetup blueprint recorded the Login Service as https://siemensdc:8093/Teamcenter1/..., which 404s. The live paths are:

/login/sa      -> 302     <- loginUrl
/identity      -> 301     <- serviceUrl
/Teamcenter1   -> 404     <- the stale blueprint value

That is tc-sso-keycloak section 11's trap: the Deployment Center web-app name and the Login Service name look interchangeable and are not. One curl per candidate settles it.

5. Polarion's JVM needs the TcSS CA, and it is not the CA you expect

EXERCISED. <tcss> makes Polarion call TcSS over HTTPS from its own JVM, which is a fourth truststore beyond the three in tc-sso-keycloak section 3. A fresh Temurin JDK trusts neither the corporate CA nor Teamcenter's.

On this estate TcSS is signed by Deployment Center's internal PKI, not the shared CA.

siemensdc:8093 chain:  CN=SIEMENSDC
                    <- CN=Siemens Deployment Center Vault Intermediate CA
                    <- CN=Siemens Deployment Center Vault root CA
Keycloak's CA file:    CN=Xcelerator Local Root CA          <- a DIFFERENT CA

Importing the Keycloak CA looks obviously right and does nothing. Take the root off the wire:

keytool -printcert -rfc -sslserver TCSS-HOST:PORT > chain.pem      # keep the LAST cert
keytool -importcert -noprompt -trustcacerts -cacerts -storepass changeit -alias NAME -file root.crt

Verify with an A/B control, because a pass alone cannot distinguish "trusted" from "validation disabled". Back up cacerts first, then probe the same URL twice: once against the live store, once against the pre-import backup via -Djavax.net.ssl.trustStore=. The second must fail PKIX path building failed. Pair with a public HTTPS URL to prove the probe itself works. Re-run after any JDK patch: a new JDK ships a fresh cacerts and the alias is gone.

curl --cacert on Windows may fail with CERT_TRUST_REVOCATION_STATUS_UNKNOWN. That is a schannel CRL-check artifact, not a trust failure; --ssl-no-revoke clears it. Do not report it as a certificate problem.

6. The TcSS Application Registry check fires on the RETURN leg only

EXERCISED, and this one is genuinely easy to misreport. Once <tcss> is saved, an unauthenticated hit on /polarion/ returns an auto-submitting form:

POST https://TCSS-HOST:8093/login/sa/weblogin/login_redirect
     TCSSORURI      = /polarion/
     TCSSONOAPPLETS = true
     TCSSOAPPID     = Polarion        <- the app id TcSS must know

POSTing that by hand returns a clean 302 to a well-formed OP authorization request, and the OP will then authenticate a real user and return a real code. None of that proves the application is registered. TcSS only consults its Application Registry when it comes to redirect the browser back, and an unregistered app fails there:

There is a system error. Please contact your system administrator. Web redirection from an unknown application: Polarion.

The fix is on the Teamcenter side, a third Application Registry row beside TCSSOLoginService and the AWC application:

Field Value
Application ID must equal TCSSOAPPID, i.e. Polarion
APPLICATIONROOTURL the host root only, e.g. https://POLARION-HOST:PORT
REDIRECTURL the same host root, not an OAuth callback

Scheme and port are part of the registered root, so moving Polarion to HTTPS breaks SSO until this row moves with it. EXERCISED 2026-08-19: putting Polarion behind TLS on a non-standard port required this value to change from http://martini-gaming to https://martini-gaming:4443. Still host root only, still no trailing slash. Since the registry is consulted on the return leg, the symptom of forgetting is a login that starts fine and fails at the end. Sequence the two changes together, and see polarion-https-and-rest.

TcSS APPENDS TCSSORURI to the registered root, so the root must NOT contain the application path. EXERCISED failure: registering http://HOST/polarion/ while Polarion posts TCSSORURI=/polarion/ produced a post-login redirect to .../polarion/polarion/, a doubled path that 404s. Register http://POLARION-HOST and let TCSSORURI supply /polarion/.

And the root must name the machine that actually serves Polarion, not the TcSS host. The same failure landed on siemensdc/polarion/polarion/ where siemensdc is the Teamcenter VM and serves no Polarion at all (http://siemensdc/polarion/ -> 404). Confirm with a plain curl which host answers 200 for the application root before registering anything.

And per tc-sso-keycloak section 18, the pool manager service must be restarted before any TcSS change is actually live. A retest that skips it can fail for reasons that have nothing to do with the change.

7. Verification bar

In order, because each step passes while the next is broken:

  1. The config saves in the built-in editor. Schema plus semantic rules, both.
  2. /polarion/ returns the auto-POST form carrying the expected TCSSOAPPID.
  3. That POST returns 302 to a well-formed OP authorization request (right client_id, redirect_uri, scope).
  4. The OP renders a login page and authenticates a real user.
  5. The callback lands back in Polarion authenticated. Only this proves SSO. Steps 2 to 4 all passed on this estate while the whole thing was still broken.
  6. The user has a Polarion account. Federated ids must match Polarion user ids, or <autocreate> must be on. A realm carrying dozens of users plus autocreate also has licence-allocation consequences worth thinking about before enabling it.

7b. A valid token is not a successful login: Polarion's catch-all message

EXERCISED. Once the parameter names are right, TcSS logs SSO token validated and the login can still fail, with a different and even less helpful message:

[AUTH-0002] Unsuccessful login attempt for user 'ed' by 'TCSS' mechanism.
Reason: Your Username or Password is incorrect, or there was another problem logging in.

There is no password in an SSO flow, so that text is a catch-all for anything that goes wrong after the token is accepted. Here the cause was the Polarion account itself.

★★ [disabled] on a Polarion user is a DERIVED state, not a settable flag. The user detail page showed Ed Engineer [disabled] in red, and there is no enable checkbox anywhere on the form. Polarion marks an account disabled when it lacks what it needs to be usable; granting the user global role cleared it on save. So "enable the user" is not an action you can take - you fix the underlying gap and the state follows. Do not go hunting for the toggle.

The diagnostic ladder, which localises the failure in one log read each:

Observation Failing layer
TcSS logs no Redirection request from: <app> Polarion is not emitting the handoff; check <tcss> is live
TcSS logs Web redirection from an unknown application app not in the TcSS Application Registry
TcSS logs the redirect but no validateAppToken parameter-name mismatch (section 4)
TcSS logs SSO token validated, Polarion still AUTH-0002 the Polarion account: disabled state, roles, licence
No AUTH-0002 and the user lands in the portal working

Check the user's own detail page early. The answer to the last case was visible as a red tag on that page the entire time, while hours went into TcSS logs, JWT payloads and certificate probes. The moment Polarion names a user in an error, open that user.

Licences are a real ceiling. The account also needed an assigned licence, and the dropdown read Named ALM (0 remaining). Shipped demo personas hold seats. Expect to free one before onboarding a real user, and note that a disabled account may still be holding its seat.

⚠ That reading was taken on the 30-day trial, whose seat count is small. On a real SALT entitlement the ceiling is whatever was issued, and the seats are visible from outside Polarion, which is a much faster check than the UI dropdown:

"C:/Program Files/Siemens/License Server/lmutil.exe" lmstat -a -c 29000@localhost | grep -i "Users of pln_"

OUT: "pln_alm_n" <user>@<HOST> lines in saltd.log name exactly who holds a seat. If licensing itself is the problem rather than the allocation, see polarion-salt-licensing: an unlicensed Polarion starts and serves normally, so a login failure is a plausible first symptom.

Where accounts come from. Do not assume an account that matches your federated id was created by <autocreate>. Compare it against the directory: here the Polarion account carried a curated name, initials, a description and the installer's admin email, while LDAP held only uid/cn/sn = ed and ed@<host>. The mismatch proved it predated SSO entirely - it shipped with the demo projects, alongside personas like Steve Developer and Melanie Test.

7c. Operating this without locking yourself out

Because password and tcss cannot coexist (section 3), every SSO experiment risks losing all access, and a session timeout alone is enough to strand you. Two things make the loop cheap:

  1. The config file's real location is <POLARION_DATA>\authentication\authentication.xml (D:\Polarion\data\authentication\ here), **not** under polarion\configuration\. Find it by recursive search excluding \plugins\ and \templates\, which hold eight same-named work-item category files that are not the auth config.
  2. Removing that file and restarting the Polarion service reverts to built-in login. Writing it back and restarting re-enables SSO. A small elevated script with local / tcss / status modes turns each flip into one command. set-polarion-auth.ps1 in Documents\Siemens\polarion-sso\.

★ Do all account work (roles, licence, provider settings) while on local login, then flip once. Testing one attribute per flip costs a lockout cycle each time.

★ Chrome blocks the return POST with "The information you're about to submit is not secure" on every login, because the form originates on HTTPS (TcSS) and posts to HTTP (Polarion). It is not a failure and the POST completes after "Send anyway", but it makes an HTTP-only Polarion unshippable to real users. Put TLS on Polarion before onboarding anyone.

8. The OIDC alternative, if you do not want the Teamcenter dependency

<oauth2 id="..." default="true"> points Polarion straight at the OP, with <authorizeUrl>, <tokenUrl>, <clientId>, <clientSecret>, optional <userUrl>, plus <mapping>, <scopes>, <groupsSynchronization>, <rolesSynchronization>. DERIVED here, not run on this estate.

Trade-off, worth stating explicitly when someone asks for "Teamcenter SSO":

  • <tcss> gives a shared Teamcenter session, which the Polarion/Teamcenter Direct and Linked Data integrations expect. Cost: Polarion login depends on the Teamcenter tier being up, and on a VM that gets reverted, TcSS config does not survive the revert.
  • <oauth2> makes Polarion a peer client of the same IdP. Both apps then trust one issuer and one user-id namespace, and Polarion keeps working when Teamcenter is down. oauth2 also carries id and default, so it can coexist with <password>, which sidesteps section 3 entirely.

Generated from skills/polarion-authentication/SKILL.md in the tc-automation-skills library, which is the canonical copy and also serves as the agent skill set for Teamcenter work.