best practice or keeping sessions alive for several days

88 views
Skip to first unread message

Seung Chan Lim

unread,
Jul 22, 2014, 4:47:27 PM7/22/14
to mobile-c...@googlegroups.com
I want my users to be able to take advantage of offline use of the app. The only way to authenticate them is through the sync gateway, which requires that they're online. So I can have them authenticate once while they're online, then keep the session cookie cached and use it to replicate whenever they go online. So far so good.

The question is, what's the best practice to doing this over a long duration of time? What if they're offline for days?

Do I keep their userid/password stored on the app locally and re-authenticate on their behalf every 24 hours (assumed expiration date of these session cookies)

slim

Jens Alfke

unread,
Jul 22, 2014, 5:23:05 PM7/22/14
to mobile-c...@googlegroups.com
On Jul 22, 2014, at 1:47 PM, Seung Chan Lim <djs...@gmail.com> wrote:

The question is, what's the best practice to doing this over a long duration of time? What if they're offline for days?

They might need to re-authenticate, if you’re using cookies and the delay is longer than the session lifetime.

Do I keep their userid/password stored on the app locally and re-authenticate on their behalf every 24 hours (assumed expiration date of these session cookies)

Why not just authenticate using HTTP auth? Then  you don’t have to worry about session cookies at all.

—Jens

Seung Chan Lim

unread,
Jul 23, 2014, 12:49:40 PM7/23/14
to mobile-c...@googlegroups.com
You mean on each and every http request (i.e. push replication), embed the user's id and plain text password in the URL and let SSL encrypt it to lower the possibility of a man-in-the-middle attack?

slim

Jens Alfke

unread,
Jul 23, 2014, 1:00:09 PM7/23/14
to mobile-c...@googlegroups.com

On Jul 23, 2014, at 9:49 AM, Seung Chan Lim <djs...@gmail.com> wrote:

You mean on each and every http request (i.e. push replication), embed the user's id and plain text password in the URL 

Well, it doesn’t go in the URL, it goes in a WWW-Authenticate: header.

This is the authentication the replicator uses by default. All you have to do is give it the username/password using a CBLAuthenticator. Or you can store the credentials in the Keychain and the replicator will automatically use them. (This is preferable because the credentials get stored very securely and don’t have to be re-entered by the user.)

and let SSL encrypt it to lower the possibility of a man-in-the-middle attack?

Yes, you definitely don’t want to use basic auth without SSL.

—Jens

Seung Chan Lim

unread,
Jul 23, 2014, 1:35:18 PM7/23/14
to mobile-c...@googlegroups.com
I'm on phone gap / iOS.

I can see how I can send in the WWW-Authenticate header, but what would I need to do do take advantage of the keychain? I guess I'm looking for a plugin for that? (i.e. https://github.com/shazron/KeychainPlugin )

How does the replicator _automatically_ to take advantage of the keychain? (i've never used the keychain feature on iOS)

slim

Jens Alfke

unread,
Jul 23, 2014, 3:41:48 PM7/23/14
to mobile-c...@googlegroups.com
On Jul 23, 2014, at 10:35 AM, Seung Chan Lim <djs...@gmail.com> wrote:

I'm on phone gap / iOS.

Oh right, that makes things a bit different. So you’re sending a POST to /_replicate. The simplest way is to insert the username (and optionally the password) into the remote db URL:
{"source":"https://myusername:mypassword@example.net:4984/db", "target":"local-db"}

I can see how I can send in the WWW-Authenticate header, but what would I need to do do take advantage of the keychain? I guess I'm looking for a plugin for that? (i.e. https://github.com/shazron/KeychainPlugin )

That plugin looks ideal. What you do is add an Internet password entry for the base remote URL (https://example.net:4984/db in the example) and realm "Couchbase Sync Gateway”. Then you don’t need to put the password (or username, really) in the replication URL anymore.

How does the replicator _automatically_ to take advantage of the keychain? (i've never used the keychain feature on iOS)

If it gets a 401 status in a response, it asks the Keychain for credentials for that URL. If it finds a username/password, it’ll retry with those. (Web browsers do exactly the same thing.)

—Jens

Seung Chan Lim

unread,
Jul 25, 2014, 7:49:57 PM7/25/14
to mobile-c...@googlegroups.com
I'm trying to figure out what exactly "add internet password entry" translates to for this keychain plugin. 

Are you referring to this:

If so, that seems to be a higher-level feature available for iOS.

The plugin uses a lower-level API to simply set/get "key" & "value" pairs for a given "service" (i.e. just 3 parameters)

My guess is that there has to be some kind of spec that denotes what keys are being stored to populate the various values to denote an "internet password."

Are you familiar with such a documentation?

I'm looking around, but can't find it. Will keep searching.

slim

Jens Alfke

unread,
Jul 25, 2014, 9:05:31 PM7/25/14
to mobile-c...@googlegroups.com

On Jul 25, 2014, at 4:49 PM, Seung Chan Lim <djs...@gmail.com> wrote:

The plugin uses a lower-level API to simply set/get "key" & "value" pairs for a given "service" (i.e. just 3 parameters)

I’m not familiar with that plugin, only with the Cocoa APIs (NSURLCredential, NSURLProtectionSpace, etc.) Sorry.

—Jens

Seung Chan Lim

unread,
Aug 2, 2014, 1:48:11 PM8/2/14
to mobile-c...@googlegroups.com
Hi Jens,

You said:

> What you do is add an Internet password entry for the base remote URL (https://example.net:4984/db in the example) and realm "Couchbase Sync Gateway”. Then you don’t need to put the password (or username, really) in the replication URL anymore.

What iOS API do you use to achieve this? I'm trying to find out how I can do this within phonegap, but I need to know what needs to happens at a lower level.


slim

Jens Alfke

unread,
Aug 2, 2014, 3:11:37 PM8/2/14
to mobile-c...@googlegroups.com

On Aug 2, 2014, at 10:48 AM, Seung Chan Lim <djs...@gmail.com> wrote:

What iOS API do you use to achieve this? I'm trying to find out how I can do this within phonegap, but I need to know what needs to happens at a lower level.

Set CBLReplication.credential, using an NSURLCredential with permanent persistence. If you look at the implementation of this  you’ll see it’s storing it into the NSURLCredentialStore, which is basically a wrapper around the Keychain.

There was a thread here earlier within the past week(?) about a PhoneGap plugin for accessing the Keychain directly.

—Jens

Seung Chan Lim

unread,
Aug 3, 2014, 5:54:43 PM8/3/14
to mobile-c...@googlegroups.com
Are you referring to this link I posted in this thread? 

https://github.com/shazron/KeychainPlugin

I'm trying to figure out if I can "set CBLReplication.credential, using an NSURLCredential with permanent persistence." using this plugin or if I need something else.

Do you have sample iOS code I can show the plugin developer so I can ask the question? (I have 0 knowledge of the iOS native API or objective-C)

slim

Jens Alfke

unread,
Aug 3, 2014, 7:11:41 PM8/3/14
to mobile-c...@googlegroups.com

On Aug 3, 2014, at 2:54 PM, Seung Chan Lim <djs...@gmail.com> wrote:

Do you have sample iOS code I can show the plugin developer so I can ask the question? (I have 0 knowledge of the iOS native API or objective-C)

Just ask (or look up) how to use the plugin to add a keychain item for an HTTP auth password. You’ll need to provide a URL, username, password and “realm” string matching the one the server sends (which for the Sync Gateway is “Couchbase Sync Gateway”.)

—Jens

Seung Chan Lim

unread,
Aug 4, 2014, 12:10:57 AM8/4/14
to mobile-c...@googlegroups.com
I think I'm missing a lot of context here to understand what this all means.

So let's say I can use the keychain plugin to set certain key/value pairs. (That's really all I can do with the plugin. Nothing fancy.)

Am I correct in assuming that as long as I set the "right" key/value pairs, simply calling https://lite.couchbase./db/_replicate the code underlying it will magically retrieve the username and password combo from the keychain and put it in the WWW-Authenticate header?

Do I have to manually do the equivalent of "set CBLReplication.credential" on phone gap? (Not sure if such a feature exists)

slim

Jens Alfke

unread,
Aug 4, 2014, 12:57:18 AM8/4/14
to mobile-c...@googlegroups.com

> On Aug 3, 2014, at 9:10 PM, Seung Chan Lim <djs...@gmail.com> wrote:
>
> Am I correct in assuming that as long as I set the "right" key/value pairs, simply calling https://lite.couchbase./db/_replicate the code underlying it will magically retrieve the username and password combo from the keychain and put it in the WWW-Authenticate header?

Yes. NSURLConnection, the Cocoa class that handles HTTP requests, knows how to look up credentials in the keychain.

--Jens

Seung Chan Lim

unread,
Aug 5, 2014, 11:03:23 PM8/5/14
to mobile-c...@googlegroups.com
What function do you call to do this:

"an HTTP auth password. You’ll need to provide a URL, username, password and “realm” string matching the one the server sends (which for the Sync Gateway is “Couchbase Sync Gateway”.)"

Do you use SecKeychainAddInternetPassword?

slim

Seung Chan Lim

unread,
Aug 6, 2014, 12:24:18 AM8/6/14
to mobile-c...@googlegroups.com
The following is a response from a friend



-----------------------
The Keychain Services API models keychain "items" as key-value dictionaries that you create/update/query/delete with a small number of functions and a large number of constants that define the keys you use to make up the dictionaries.

So, looking more closely at that KeychainPlugin source code, it obscures this by wrapping "SFHFKeychainUtils" which in turn wraps that actual Keychain Services API.

It looks like if you call in Javascript:

   setForKey(key, serviceName, value)

That turns into a call to

   [SFHFKeychainUtils storeUsername:key andPassword:value forServiceName:serviceName updateExisting:YES error:&error];

Which in turn calls:

   SecKeychainAddGenericPassword(NULL, serviceName, username, password, NULL)

I'm not 100% certain, but I think that won't help you, because NSURLCredentialStorage is going to be looking for items created with `SecKeychainAddInternetPassword` (or, more accurately, items with the key-value pairs that are created by that function). Specifically, instead of "service name" which is an arbitrary string, the Internet password function lets you specify a hostname, port, etc. that NSURLConnection uses to look for a match.

<https://developer.apple.com/library/mac/documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898-CH1g-BCICBIHF>

So, I think that particular plugin is only useful for reading/writing a name password pair exclusively in your own code.
Reply all
Reply to author
Forward
0 new messages