Xamarin Forms - Quick and Dirty Cookies Access (iOS and Android)
Cross-platform Cookie Access on iOS and Android in Xamarin Forms
On one of my previous gigs I was building a Xamarin Forms app targeting iOS and Android, and needed to be able to access an OAuth-based cookie obtained from a WebView-based login flow.
The cookie in question needed to be attached to some pseudo-REST-based HTTP requests (made using the standard .NET HttpClient
) to GET and POST data to an ASP.NET Web API serviced back-end system.
In order to maximise the cross-platform availability (and testability) of the library making those requests, it was built as a portable class library (PCL).
And because it needed to be xplat, there was no way to directly access the iOS and Android platform-specific Cookie managers.
On both iOS and Android, both platforms have a shared “Cookie Store” which is used by web browsers installed on the device. This includes the Xamarin Forms xplat WebView
implementation, since this is just a cross-platform “placeholder” for the native web view’s custom renderer. So if the native browser has stored a cookie, the WebView can pick it up, and vice versa.
The good news is that the platspec cookie managers are easily exposed on both iOS and Android platforms (on iOS it’s a static instance of NSHttpCookieStorage.SharedStorage.Cookies
and on Android it’s a static instance of Android.WebKit.CookieManager
). More importantly they don’t even need a WebView for you to be able to get at the device’s cookies.
This means it’s really easy to provide a cross-platform solution using dependency injection.
What Can It Do?
My use case was pretty simple:
- read the cookie(s) for a site I had logged in with,
- extract the oauth-related one(s) I needed,
- use them in the
HttpClient
headers to auth my requests with the back-end
- use them in the
- delete those cookie(s) when done, from the cookie manager (to enforce a log-out function)
The rest of this post only deals with the methods I required, but I think in most cases that will suit your requirements too. And there’s ample documentation on how to use the respective cookie managers, should you need to expand your functionality.
The Cross-Platform (‘Shared’) Interface
In order to be able to pass the platspec instance of the cookie manager down to the cross-platform PCL (which actually uses it), I need to use a dependency injection. I used Splat for this, because it’s awesome, but obviously you can use whichever DI container you’re most comfortable with.
I created a shared IPlatformCookieStore
interface which I can then use to register the actual platspec cookie manager instance in my DI container’s registry. The interface looks like this:
Pretty straightforward: Give me a list of the current cookies. Let me dump all the cookies to a log so I can see what’s in them. And let me delete cookies from the platspec instance.
Then, a quick and dirty wrapper class with those interfaced methods wrapped around the iOS Cookie Manager (NSHttpCookieStorage.SharedStorage.Cookies
).:
IOSCookieStore Implementation
The LogDebug
method is just abstract I’ve created here for demo purposes, this could just as easily point to your logging library instance, or something like Console.WriteLine()
.
DroidCookieStore Implementation
Registering and Using the Cookie Store
Now we add our shared IPlatformCookieStore
to our DI container’s registry (as I mentioned earlier, I use Splat, but you can use whatever you like).
iOS
In my iOS project’s AppDelegate, in the FinishedLaunching
method:
Locator
is just my static Splat DI instance
Android
In my Android project’s MainActivity, in the OnCreate
method:
Note that the constructor for the DroidCookieStore
requires a website base URL for proper initialisation
Wrapping Up
Now all that remains is to access your platspec cookie store from your shared cross-platform code by interacting with the instance you registered with your DI container.
How and where you use it will depend on your implementation. A simple (contrived) solution can be done something like the code below (NB: I’ve not compiled the class below, but the intent should be clear):
Another option is to inherit from the xplat WebView
control in Xamarin Forms, and add an IPlatformCookieStore
object to it. You can then go hunting for your cookies whenever (for example) the WebView.OnNavigated
or OnNavigating
methods fire.
So where is it?
The source code is on GitHub as a gist, at https://gist.github.com/wislon/260438ee77e8de9e4ffc. I haven’t had time to pull all the bits together into a buildable, standalone project, but this will definitely be enough to get you going.
License
The code in this gist/repo is released under the free-for-all MIT License, so if you want to copy it and do better stuff with it, go right ahead! :)