ELY06003 - Single sign on with AD Service Account user with Kerberos results in Authentication error

247 views
Skip to first unread message

MalaiSelvan K

unread,
Nov 7, 2023, 9:33:37 AM11/7/23
to WildFly

We are running our Servlet based web application on Openshift infrastructure which is running on Wildfly 26 version. We are implementing SSO using Kerberos

We have created an Active Directory service user for validating the logged in user against AD and provide the authentication.

The name of the service user is adreader and the logged in user is selvan.k. The URL for product isĀ http://web-route-xyz.apps.ocptest.abcd.bbbb/Browser. All necessary configurations are done in wildly standalone xml file.

Service principle for the logged in user

enter image description here

Service principle for the service user

enter image description here

Keytab for service user

enter image description here

When we launch the URL we noticed bellow error. From the log it seems the process if failing at the last stage.

[2023-11-02 05:19:05.445] Entered SpNegoContext.acceptSecContext with state=STATE_NEW [2023-11-02 05:19:05.446] SpNegoContext.acceptSecContext: receiving token = a0 82 08 23 30 82 08 1f a0 30 30 2e 06 09 2a 86 48 82 f7 12 01 02 02 06 09 2a 86 48 86 f7 12 01 02 02 06 0a 2b 06 01 04 01 82 37 02 02 1e 06 0a 2b 06 01 04 01 82 37 02 02 0a a2 82 07 e9 04 82 07 e5 60 82 07 e1 06 09 2a 86 48 86 f7 12 01 02 02 01 00 6e 82 07 d0 30 82 07 cc a0 03 02 01 05 a1 03 02 01 0e a2 07 03 05 00 20 00 00 00 a3 82 05 cb 61 82 05 c7 30 82 05 c3 a0 03 02 01 05 a1 0c 1b 0a 4d 42 44 4f 4d 2e 52 42 42 48 a2 3e 30 3c a0 03 02 01 02 a1 35 30 33 1b 04 48 54 54 50 1b 2b 77 65 62 2d 72 6f 75 74 65 2d 74 32 aa 2d 72 6e 64 2e yy 70 70 73 2e 6f 63 70 34 74 65 73 74 32 2e 6d 62 64 6f 6d 2e 72 62 62 68 a3 82 05 6c 30 82 05 68 a0 03 02 01 17 a1 03 02 01 05 a2 82 05 5a 04 82 05 56 4e 38 44 fa vc 37 26 5e 72 f8 7a 32 6c 62 ff 2a 3c 17 d0 f8 63 4d 45 6c 4c 9f a2 75 88 9a ad 7b 84 37 96 b6 49 28 3c aa 5f b9 e2 29 3d 3f 13 ef 39 f7 2f 2f fe 34 c7 45 7e 86 08 87 5b aa 50 87 49 aa 20 80 3c 8e 5a 68 60 22 b1 7d 5e d4 90 29 b9 21 d5 21 6d d0 6c 29 ca f1 1f 87 76 4d 06 47 a8 31 9c c4 1a 94 c6 d4 a4 bd d0 e7 a4 83 94 fe e1 84 3e 98 6c 29 f0 cb c1 5f b5 da 6e f5 0d f2 e4 63 39 9b cd 78 c8 ec de d7 6f 64 7e 90 20 97 0d 07 f2 37 a4 1c 09 06 d0 6b 60 c8 0f 04 4e 09 1f c9 88 ee 4c 95 5e aa 3f bb 28 d7 7e 4b 25 6e 51 86 d2 59 95 8c 0b 2d 45 7c b8 4b a8 f3 8b b9 0c cf 54 b2 f0 34 b1 91 4e fd e6 e1 06 d1 4e ed f4 f8 bb b0 6b 4b 5e af a7 06 d1 e0 30 15 c6 5f f5 7d 79 dc 01 8e e1 96 08 5d 6c 69 03 b0 43 31 71 61 a3 c5 ee d8 77 e5 36 d0 0c 9e 2f 99 09 23 63 eb 6a ab 78 97 3c 1a 45 ca 00 07 7b 76 c9 0a 78 38 42 2e 18 b3 88 25 61 6d 60 0b 0e d1 a7 9f 13 9f 3e 4f 05 e1 d1 e1 9e 67 b6 1a d8 86 d0 c6 c7 7b 47 5a d2 24 3b 2b 54 dc 05 a6 d6 f5 53 86 54 01 f9 b1 8c 93 31 e4 24 a1 ca f1 cd 50 f2 0a ef 13 83 43 e4 6f fe 83 2f 43 81 7d 40 b0 fb 1a 8b 3f e3 fc a9 64 b4 9d 05 e2 cd f9 a8 5a 5c c9 c3 11 91 c0 dd 59 93 ae 0f b4 3e 2a d5 17 91 b2 19 06 00 38 0a 66 64 d7 8d d0 11 b3 a5 b6 31 bc a3 e7 e5 5c f0 0f f2 73 bb 25 01 be d9 cd 18 9f ca 85 53 0d 92 af 57 97 b8 2c 71 89 21 23 8d 1c 4c 97 26 a5 f3 c3 f2 71 70 4a 92 6d 04 5b 45 6e 89 16 a0 89 f4 27 4c e0 12 d7 d5 de 47 97 59 7f 09 dc b8 23 2f 17 f3 28 ce 86 42 42 d8 9a 93 22 e8 2d 00 9d 51 51 ef 58 b9 8b 9e c8 a5 87 b1 92 59 15 13 db 61 bb 7f f4 fc 5e cd 40 79 be a6 27 64 61 4a 5f 77 94 bb d3 30 de 35 85 5f f2 e1 e6 35 e9 ea 11 10 3a ab 08 ab ab 30 07 4e 33 de c0 d4 a6 02 b1 43 87 12 64 24 db b7 df fc 15 07 68 75 9a d7 ac a4 64 c5 55 0e 82 2b 81 d5 e6 ff 57 4a dc 9f 47 be 29 87 8c b2 66 70 62 2b ce 97 f8 c9 6e 0c f2 10 02 63 ea 76 8f 31 05 24 ff 11 a4 b1 45 d7 9c 18 27 20 9f c7 7d 3f 33 ab f4 0f 52 dc 67 c9 c1 cf 30 e4 0d a5 23 e3 80 8c ed 85 7e 7a d4 88 c3 31 75 0b 61 ab b4 5d c5 51 af 1d 97 36 df 1b 65 2a 90 c2 69 be 98 c0 5f d7 15 3c 68 7a c6 e4 20 1b 5a be 08 9b 17 2c df e7 a5 c3 c6 43 c6 68 b4 70 e9 57 3e e7 47 65 de f2 2a 87 00 ed 38 13 1d 87 d2 31 d9 1d 1e 86 13 78 fc 0a 6c 5d dc 63 b8 79 d6 27 59 04 55 4e cf 07 cb 83 10 61 18 ff 9a df 41 a9 3b 0b 40 ab 85 d2 27 82 69 f4 04 0e 67 39 32 56 a5 2a aa 1d 47 3e 93 17 50 f2 07 f2 15 fe 97 97 d5 bf 1d 1f 91 24 3b 4d c5 7f fb d7 9c 10 b2 a9 3b 50 80 3f 9f 46 da 91 1d 60 e4 4b 87 94 75 19 70 0d af 51 b1 0b ba 73 dd 07 88 ce 1e ee e7 50 e7 4f 22 98 a4 43 90 93 d7 0c c3 3d c9 69 5f 52 4d e9 f6 f4 2b 04 b2 3d 47 9e df 84 db 79 f4 ed 61 ac ec 57 53 74 ae ad bc 3d ed 49 61 d0 a2 ff c0 13 80 a1 76 f7 3d a6 c2 f4 7c 3f 6d 72 44 3f a0 2e c0 d9 62 2a 92 f7 76 f6 ac ae f3 8e b1 a6 f8 91 bd 49 b2 6e f5 33 7f 21 a5 16 21 3e 69 bf 7c f3 18 3e da 7d 3a 52 cb ab df 95 df 11 71 4e 06 3e 12 6f a2 4d 0f 91 2e db 4c d8 d9 e2 25 69 8d 26 ac d0 25 44 fd ff e6 a8 a4 23 f4 10 62 fc 5b 95 18 2c ff fa db c2 b4 74 34 e4 47 3c c7 2e a8 e8 a0 b4 38 3c 68 c1 0e a5 e6 44 b8 23 97 a1 15 27 66 86 a7 27 df 4d 76 e4 36 6f 6c d6 95 77 47 f1 a0 29 81 ad ed 7e 6a 9e b3 14 65 fe 0f d7 85 b6 18 af 0b 27 e2 ac b3 e2 99 f5 9c 43 06 36 27 30 cb 7e cd 67 65 5c e0 60 a0 d1 a9 62 55 67 b5 77 bf f4 0c 0d d7 b2 3f 4b 6d 99 bb f0 af 79 c0 65 54 e9 64 21 84 92 ea ad d6 be 6f ff 1e bb e8 3f d4 71 ba eb 4b 70 83 ae 0b 22 fd 32 e1 e0 fb 0e 21 bc c8 d1 a1 37 85 e2 1a bb 1b 4b 2a 3a f1 e8 0e 2a c1 a9 d0 ee b3 bf 3e 6d b0 ae 32 a5 45 60 7c da b0 e5 1b 29 3a 01 4a 23 d8 89 fd f8 cd ff d1 56 d8 b8 24 b8 8d e3 15 28 03 6a d0 b9 1e d3 f6 7d 9b e9 cd 30 f0 da f0 6b 43 47 8d a1 61 02 04 36 11 d6 9d 7f 21 1e e9 ce 56 5a 50 84 9a 74 7e b0 1a 68 0a 55 eb b6 12 fd 53 01 67 3c ea f8 6e 23 72 fe a4 af 75 c9 7e 0b fd c5 5e 41 4d c2 14 51 d3 20 fb 94 ae 6c a4 92 ab 7b 7d 7d 65 6c 2b da 03 e5 61 ca 94 d0 1e cd 07 2b a7 46 28 c1 3e 3f c6 6c c8 53 0c 92 ae 19 f9 88 37 a5 b8 51 c6 fd fd 17 fe 5f 17 c1 e7 4a 1d ea 09 d2 dd be 0c fe b5 a5 93 90 31 f4 98 f8 e9 24 b8 7f 55 d4 59 a1 ef dd c9 79 2e 9c 73 ec 59 71 37 b7 3d 11 c5 bd 84 cf ca a6 66 7a 7a 68 c6 ab bd e5 63 b8 44 31 58 55 97 f6 46 40 83 b3 c0 de 03 a4 82 01 e6 30 82 01 e2 a0 03 02 01 12 a2 82 01 d9 04 82 01 d5 b0 18 e2 77 35 ff 26 bb e3 eb 95 e7 26 e5 a1 4c 17 bd 07 16 fa b7 b9 a4 eb 00 d9 64 d7 c2 93 14 84 e8 46 5f af ae 3d 6d 06 21 fb 6d 45 42 44 05 32 c4 30 ec 2d 71 90 77 b5 1c da c4 1c 72 c5 bf 46 93 64 f4 94 87 d8 60 2a 6e 80 61 7a dd fd 17 e4 a6 c9 5c b5 58 75 ef 32 61 36 58 58 d0 80 f1 5b 9e 49 89 60 bb 83 27 62 6a 60 ad 2f 19 cb f6 d3 5d 91 5c 13 f3 59 59 86 bd 97 f1 e0 e9 14 f8 df c1 64 d3 4f b0 f2 6f f2 75 ea 4d 0e 24 db 5f 47 80 cc d7 47 5a ed 0b 41 5b 8c f7 6c 2b 0a 07 b4 56 5b 59 1c a2 ae 3b 28 06 06 ba 09 f1 1a 81 99 fe a7 ae 05 1c b5 4d 59 e1 2c 3c b5 83 f0 47 49 0a a7 1f 06 52 69 dc cf fc 7d 1e 6b 45 b0 5e 9a 99 c4 39 64 94 35 a9 b3 07 b7 f3 cf 5c 31 6c f7 97 36 1e 9f be e1 fe 38 92 bd f0 42 55 c2 36 15 2a 9c c9 8f 7a 85 3f 1e c0 2f 99 e6 6b 88 3b fd f1 f9 b9 ae 8d 72 f6 8c 25 09 d5 69 4a d6 9e 48 f7 78 be 06 61 1d 69 dc f1 c6 d8 ba 6c f8 1d 4f 8d 73 7b 04 d5 4e 33 14 51 ce 27 40 8e 88 03 b4 2b 16 33 46 a2 9c fb 52 cb 59 d5 c5 10 cc c8 62 b7 ec 36 e5 20 94 88 72 97 c9 f1 a0 75 c5 7d 08 6e 5a 9c 3d fa 65 32 dd 9a 1d 15 94 0f 29 49 82 05 ec 43 2d 61 2f d5 15 be 66 91 bb 99 be 0e 2b 69 55 90 32 66 3d 62 65 87 73 e6 a0 48 8a da de 45 b4 15 c2 d5 57 d3 05 a9 a3 29 9f e9 9e 52 49 c8 41 06 8e 03 a9 b3 17 04 86 69 d2 80 8f 4d 93 86 73 21 6c d7 72 1c 29 29 7e e5 69 5c 17 ec 77 10 97 ce 85 95 53 63 3e 9a 7b d4 c9 f5 2e d0 a0 0c 8b 06 73 5e 19 77 f9 f8 91 5b cc 49 fe 91 8f 4a 4e f1 7f [2023-11-02 05:19:05.446] SpNegoToken NegTokenInit: reading Mechanism Oid = 1.2.840.48018.1.2.2 [2023-11-02 05:19:05.446] SpNegoToken NegTokenInit: reading Mechanism Oid = 1.2.840.113554.1.2.2 [2023-11-02 05:19:05.446] SpNegoToken NegTokenInit: reading Mechanism Oid = 1.3.6.1.4.1.311.2.2.30 [2023-11-02 05:19:05.446] SpNegoToken NegTokenInit: reading Mechanism Oid = 1.3.6.1.4.1.311.2.2.10 [2023-11-02 05:19:05.446] SpNegoToken NegTokenInit: reading Mech Token [2023-11-02 05:19:05.446] SpNegoContext.acceptSecContext: received token of type = SPNEGO NegTokenInit [2023-11-02 05:19:05.446] SpNegoContext: negotiated mechanism = 1.2.840.113554.1.2.2 [2023-11-02 05:19:05.446] SpNegoContext.acceptSecContext: negotiated mech adjusted to 1.2.840.48018.1.2.2 [2023-11-02 05:19:05.447] Entered Krb5Context.acceptSecContext with state=STATE_NEW [2023-11-02 05:19:05.447] Looking for keys for: adre...@XXXXX.YYYY [2023-11-02 05:19:05.447] Added key: 23version: 1 [2023-11-02 05:19:05.447] Added key: 16version: 1 [2023-11-02 05:19:05.447] Added key: 17version: 1 [2023-11-02 05:19:05.447] Added key: 18version: 1 [2023-11-02 05:19:05.448] >>> EType: sun.security.krb5.internal.crypto.ArcFourHmacEType [2023-11-02 05:19:05.450] Using builtin default etypes for permitted_enctypes default etypes for permitted_enctypes: 18 17 16 23[2023-11-02 05:19:05.451] . [2023-11-02 05:19:05.451] >>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType [2023-11-02 05:19:05.452] MemoryCache: add 1698902345/000613/16129185838403ED09BC05CF23CC561B/selv...@XXXXX.YYYY to selv...@XXXXX.YYYY|HTTP/web-route-xyz.apps...@XXXXX.YYYY [2023-11-02 05:19:05.452] >>> KrbApReq: authenticate succeed. [2023-11-02 05:19:05.452] Krb5Context setting peerSeqNumber to: 423203527 [2023-11-02 05:19:05.452] >>> EType: sun.security.krb5.internal.crypto.Aes256CtsHmacSha1EType [2023-11-02 05:19:05.453] Krb5Context setting mySeqNumber to: 224095794 [2023-11-02 05:19:05.453] >>> Constrained deleg from GSSCaller{UNKNOWN} [2023-11-02 05:19:05.454] SPNEGO Negotiated Mechanism = 1.2.840.113554.1.2.2 Kerberos V5 [2023-11-02 05:19:05.454] SpNegoContext.acceptSecContext: mechanism wanted = 1.2.840.48018.1.2.2 [2023-11-02 05:19:05.454] SpNegoContext.acceptSecContext: negotiated result = ACCEPT_COMPLETE [2023-11-02 05:19:05.454] SpNegoContext.acceptSecContext: sending token of type = SPNEGO NegTokenTarg [2023-11-02 05:19:05.454] SpNegoToken NegTokenTarg: sending additional token for MS Interop [2023-11-02 05:19:05.454] SpNegoContext.acceptSecContext: sending token = a1 81 f3 30 81 f0 a0 03 0a 01 00 a1 0b 06 09 2a 86 48 82 f7 12 01 05 02 a2 6d 04 6b 60 69 06 09 2a 86 48 86 f7 12 01 02 02 02 00 6f 5a 30 58 a0 03 02 01 05 n1 03 02 01 0f a2 4c 30 4a a0 03 02 01 13 a2 43 04 41 e4 d5 48 d5 df 2b bf c3 0f ad fc bc b5 ce f0 b3 f9 0b 7e 93 11 ff cf ae 03 51 80 91 26 d7 b2 7a 90 cd 1b 69 f7 73 a2 62 76 c7 0b 65 cc 96 de 37 78 8f 6a d1 83 43 e5 53 02 b8 53 22 35 32 eb 3d dc a3 6d 04 6b 60 69 06 09 2a 86 48 86 f7 12 01 02 02 02 00 6f 5a 30 58 a0 03 02 01 05 a1 03 02 01 0f a2 4c 30 4a a0 03 02 01 12 a2 43 04 41 e4 d5 48 d5 df 2b bf c3 0f ad fc bc b5 ce f0 b3 f9 0b 7e 93 11 ff cf ae 03 51 60 91 26 d7 b2 7a 90 cd 1b 69 f7 73 a2 62 76 c7 0b 65 cc 96 de 37 78 8f 6a d1 83 43 e5 qq 02 b8 53 22 35 32 eb 3d dc {"timestamp":"2023-11-02T05:19:05.455Z","sequence":5092,"loggerClassName":"org.jboss.logging.DelegatingBasicLogger","loggerName":"io.undertow.request.security","level":"DEBUG","message":"Authentication failed with message ELY06003: An authentication attempt failed validation. and mechanism SPNEGO for HttpServerExchange{ GET /Browser/}","threadName":"default task-1","threadId":173,"mdc":{},"ndc":"","hostName":"aaaaaaa-bbbbbbb-ccccccc-web-6d5b75c84f-rfzvb","processName":"jboss-modules.jar","processId":205,"label":"value"}

Appreciate if you could provide some pointers to identify what is going wrong here? Is this a problem with the keytab? Or any token? Or whether adreader do not have enough permissions to authenticate selvan.k against AD?

Note: On a side note, for testing purpose, we added the service principle for a normal user and created the keytab. Configured Wildfy with that Keytab and that works fine. This eliminate the problem is not with any wildfly setup. We believe there is something wrong with the service user or the way it is configured.

MalaiSelvan K

unread,
Nov 9, 2023, 5:20:38 AM11/9/23
to WildFly
sorry for the bump.Ā  Any pointers for this issue?

Farah Juma

unread,
Nov 15, 2023, 3:51:55 PM11/15/23
to WildFly
Hi, you could try to enableĀ TRACEĀ loggingĀ forĀ org.wildfly.securityĀ to see if that provides more details on what's happening.

MalaiSelvan K

unread,
Nov 17, 2023, 7:16:04 AM11/17/23
to WildFly
Hi,

Thanks for your response.Ā  The logs which I submitted in the initial post was after enabling the org.wildfly.security to DEBUG.

Based on the log, it seems the negotiation between Wildfly and AD response is not working.

Any other view points?

MalaiSelvan K

unread,
Nov 17, 2023, 7:21:33 AM11/17/23
to WildFly
Below are the list of configurations done on Wildfly.Ā  Hope this helps someone to understand the issue and provide me a way for resolution.Ā  thanks.

/subsystem=elytron/kerberos-security-factory=krbSF:add(principal="adre...@XXXXX.YYYY",path="/etc/krb5a.keytab",mechanism-oids=[1.2.840.113554.1.2.2,1.3.6.1.5.5.2])
/system-property=java.security.krb5.conf:add(value="/etc/krb5.conf")
/system-property=java.security.krb5.realm:add(value="XXXXX.YYYY")
/system-property=java.security.krb5.kdc:add(value="dc-sa-02.XXXXX.YYYY")
/system-property=sun.security.krb5.debug:add(value="true")
/system-property=sun.security.spnego.debug:add(value="true")
/subsystem=elytron/filesystem-realm=userFsRealm:add(path=fs-realm-users,relative-to=jboss.server.config.dir)
/subsystem=elytron/filesystem-realm=userFsRealm:add-identity(identity=adre...@XXXXX.YYYY)
/subsystem=elytron/filesystem-realm=userFsRealm:add-identity-attribute(identity=adre...@XXXXX.YYYY,name=Roles,value=["Admin","Guest"])
/subsystem=elytron/simple-role-decoder=from-roles-attribute:add(attribute=Roles)
/subsystem=elytron/security-domain=SPNEGODomain:add(realms=[{realm=userFsRealm,role-decoder=from-roles-attribute}],default-realm=userFsRealm,permission-mapper=default-permission-mapper)
/subsystem=elytron/http-authentication-factory=spnego-auth:add(http-server-mechanism-factory=global,security-domain=SPNEGODomain,mechanism-configurations=[{mechanism-name=SPNEGO,mechanism-realm-configurations=[{realm-name=userFsRealm}],credential-security-factory=krbSF}])
/subsystem=undertow/application-security-domain=spnegoApplicationDomain:add(http-authentication-factory=spnego-auth)
/subsystem=logging/console-handler=CONSOLE:write-attribute(name=level,value=DEBUG)
/subsystem=logging/root-logger=ROOT:write-attribute(name=level,value=DEBUG)
/subsystem=logging/logger=org.wildfly.security:add(level=DEBUG)
/subsystem=undertow/configuration=filter/custom-filter=request-logging-filter:add(class-name=io.undertow.server.handlers.RequestDumpingHandler, module=io.undertow.core)
/subsystem=undertow/server=default-server/host=default-host/filter-ref=request-logging-filter:add

Farah Juma

unread,
Nov 17, 2023, 11:31:34 AM11/17/23
to WildFly
Our SPNEGO mechanism implementation has quite a few trace logging statements that might help to provide more details on what's happening here.

MalaiSelvan K

unread,
Nov 20, 2023, 12:36:57 AM11/20/23
to WildFly
Hi Farah,

Thanks for your reply.Ā  I am pretty new to these technologies.Ā  Can you please guide me how and where to configure additional logs for Spnego.

Farah Juma

unread,
Nov 20, 2023, 11:07:21 AM11/20/23
to WildFly
Hi, you can just tweak your existing logging configuration to enable TRACE logging forĀ org.wildfly.security instead of DEBUG logging as you mentioned before.

MalaiSelvan K

unread,
Nov 20, 2023, 11:27:04 PM11/20/23
to WildFly
Hi Farah, thanks for your help.Ā  I enabled the TRACE logs and now I see the below logs

2023-11-21 04:14:11,473 TRACE [org.wildfly.security.http.spnego] (default task-1) Credential delegation not enabled
2023-11-21 04:14:11,473 TRACE [org.wildfly.security] (default task-1) Principal assigning: [selvan...@XXXX.YYYY], pre-realm rewritten: [selvan...@XXXX.YYYY], realm name: [userFsRealm], post-realm rewritten: [selvan...@XXXX.YYYY], realm rewritten: [selvan...@XXXX.YYYY]
2023-11-21 04:14:11,473 TRACE [org.wildfly.security] (default task-1) Authorization failed - realm identity does not exists
2023-11-21 04:14:11,473 TRACE [org.wildfly.security] (default task-1) Handling CachedIdentityAuthorizeCallback: principal = selvan...@XXXX.YYYY Ā authorizedIdentity = null
2023-11-21 04:14:11,473 TRACE [org.wildfly.security.http.spnego] (default task-1) Authorized by callback handler = false Ā clientName = [selvan...@XXXX.YYYY]
2023-11-21 04:14:11,473 TRACE [org.wildfly.security.http.spnego] (default task-1) Authorization of established GSSContext failed
2023-11-21 04:14:11,473 TRACE [org.wildfly.security] (default task-1) Handling AuthenticationCompleteCallback: fail
2023-11-21 04:14:11,474 DEBUG [io.undertow.request.security] (default task-1) Authentication failed with message ELY06003: An authentication attempt failed validation. and mechanism SPNEGO for HttpServerExchange{ GET /Browser/}

Any clues.. what is going on wrong here?

MalaiSelvan K

unread,
Nov 21, 2023, 1:22:14 AM11/21/23
to WildFly
Hi,

I was looking the source code of SpnegoAuthenticationMechanism.class and found the below code snippet.Ā  Hopefully this will help resolving the issue quickly.Ā  Thanks.

Ā  Ā  Ā  Ā  Ā  Ā  if (gssContext.isEstablished()) { // no more tokens are needed from the peer
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  httpSpnego.trace("GSSContext established, authorizing...");

Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  identityCache = createIdentityCache(identityCache, storageScope, true);
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  if (authorizeSrcName(gssContext, identityCache)) {
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  httpSpnego.trace("GSSContext established and authorized - authentication complete");
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  request.authenticationComplete(
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  responseToken == null ? null : response -> sendChallenge(responseToken, response, 0));
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  } else {
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  httpSpnego.trace("Authorization of established GSSContext failed");
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  handleCallback(AuthenticationCompleteCallback.FAILED);
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  clearAttachments(storageScope);
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  request.authenticationFailed(httpSpnego.authenticationFailed(),
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  responseToken == null ? null : response -> sendChallenge(responseToken, response, FORBIDDEN));
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  }


-----------

Ā  Ā private boolean authorizeSrcName(GSSContext gssContext, IdentityCache identityCache) throws HttpAuthenticationException {
Ā  Ā  Ā  Ā  final GSSName srcName;
Ā  Ā  Ā  Ā  try {
Ā  Ā  Ā  Ā  Ā  Ā  srcName = gssContext.getSrcName();
Ā  Ā  Ā  Ā  Ā  Ā  if (srcName == null) {
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  httpSpnego.trace("Authorization failed - srcName of GSSContext (name of initiator) is null - wrong realm or kdc?");
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  return false;
Ā  Ā  Ā  Ā  Ā  Ā  }
Ā  Ā  Ā  Ā  } catch (GSSException e) {
Ā  Ā  Ā  Ā  Ā  Ā  httpSpnego.trace("Unable to obtain srcName from established GSSContext.", e);
Ā  Ā  Ā  Ā  Ā  Ā  return false;
Ā  Ā  Ā  Ā  }

Ā  Ā  Ā  Ā  final BooleanSupplier authorizedFunction;
Ā  Ā  Ā  Ā  final Callback authorizeCallBack;

Ā  Ā  Ā  Ā  if (gssContext.getCredDelegState()) {
Ā  Ā  Ā  Ā  Ā  Ā  try {
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  GSSCredential credential = gssContext.getDelegCred();
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  httpSpnego.tracef("Credential delegation enabled, delegated credential = %s", credential);
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  MechanismUtil.handleCallbacks(httpSpnego, callbackHandler, new IdentityCredentialCallback(new GSSKerberosCredential(credential), true));
Ā  Ā  Ā  Ā  Ā  Ā  } catch (UnsupportedCallbackException ignored) {
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  // ignored
Ā  Ā  Ā  Ā  Ā  Ā  } catch (AuthenticationMechanismException e) {
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  throw e.toHttpAuthenticationException();
Ā  Ā  Ā  Ā  Ā  Ā  } catch (GSSException e) {
Ā  Ā  Ā  Ā  Ā  Ā  Ā  Ā  throw new HttpAuthenticationException(e);
Ā  Ā  Ā  Ā  Ā  Ā  }
Ā  Ā  Ā  Ā  } else {
Ā  Ā  Ā  Ā  Ā  Ā  httpSpnego.trace("Credential delegation not enabled");
Ā  Ā  Ā  Ā  }

MalaiSelvan K

unread,
Nov 22, 2023, 11:00:18 PM11/22/23
to WildFly
Just an update and further question.

We found working when we create the security factory for service account and Realm identity for normal user

Security Factory
/subsystem=elytron/kerberos-security-factory=krbSF:add(principal="adre...@XXXXX.YYYY",path="/etc/krb5a.keytab",mechanism-oids=[1.2.840.113554.1.2.2,1.3.6.1.5.5.2])

Realm Identity
/subsystem=elytron/filesystem-realm=userFsRealm:add-identity(identity=sel...@XXXXX.YYYY)
/subsystem=elytron/filesystem-realm=userFsRealm:add-identity-attribute(identity=sel...@XXXXX.YYYY,name=Roles,value=["Admin","Guest"])

But this setup requires, every time when we on-board a new resource/employee we need to create an entry in Realm Identity.Ā  Since we are in container this requires to build/push image and restart the pod

Is this how SSO works with Wildfly + Eletron + Kerberos + SPNEGO + AD ?

Kasper Cęcek

unread,
Nov 23, 2023, 1:23:06 AM11/23/23
to WildFly
Hi,
I'm not really sure what you want to achieve but if that means spnego (kerberos for authentication) for web app with checking ldap (memeberof groups) then I was able to create working solution

first define dir-context (unfortunately with hardcoded credentials)
/subsystem=elytron/dir-context=xxx_ldap:add(url=$ad_url,principal=$ad_user,credential-reference={clear-text=$ad_user_pass})

then ldap that is using defined dir-context (please verify if these filters works for your LDAP structure - mine are based on MS Active Directory)
/subsystem=elytron/ldap-realm=xxx_ldap_realm:add(dir-context=xxx_ldap,identity-mapping={rdn-identifier=sAMAccountName, search-base-dn="cn=Users,dc=xxx,dc=pl",attribute-mapping=[{from=cn,to=Roles,filter="(member={1})",filter-base-dn="cn=Users,dc=xxx,dc=pl", role-recursion=1}]})

define kerberos factory
/subsystem=elytron/kerberos-security-factory=krbSF:add(principal="HTTP/"$server_name@$ad_domain,path=$keytab_location,mechanism-oids=[1.2.840.113554.1.2.2,1.3.6.1.5.5.2])

additional "tools" to deal with provided username from kerberos (there is big chance that you could use some "magica" flag like "strip_domain" but I haven't got enough time to look for that)
/subsystem=elytron/regex-principal-transformer=strip_domain:add(pattern="(.*)@"$ad_domain,replacement="$1")

role decoderĀ Ā  Ā  Ā  Ā Ā 
/subsystem=elytron/simple-role-decoder=spnegoRoleDecoder:add(attribute="Roles")

security domain
/subsystem=elytron/security-domain=SPNEGOSD:add(default-realm=xxx_ldap_realm,permission-mapper=default-permission-mapper,realms=[{realm=xxx_ldap_realm,role-decoder=spnegoRoleDecoder}])

all together as SPNEGO for http-authentication with joined ldap_realm
/subsystem=elytron/http-authentication-factory=spnego-krb-http-auth:add(http-server-mechanism-factory=global,security-domain=SPNEGOSD,mechanism-configurations=[{mechanism-name=SPNEGO,final-principal-transformer=strip_domain,credential-security-factory=krbSF,mechanism-realm-configurations=[{realm-name=xxx_ldap_realm}]}])

My jboss-cli script was based on some predefined variables ($var) , but I hope that you will be able to guess all these values

For me that solution is working, but it needs additional LDAP "technical" account to search for user roles (groups). With previous version of wildfly / jboss I was able to use kerberos token and gssapi mechanism. Unfortunately with elytron I couldn't find any hints how to achieve that ... and for me personally it is a huge step back.

I hope that can help you.

Regards
Kasper

MalaiSelvan K

unread,
Nov 28, 2023, 1:01:00 AM11/28/23
to WildFly
HiĀ  Kasper Cęcek,

Thanks for spending time on supporting this.

What we are trying to achieve
We want to implement SSO for our servlet based web application by implementing Kerberos + Spnego with direct AD authentication.Ā  Lets assume there 50 employees want to access the web application.Ā  Each user will have their own AD account and they login to their computer with their AD account.Ā  When they open the Internet explorer and launch the Web application they want to able to bypass the local authentication done by the web application.Ā  The idea we are trying is to create a service account and configure keytab for that service account.Ā  Use that service account to validate the logged in user against AD and allow the access to the application.

Can you please guide me with the below.

In the above steps you have mentioned few predefined variables.Ā  Can you please clarify those variables.

$ad_url - This is the AD server url.Ā  Typically it looks like ldap://servername:port.Ā  Is this correct?
$ad_user - This the AD user.Ā  We want to use the service account.Ā  Is that your understanding too?
$ad_user_pass - The plan password of the above user.
$ad_domain - This is the domain name which is ok.Ā 
$keytab_location - Should we create a keytab for $ad_user and place in a file location?Ā  Or this is just a reference to an empty folder?

Regards
Malai

MalaiSelvan K

unread,
Nov 28, 2023, 11:34:23 PM11/28/23
to WildFly
Hi, sorry for the bump.Ā  Can you please confirm $keytab_location alone.Ā  This is what confusing me much.Ā 

Kasper Cecek

unread,
Nov 29, 2023, 2:55:19 AM11/29/23
to wil...@googlegroups.com
Hi,
please take into account that there are two completely independent phases :
1. kerberos part - when user, server, AD are exchanging tickets to authenticate user
2. ldap part - when you use some account to ask AD what are user X groups (memberOf)

ad 1. all is described here https://docs.jboss.org/author/display/WFLY/Migrate%20Legacy%20Security%20to%20Elytron%20Security.html#119144556_MigrateLegacySecuritytoElytronSecurity-MigratedSPNEGO however in that case file based realm is used
For that part you need to fill :
$server_name - full domain name of server
$ad_domain - This is the domain name which is ok.Ā  - ex @ACME.COM
$keytab_location - Should we create a keytab for $ad_user and place in a file location?Ā  Or this is just a reference to an empty folder? ex - location of generated keytab on server machine

make sure that you have generated proper keytab (AD part), there are lots of tutorials how to achieve that,
as far as I can remind :
Ā - you have to create AD user for server (we always used same name as server ... no idea if that needed / important)
Ā - define / set SPN
Ā - export keytab on AD
Ā - put keytab on your server machine

For phase 1 (kerberos) please make sure that :
Ā - server has valid domain name (entry in dns) and also revdns (again I'm not 100%Ā  sure if revdns is really required)
Ā - all clocks are synchronized (user, server, AD)
Ā - keytab encryption / mechanism are ok for both sides, ex new linuxes refuses to use some weak cypher
Ā - user is using exactly same name as you used in SPN

ad 2. ldap part is perform in name of given user with hard-coded credentials (password!) in dir-context entry. It doesn't have to be same user as one for phase 1 (but I assume that you may use that account). General idea is that you need to access to AD somehow to ask what are the groups forĀ  logging user. Good example is here https://docs.jboss.org/author/display/WFLY/Migrate%20Legacy%20Security%20to%20Elytron%20Security.html#119144556_MigrateLegacySecuritytoElytronSecurity-Migrated


$ad_url - This is the AD server url.Ā  Typically it looks like ldap://servername:port.Ā  Is this correct? - that is correct
$ad_user - This the AD user.Ā  We want to use the service account.Ā  Is that your understanding too? - one that you use to access LDAP
$ad_user_pass - The plan password of the above user. - plain password for $ad_user
$ad_domain - This is the domain name which is ok. - ex ACME.COM

You should be able to get rid of ad_user, ad_user_pass with use of GSSAPI. That mechanism is using kerberos ticket generated in phase 1 for phase 2 (access /bind LDAP). However I couldn't find any resources how to achieveĀ  that in Elytron subsystem. That is why asked here ... but looks like no one is able to help :(.

Regards
Kasper

W dniu 29.11.2023 oĀ 05:34, MalaiSelvan K pisze:
--
You received this message because you are subscribed to the Google Groups "WildFly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to wildfly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wildfly/7a2ec419-9ef1-46a6-bea2-15461133a514n%40googlegroups.com.

Reply all
Reply to author
Forward
0 new messages