I have some trouble connecting to a remote mongodb from a java spring boot application.
The MongoDB server has no firewall set up, and I can connect to mongo remotely from another machine. I have a database with collections and a user set up.
When I try to connect to the database from my java app with the user credentials, I get an exception:
com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=null, userName='sokrates', source='homeControl', password=<hidden>, mechanismProperties={}}
at com.mongodb.connection.SaslAuthenticator.authenticate(SaslAuthenticator.java:61) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.DefaultAuthenticator.authenticate(DefaultAuthenticator.java:32) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.InternalStreamConnectionInitializer.authenticateAll(InternalStreamConnectionInitializer.java:99) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.InternalStreamConnectionInitializer.initialize(InternalStreamConnectionInitializer.java:44) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:115) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:128) ~[mongodb-driver-core-3.2.2.jar:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_92]
Caused by: com.mongodb.MongoCommandException: Command failed with error 18: 'Authentication failed.' on server localhost:27017. The full response is { "ok" : 0.0, "code" : 18, "errmsg" : "Authentication failed." }
at com.mongodb.connection.CommandHelper.createCommandFailureException(CommandHelper.java:170) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.CommandHelper.receiveCommandResult(CommandHelper.java:123) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.CommandHelper.executeCommand(CommandHelper.java:32) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.SaslAuthenticator.sendSaslStart(SaslAuthenticator.java:95) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.SaslAuthenticator.authenticate(SaslAuthenticator.java:45) ~[mongodb-driver-core-3.2.2.jar:na]
... 6 common frames omitted
When I use the same code to connect to a local MongoDB, with the same setup, database, collections and user, all is OK.
I had a little trouble with setting an admin user up on the mongo installation. Also, the local mongo runs on OSX, whereas the production mongo (that fails to authenticate) runs on Ubuntu Server 16.04.
I have researched other MongoDB authentication threads for two days now, but none could solve this issue for me. Any help with this is appreciated :-)
Thanks,
Stefan
I found the problem. For completeness of this thread, I'll share the answer, including the code.
The issue was that I used the application property spring.data.mongodb.uri wrong: it did not have the username and password in the URI, because I mistakenly believed that spring.data.mongodb.username and spring.data.mongodb.password covered that. So, either use the uri with username and password, or use the host and database (and maybe also port) spring properties explicitly.
Here is the code. It will work in the spring boot app with mongoDB support (use initializr or IntelliJ to create that project).
I have a model:
package net.IndyStef.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Document(collection = "person")
public class Person {
@Id
private String id;
private String name;
private Integer age;
public Person() {
}
public Person(String id) {
this.id = id;
}
public Person(String id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
... getters/setters omitted for breverity ...
}
The data is read and written through a repository:
package net.IndyStef.repository;
import net.okrongli.model.Person;
import org.springframework.data.mongodb.repository.MongoRepository;
/**
* Created by IndyStef on 23/08/16.
*/
public interface PersonRepository extends MongoRepository<Person, String> {
}
The database name, host, and credentials are in the application.properties file:
spring.data.mongodb.host=192.168.1.90
spring.data.mongodb.database=people
spring.data.mongodb.username=user
spring.data.mongodb.password=password
#spring.data.mongodb.uri=mongodb://192.168.1.90/people
Important is to not mix the uri with database and username. If you use uri, it needs to include the username and password, like this:
spring.data.mongodb.uri=mongodb://user:password@192.168.1.90/people
To test this, I used a simple Spring command line runner:
package net.IndyStef;
import net.IndyStef.model.Person;
import net.IndyStef.repository.PersonRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.List;
@SpringBootApplication
public class MongoDbTestApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(MongoDbTestApplication.class, args);
}
@Autowired
private PersonRepository repository;
@Override
public void run(String... args) {
repository.save(new Person("peter.pan", "Peter Pan", 865));
List<Person> people = repository.findAll();
for (Person person: people) {
System.out.println(person);
}
}
}
I hope this explanation helps others that couldn't figure it out, like myself for a couple of days.
Thanks,
Stefan
As of Spring Boot 1.5.15, you can add the following line to your application.properties
file:
spring.data.mongodb.uri=mongodb://username:password@localhost:27017/?authSource=admin&authMechanism=SCRAM-SHA-1
spring.data.mongodb.database=mycollection
This is what worked for me at then end:
spring.data.mongodb.uri=mongodb://user:password@******.mongodb.net:27017/dbname?ssl=true&authSource=admin&authMechanism=SCRAM-SHA-1
I had to add ssl=true
, otherwise I was getting error:
com.mongodb.MongoSocketReadException: Prematurely reached end of stream