[JAVA-4389] Getting com.mongodb.MongoSecurityException: Failed to login Subject when connecting mongoDB Created: 04/Nov/21  Updated: 07/Apr/23  Resolved: 08/Nov/21

Status: Closed
Project: Java Driver
Component/s: Authentication
Affects Version/s: None
Fix Version/s: None

Type: Task Priority: Major - P3
Reporter: Amy Cui Assignee: Jeffrey Yemin
Resolution: Done Votes: 0
Labels: external-user
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to JAVA-3836 Support a Kerberos ticket cache Closed
is related to JAVA-4391 Accept "com.sun.security.jgss.initiat... Closed

 Description   

Hi,

To replace mongodb-java-driver 3.12.8, I am trying to make my code work this the following jars:

mongodb-driver-sync-4.3.3.jar

mongodb-driver-core-4.3.3.jar

mongodb-driver-legacy-4.3.3.jar

bson-4.3.3.jar

I use the following code to connect:

 

 System.setProperty("java.security.krb5.conf", "krb5.conf"); 

System.setProperty("java.security.krb5.conf", "krb5.conf");     System.setProperty("java.security.krb5.realm", "<<my-domain>>");     System.setProperty("java.security.krb5.kdc", "<<my-domain>>"");     System.setProperty("javax.security.auth.useSubjectCredsOnly","false");     System.setProperty("java.security.auth.login.config", "jaas.conf");    

return new MongoClient(serverAddresses, MongoCredential.createGSSAPICredential("<<my-kerberos-id>>@<<my-domain>>"), options);

 

my jaas.conf is as follows:

com.sun.security.jgss.initiate

{ com.sun.security.auth.module.Krb5LoginModule required useKeyTab=true useTicketCache=false doNotPrompt=true debug=true keyTab="mykeytab.kt" principal="<<my-kerberos-id>>@<<my-domain>>; }

;

 

I am getting below errors:

 

INFO: Creating new LoginContext and logging in the principalException in thread "main" com.mongodb.MongoSecurityException: Failed to login Subject at com.mongodb.internal.connection.SaslAuthenticator.getSubject(SaslAuthenticator.java:200) at com.mongodb.internal.connection.SaslAuthenticator.doAsSubject(SaslAuthenticator.java:278) at com.mongodb.internal.connection.SaslAuthenticator.authenticate(SaslAuthenticator.java:57) at com.mongodb.internal.connection.InternalStreamConnectionInitializer.authenticate(InternalStreamConnectionInitializer.java:205) at com.mongodb.internal.connection.InternalStreamConnectionInitializer.finishHandshake(InternalStreamConnectionInitializer.java:79) at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:170) at com.mongodb.internal.connection.UsageTrackingInternalConnection.open(UsageTrackingInternalConnection.java:53) at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.open(DefaultConnectionPool.java:495) at com.mongodb.internal.connection.DefaultConnectionPool$OpenConcurrencyLimiter.openOrGetAvailable(DefaultConnectionPool.java:855) at com.mongodb.internal.connection.DefaultConnectionPool$OpenConcurrencyLimiter.openOrGetAvailable(DefaultConnectionPool.java:805) at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:154) at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:144) at com.mongodb.internal.connection.DefaultServer.getConnection(DefaultServer.java:92) at com.mongodb.internal.binding.ClusterBinding$ClusterBindingConnectionSource.getConnection(ClusterBinding.java:141) at com.mongodb.client.internal.ClientSessionBinding$SessionBindingConnectionSource.getConnection(ClientSessionBinding.java:163) at com.mongodb.internal.operation.ListCollectionsOperation$1.call(ListCollectionsOperation.java:233) at com.mongodb.internal.operation.ListCollectionsOperation$1.call(ListCollectionsOperation.java:230) at com.mongodb.internal.operation.OperationHelper.withReadConnectionSource(OperationHelper.java:583) at com.mongodb.internal.operation.ListCollectionsOperation.execute(ListCollectionsOperation.java:230) at com.mongodb.internal.operation.ListCollectionsOperation.execute(ListCollectionsOperation.java:86) at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:184) at com.mongodb.client.internal.MongoIterableImpl.execute(MongoIterableImpl.java:135) at com.mongodb.client.internal.MongoIterableImpl.iterator(MongoIterableImpl.java:92) at com.mongodb.client.internal.MappingIterable.iterator(MappingIterable.java:39) at com.mongodb.client.internal.MappingIterable.iterator(MappingIterable.java:27) at MyGFMongoTest.main(MyGFMongoTest.java:81)Caused by: javax.security.auth.login.LoginException: No LoginModules configured for com.sun.security.jgss.krb5.initiate at javax.security.auth.login.LoginContext.init(LoginContext.java:264) at javax.security.auth.login.LoginContext.<init>(LoginContext.java:348) at com.mongodb.KerberosSubjectProvider.getSubject(KerberosSubjectProvider.java:84) at com.mongodb.internal.connection.SaslAuthenticator.getSubject(SaslAuthenticator.java:198) ... 25 more

 

 

The same code works with mongodb-java-driver-3.12.8.jar

 

Please advise.

 

 



 Comments   
Comment by Jeffrey Yemin [ 08/Nov/21 ]

Glad that you got it working. I opened JAVA-4391 to address the underlying issue.

Thanks for reporting this! I'm sure the fix to JAVA-4391 will help future users.

Comment by Amy Cui [ 08/Nov/21 ]

Hi Jeff,

Thank you for your quick response. I tried what you suggested with 4.3.3 version and I am able to get it working.  Code snippet:

 

 com.mongodb.KerberosSubjectProvider provider= new KerberosSubjectProvider("com.sun.security.jgss.initiate");    

MongoCredential credential = MongoCredential.createGSSAPICredential("<<my-kerberos-id>>@<<my-domain>>);    

credential.withMechanismProperty(MongoCredential.JAVA_SUBJECT_PROVIDER_KEY, provider);    

return new MongoClient(serverAddresses,credential,options);

 

Thank you 

Amy

Comment by Jeffrey Yemin [ 06/Nov/21 ]

I think I understand what's going on. In the 4.2 release, we introduced a new feature for caching Kerberos tickets: JAVA-3836. One of the consequences of that work is that the driver now by default always creates the Subject instance itself instead of relying on the JDK to do so. The LoginContext is now configured here. Note that the default is to use "com.sun.security.jgss.krb5.initiate" as the default login context name. In contrast, the JDK looks for both "com.sun.security.jgss.krb5.initiate" and "com.sun.security.jgss.initiate" (for reasons I'm not sure of). You can find that code here.

I think we should change the driver to also accept both, but until then you can work around it in a number of ways:

  • Change your jaas.conf to configure "com.sun.security.jgss.krb5.initiate", as mentioned above
  • Configure com.mongodb.MongoCredential#JAVA_SUBJECT_PROVIDER_KEY with an instance of com.mongodb.KerberosSubjectProvider constructed like new KerberosSubjectProvider("com.sun.security.jgss.initiate")

CC luke.prochazka

Comment by Jeffrey Yemin [ 05/Nov/21 ]

Also, can you try changing your jaas.conf to configure com.sun.security.jgss.krb5.initiate instead of com.sun.security.jgss.initiate?

Comment by Jeffrey Yemin [ 05/Nov/21 ]

Hi tcui@pershing.com,

Can you try with 4.1 driver, and then either 4.0 (if 4.1 fails) or 4.2 (if 4.1 succeeds)? That will help narrow down where the problem was introduced.

Thanks,
Jeff

Generated at Thu Feb 08 09:01:57 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.