Cookie Auth Question

218 views
Skip to first unread message

Michael Mayer

unread,
May 17, 2014, 9:00:48 AM5/17/14
to mobile-c...@googlegroups.com
We are using cookie authentication for the sync gateway from our iOS application.  We have written a custom authentication api that the mobile application calls.  We authenticate the user via Active Directory in our enterprise and authorize them using custom logic.  Once they are authenticated and authorized, our api calls the sync-gateway /db/_session api via the admin port as described in your documentation and we retrieve a session cookie that is sent back to the phone and stored in the NSHTTPCookieStorage.  When the pull and push replicators are started this works fine as long as the replicators are pointed to the admin port, however it does not seem to be working when we point the replicators to the standard interface port.  On the standard interface port we receive a "authentication required" message.  For obvious reasons we do not want to expose the admin port to the world for our mobile devices to connect.  Can you explain how to make this work on the standard port?  


I noticed this quote on your Sync Gateway documentation page.   Is this my issue?

Subsequent client requests to the gateway will now include the session in a cookie, which the gateway will recognize. For the cookie to be recognized, your site must be configured so that your app’s API and the gateway appear on the same public host name and port.

J. Chris Anderson

unread,
May 19, 2014, 1:22:16 PM5/19/14
to mobile-c...@googlegroups.com


On Saturday, May 17, 2014 6:00:48 AM UTC-7, Michael Mayer wrote:
We are using cookie authentication for the sync gateway from our iOS application.  We have written a custom authentication api that the mobile application calls.  We authenticate the user via Active Directory in our enterprise and authorize them using custom logic.  Once they are authenticated and authorized, our api calls the sync-gateway /db/_session api via the admin port as described in your documentation and we retrieve a session cookie that is sent back to the phone and stored in the NSHTTPCookieStorage.  When the pull and push replicators are started this works fine as long as the replicators are pointed to the admin port, however it does not seem to be working when we point the replicators to the standard interface port.  On the standard interface port we receive a "authentication required" message.  For obvious reasons we do not want to expose the admin port to the world for our mobile devices to connect.  Can you explain how to make this work on the standard port?  

In order for the cookie to be used, it must be set from the same origin as the sync connections are going to. So the call from your mobile code to your custom API, should be in a sub-path of the same domain and port as the sync service.

Does that help?
Chris

Michael Mayer

unread,
May 19, 2014, 2:20:08 PM5/19/14
to mobile-c...@googlegroups.com
So if I understand you correctly, 

If my sync-gateway were on https://sg.somedomain.com:4984, my authorization API would have to be on something like https://sg.somedomain.com:4984/auth?

Traun Leyden

unread,
May 19, 2014, 5:27:15 PM5/19/14
to mobile-c...@googlegroups.com
On Mon, May 19, 2014 at 10:22 AM, J. Chris Anderson <jch...@couchbase.com> wrote:


In order for the cookie to be used, it must be set from the same origin as the sync connections are going to. So the call from your mobile code to your custom API, should be in a sub-path of the same domain and port as the sync service.



Actually there is now a new native API call that makes the original cookie domain irrelevant.

Here's a diagram that describes the interaction of the various components during a Cookie auth:


In step #7, you would call this API to set the cookie:

    /**
     * Sets an HTTP cookie for the Replication.
     *
     * @param name The name of the cookie.
     * @param value The value of the cookie.
     * @param path The path attribute of the cookie.  If null or empty, will use remote.getPath()
     * @param expirationDate The expiration date of the cookie.
     * @param secure Whether the cookie should only be sent using a secure protocol (e.g. HTTPS).
     * @param httpOnly (ignored) Whether the cookie should only be used when transmitting HTTP, or HTTPS, requests thus restricting access from other, non-HTTP APIs.
     */
    @InterfaceAudience.Public
    public void setCookie(String name, String value, String path, Date expirationDate, boolean secure, boolean httpOnly) {
    }

and the cookie domain will be set to the domain of the sync gateway, no matter what your domain of your webapp is:

    cookie.setDomain(syncGatewayURL.getHost());



Michael Mayer

unread,
May 19, 2014, 5:54:39 PM5/19/14
to mobile-c...@googlegroups.com
What you describe is what I have been trying to accomplish.  My step #7 looks like this, where responseObject is a json object I get back from the webapp with the cookie obtained by posting to the admin port of the sync gateway.

NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys:
[self dbUrl], NSHTTPCookieDomain,
[[self database] name], NSHTTPCookiePath,
[responseObject valueForKey:@"cookie_name"], NSHTTPCookieName,
[responseObject valueForKey:@"session_id"], NSHTTPCookieValue,
[responseObject valueForKey:@"expires" ], NSHTTPCookieExpires,
nil];
NSHTTPCookie *syncCookie = [NSHTTPCookie cookieWithProperties:properties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:syncCookie];


I guess I was thinking storing the cookie in the sharedHTTPCookieStorage would cause the replicators to automatically use it for authentication.  I have not found an iOS API to specify the cookie to be used for authentication by the replicators.  Am I missing something?

Traun Leyden

unread,
May 19, 2014, 8:30:31 PM5/19/14
to mobile-c...@googlegroups.com

If you are using [NSHTTPCookieStorage sharedHTTPCookieStorage], then what Chris says does apply.

But if you use this method, you shouldn't need to care about the origin of the cookie:

/** Adds a cookie to the shared NSHTTPCookieStorage that will be sent to the remote server. This

    is useful if you've obtained a session cookie through some external means and need to tell the

    replicator to send it for authentication purposes.

    This method constructs an NSHTTPCookie from the given parameters, as well as the remote server

    URL's host, port and path.

    If you already have an NSHTTPCookie object for the remote server, you can simply add it to the

    sharedHTTPCookieStorage yourself. 

    If you have a "Set-Cookie:" response header, you can use NSHTTPCookie's class methods to parse

    it to a cookie object, then add it to the sharedHTTPCookieStorage. */

- (void) setCookieNamed: (NSString*)name

              withValue: (NSString*)value

                   path: (NSString*)path

         expirationDate: (NSDate*)expirationDate

                 secure: (BOOL)secure;


I don't know the exact version of the code where this was added, but if you update to the latest version on the master branch you should be able to call this method.





--
You received this message because you are subscribed to the Google Groups "Couchbase Mobile" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mobile-couchba...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/mobile-couchbase/57bd3964-22e7-4184-b4ad-cceab1916286%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages