Problem with basic authentication in iOS

I try to set a basic authentication. When I set simple password push replication works great.

			let pass : String = CouchbaseDatabaseUtils.passwordForServiceName(NetService.nameAndId())
			let user : String = NetService.serviceUserName()
			list.setPasswords([user : pass])

The problem i when my password generator provides string with special characters that is eg. “/” -> "%2f"
special characters

eg. for password “/K+afvYTNVgjKxnxBotMjZJD/V7uL2jOwVEChL1wa9Y=” I get “http://username:%2FK+afvYTNVgjKxnxBotMjZJD%2FV7uL2jOwVEChL1wa9Y=@192.168.110.89:50293/test_db

No matter how hard I try, either via replication authenticator property or putting user and password inside of the url, replication does not work. What is the most strange is that when I set password in the listener with a encoded form it works. I is unexceptable solution becouse I have to deal with Android as well from which pushes works as expected. So my conclusion is that iOS implementation wants to compare stored password "/K+afvYT… with encoded “%2FK+afvYT…” while it should know that incoming connection is encoded and decode incoming or encode stored and then make comparisation.

Anyone had similar issue?

Putting passwords in URLs is discouraged. It’s better to use an Authenticator instead.

Thanks for response. Yes, I know, I tried this method at first but with no success. I’m not sure now but I think it was working with saved encoded version of the password. That’s lead me to the conclusion that there is something wrong with passwords comparison,

Try the Authenticator again and post your problem, if you still have one.

Still nothing. Have a look

let user = "USER"
let pass = "/K+afvYTNVgjKxnxBotMjZJD/V7uL2jOwVEChL1wa9Y="
let suncUrl = http://192.168.110.89:51443/test_db

let push = database.createPushReplication(syncUrl)
push.authenticator = CBLAuthenticator.basicAuthenticator(withName: user, password: pass)
push.continuous = true;
push.start()

and I get

Optional(Error Domain=CBLHTTP Code=401 “unauthorized” UserInfo={NSLocalizedDescription=unauthorized, NSErrorFailingURLKey=http://192.168.110.89:51443/test_db/_revs_diff, AuthChallenge={
Scheme = Digest;
“WWW-Authenticate” = “Digest realm=“CouchbaseLite”, qop=“auth”, nonce=“1700F8B8-FA39-49EA-9819-2E9018800C3B””;
realm = CouchbaseLite;
}, NSLocalizedFailureReason=unauthorized})

What am I doing wrong?

What are you replicating with?

I am generating database like that

class fileprivate func generateDefaultDatabase() -> CBLDatabase? {
	do {
		let manager = CBLManager.sharedInstance()
		return try manager.databaseNamed(defaultDatabaseName)

	} catch {
		print("error when creating database named \(defaultDatabaseName)")
	}
	return nil
}

later on I fire a listener like that

fileprivate func startListener(authentication: Bool) -> Bool {

	let list = CBLListener.init(manager: CBLManager.sharedInstance(), port: 21700)
	if authentication == true {
		list.requiresAuth = true
		let pass: String = CouchbaseDatabaseUtils.passwordForServiceName(NetService.nameAndId())
		let user: String = NetService.serviceUserName()
		list.setPasswords([user: pass])
	}

	do {
		try list.start()
	} catch {
		print("unable to start syncing, already started?")
		ViewController.showOkAlert(message: "unable to start syncing, already started?")
		return false
	}

	self.listener = list
	return true
}

And i finally on the other device I create database in the same way and then start replication as described in the previous post.

I found an existing issue that’s the same as what you’re getting. Look at the later comments for the explanation — in short, the replicator won’t use Basic auth over plain HTTP for security reasons, so it uses Digest instead, but the Listener component doesn’t handle digest auth.

The workaround is to enable SSL in the listener (which is a good idea anyway.) See the issue for instructions.

Thanks for reply. I’ll check the solution with self signed certificate.