I am trying to configure basic login / password authentication for p2p replication.
Replication works fine with no authentication. So I pretty sure my issue relates to authentication configuration.
CBListener
configuration:
login = "my_login"
password = "my_password"
listener = CBLListener(manager: CBLManager.sharedInstance(), port: 55555)
listener.setBonjourName(netServiceName, type: netServiceType)
listener.readOnly = true
listener.setPasswords([login : password])
try! listener.start()
CBLReplication
configuration:
let netService: NetService = ... // Got from NetServiceBrowserDelegate and NetServiceDelegate
let components = NSURLComponents()
components.scheme = "http"
components.host = netService.hostName
components.port = NSNumber(value: 55555)
components.path = "/" + database.name
components.user = login
components.password = password
let newReplication = database.createPullReplication(components.url!)
newReplication.continuous = true
newReplication.start()
Here is what I am getting in Xcode console:
CBLRestPuller[http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: Going online
CBLRestPuller[http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: No local checkpoint; not getting remote one
CBLRestPuller[http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net] Progress: set active = 1
CBLReplication[from http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: active, progress = 0 / 0, err: (null) nil
CBLRestPuller[http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: Reachability state = :reachable (20002), suspended=0
: HTTP auth failed; sent Authorization: Basic bXlfbG9naW46bXlfcGFzc3dvcmQ= ; got WWW-Authenticate: Digest realm="CouchbaseLite", qop="auth", nonce="69773230-683C-4DCC-AB40-A21527A1F911"
CBLSocketChangeTracker[0x127d63810 sg_to_firstfoundry_net]: Can't connect, giving up: CBLHTTP[401, http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_changes?feed=normal&heartbeat=300000&style=all_docs]<--NSURLError[-1013, http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_changes?feed=normal&heartbeat=300000&style=all_docs]
CBLRestPuller[http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: ChangeTracker stopped; error=CBLHTTP[401, http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_changes?feed=normal&heartbeat=300000&style=all_docs]<--NSURLError[-1013, http://my_login:*****@Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_changes?feed=normal&heartbeat=300000&style=all_docs]
I think the most important log here is this line:
: HTTP auth failed; sent Authorization: Basic bXlfbG9naW46bXlfcGFzc3dvcmQ= ; got WWW-Authenticate: Digest realm="CouchbaseLite", qop="auth", nonce="69773230-683C-4DCC-AB40-A21527A1F911"
Alternatively I tried to use CBLAuthenticator
instead of injecting login/password into url. Still doesn't work, however I am getting different error messages in log:
What is changed:
// Added:
newReplication.authenticator = CBLAuthenticator.basicAuthenticator(withName: login, password: password)
// Removed:
components.user = login
components.password = password
Here is what I am getting in Xcode console after updating the code:
CBLRestPuller[http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: Going online
CBLRestPuller[http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net] Progress: set active = 1
CBLRestPuller[http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: Successfully logged in!
RemoteRequest: Added Authorization header for CBLPasswordAuthorizer[my_login/****]
CBLRemoteJSONRequest[GET http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_local/b3f625c9bddabfb59ee49d78f3bb484a5876b486]: Starting...
DEALLOC CBLRemoteLogin[http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net] 2017-02-20 16:51:28.335 Union Dev[1922:1702832] RemoteRequest: CBLRemoteSession starting CBLRemoteJSONRequest[GET http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_local/b3f625c9bddabfb59ee49d78f3bb484a5876b486]
Sync: CBLReplication[from http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: active, progress = 0 / 0, err: (null) nil
CBLRestPuller[http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: Reachability state = :reachable (20002), suspended=0
RemoteRequest: Got challenge for CBLRemoteJSONRequest[GET http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_local/b3f625c9bddabfb59ee49d78f3bb484a5876b486]: method=NSURLAuthenticationMethodHTTPDigest, err=(null)
RemoteRequest: challenge: (phase 3) continueWithoutCredential
Sync: CBLRestPuller[http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: Server is (null)
RemoteRequest: CBLRemoteJSONRequest[GET http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_local/b3f625c9bddabfb59ee49d78f3bb484a5876b486]: Got response, status 401
CBLRemoteJSONRequest[GET http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_local/b3f625c9bddabfb59ee49d78f3bb484a5876b486]: Got error CBLHTTP[401, "unauthorized", http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_local/b3f625c9bddabfb59ee49d78f3bb484a5876b486]
Sync: CBLRestPuller[http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net]: Error fetching last sequence: CBLHTTP[401, "unauthorized", http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_local/b3f625c9bddabfb59ee49d78f3bb484a5876b486]
Sync: CBLRestPuller[http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net] Progress: set error = CBLHTTP[401, "unauthorized", http://Uladzimir-Papkos-iPad.local.:55555/sg_to_firstfoundry_net/_local/b3f625c9bddabfb59ee49d78f3bb484a5876b486]
Could anybody point me to place where I am doing something wrong?
After having conversation with Couchbase engineers it was decided that the best solution here is to enable secure http connection, since it doesn't make sense to send login / password through insecure http request.
The easiest (not most secure) way to enable https is to do next:
// Change url to https
components.scheme = "https"
// Inject self-signed generated on the fly certificate into CBLListener
try listener.setAnonymousSSLIdentityWithLabel("use_any_string_here")
More information about configuring https connection for p2p replication is available here.