# Details
[![Components-XamarinAuth][7]][8]
[7]: https://jenkins.mono-project.com/view/Components/job/Components-XamarinAuth/badge/icon
[8]: https://jenkins.mono-project.com/view/Components/job/Components-XamarinAuth
Xamarin.Auth helps developers authenticate users via standard authentication mechanisms
(e.g. OAuth 1.0 and 2.0), and store user credentials. It's also straightforward to add
support for non-standard authentication schemes.
## Current version and status
* nuget version 1.5.0
* Native UI (CustomTabs on Android and SFSafariViewController on iOS)
* Xamarin.Forms support
* Xamarin.Android (tested)
* Xamarin.iOS (tested)
* Windows platforms (tests in progress)
* Xamarin.iOS Embedded Browser WKWebView support as alternative
WKWebView instead of UIWebView
[Change Log](./details/change-log.md)
### Status
CI servers:
* MacOSX builds
https://jenkins.mono-project.com/view/Components/job/Components-XamarinAuth/
* Windows builds
https://jenkins.mono-project.com/view/Components/job/Components-XamarinAuth-Windows/
Xamarin.Auth has grown into fully fledged cross platform library supporting:
* Xamarin.Android
* Xamarin.iOS (Unified only, Classic Support is removed)
* Windows Phone Silverlight 8 (8.1 redundant)
* Windows Store 8.1 WinRT
* Windows Phone 8.1 WinRT
* Universal Windows Platform (UWP)
The library is cross-platform, so once user learns how to use it on one platform,
it is fairly simple to use it on other platforms.
Recent changes in Xamarin.Auth brought in new functionalities which caused minor
breaking changes. Version 1.4.x broke `GetUI()` API, because it returned `System.Object`
instead of `Intent` on Android and `UIViewController` on iOS. Efforts to add Xamarin.Forms
support led to more refactoring and pushing functionality deeper into Xamarin.Auth, so
version 1.5.0 reverted `GetUI()` API to original flavor returning UI object for each
platform.
So, in version 1.5.0 `GetUI()` returns
* on Android:
* `Android.Content.Intent` for embedded WebViews and NativeUI
* on iOS:
* `UIKit.UIViewController` for embedded WebViews and
* `SafariServices.SFSafariViewController` for Native UI
[TODO API design and breaking changes]
## Work in progress and plans
* Xamarin.Forms Windows support
* more samples
* Azure AD B2C
* Azure ADAL
* Flickr
* restructuring samples
* UserAgent API
[DEPRECATED] [NOT RECOMMENDED] ToS violations
workaround for attempts to fake UserAgent for Embedded Browsers to fool
Google
## Support
If there is need for real-time support use Xamarin Chat (community slack team) and go to
\#xamarin-auth-social channel where help from experienced users can be obtained.
For all users without account for community slack team, please, go to self-invite link
first.
### Documentation - Github Wiki pages
### Github
Issues
Samples (with nuget references) from the repo separated for faster development:
https://github.com/moljac/Xamarin.Auth.Samples.NugetReferences/
### Xamarin Forums
https://forums.xamarin.com/search?search=auth
https://forums.xamarin.com/search?search=xamarin.auth
### Stackoverflow
http://stackoverflow.com/search?q=xamarin.auth
### Xamarin Chat - Community Slack Team (xamarin-auth-social room)
For those that need real-time help (hand-in-hand leading through implementation) the
best option is to use community slack channel. There are numerous people that have
implemented Xamarin.Auth with Native UI and maintainers/developers of the library.
https://xamarinchat.slack.com/messages/C4TD1NHPT/
For those without Xamarin Chat account please visit this page and generate
self-invitation:
https://xamarinchat.herokuapp.com/
## OAuth
OAuth flow (process) is setup in 4 major steps:
0. **Server side setup for OAuth service provider**
To name some:
1. Google
Google introduced mandatory use of Native UI for security reasons because
Android CustomTabs and iOS SFSafariViewController are based on Chrome and
Safari code-bases thus thoroughly tested and regulary updated. Moreover
Native UI (System Browsers) have reduced API, so malicious users have less
possibilities to retrieve and use sensitive data.
[Google](./details/setup-server-side-oauth-providers/google.md)
2. Facebook
[Facebook](./details/setup-server-side-oauth-providers/facebook.md)
3. Microsoft
[Microsoft](./details/setup-server-side-oauth-providers/microsoft.md)
4. Fitbit
Fitbit is good for testing, because it allows arbitrary values for
redirect_url.
[Fitbit](./details/setup-server-side-oauth-providers/fitbit.md)
5.
1. **Client side initialization of Authenticator object**
This step prepares all relevant OAuth Data in Authenticator object (client_id,
redirect_url, client_secret, OAuth provider's endpoints etc)
2. **Creating and optionally customising UI**
3. **Presenting/Launching UI and authenticating user**
1. Detecting/Fetching/Intercepting URL change - redirect_url and
This substep, often called "App Linking" or "Deep Linking", is needed for
NativeUI and requires a custom scheme registration for the redirect_url
intercepting mechanism.
2. Parsing OAuth data from redirect_url
In order to obtain OAuth data returned redirect_url must be parsed and the
best way is to let Xamarin.Auth do it automatically by parsing redirect_url
3. Triggering Events based on OAuth data
Parsing subsytem of the Authenticator will parse OAuth data and raise
appropriate events based on returned data
4. **Using identity**
1. Using protected resources (making calls)
2. Saving account info
3. Retrieving account info
Xamarin.Auth with Embedded Browser API does a lot under the hood for users, but with
the Native UI step 3.1 Deep Linking (App linking) must be manually implemented by the
user.
## Xamarin.Auth usage
Xamarin.Auth covers 2 Xamarin technologies - traditional/standard (Xamarin.Android,
Xamarin.iOS) and Xamarin.Forms. The library implements nuget "bait and switch"
technology.
### Usage Xamarin Traditional (Standard)
Design of the library is aimed to reduce platform differences, but this is not possible
in all cases (most methods in Android API need Context as a parameter), so user must
be familiar with platform concepts and details.
#### 1. Initialization
##### 1.1 Creating and configuring an Authenticator
The server side setup of the OAuth provider defines OAuth flow used which again
defines which Authenticator constructor will be used.
This code is shared accross all platforms:
```csharp
OAuth2Authenticator auth = new OAuth2Authenticator
(
clientId: "",
scope: oauth2.OAuth2_Scope,
authorizeUrl: oauth2.OAuth_UriAuthorization,
redirectUrl: oauth2.OAuth_UriCallbackAKARedirect,
// Native UI API switch
// true - NEW Native UI support
// false - OLD Embedded Browser API [DEFAULT]
// DEFAULT will be switched to true in the near future 2017-04
isUsingNativeUI: test_native_ui
)
{
AllowCancel = oauth1.AllowCancel,
};
```
[TODO Link to code]
##### 1.1 Subscribing to Authenticator events
In order to receive OAuth events Authenticator object must subscribe to the
events.
```csharp
Auth1.Completed += Auth_Completed;
Auth1.Error += Auth_Error;
Auth1.BrowsingCompleted += Auth_BrowsingCompleted;
```
[TODO Link to code]
In those events user can close the Login UI or perform further actions, based on
event raised (Completed or Error) and information which can be extracted from
EventArgs.
The Authenticator object has three events:
* Completed - which is fired when an Authentication is successful,
* Error - which is fired if the Authentication fails, and
* BrowsingCompleted which is fired when when the browser window is closed
User will need to subscribe to these event in order to work with the data received
from the authentication response.
#### 2. Creating/Preparing UI
##### 2.1 Creating Login UI
Creating UI step will call `GetUI()` method on Authenticator object which
will return platform specific object to present UI for login.
This code cannot be shared for most of the platforms, because it returns platform
specific objects.
On Android:
```csharp
// Step 2.1 Creating Login UI
Android.Content.Intent ui_object = Auth1.GetUI(this);
```
[TODO Link to code]
On iOS:
```csharp
// Step 2.1 Creating Login UI
UIKit.UIViewController ui_object = Auth1.GetUI();
```
[TODO Link to code]
for new API (both Embedded Browsers and Native UI Support) user will need to
cast object to appropriate type:
NOTE: there is still discussion about API and returning object, so
this might be subject to change.
NOTE:
Windows platforms currently do NOT support Native UI embedded browser support
only. Work in progress.
On Windows - Universal Windows Platform
```csharp
// Step 2.1 Creating Login UI
Type page_type = auth.GetUI();
this.Frame.Navigate(page_type, auth);
```
[TODO Link to code]
On Windows - WinRT - Windows Store 8.1 and Windows Phone 8.1
```csharp
// Step 2.1 Creating Login UI
System.Type page_type = auth.GetUI();
```
[TODO Link to code]
On Windows Phone Silverlight 8.x
```csharp
// Step 2.1 Creating Login UI
System.Uri uri = auth.GetUI ();
```
[TODO Link to code]
##### 2.2 Customizing the UI - Native UI [OPTIONAL]
Embedded Browser API has limited API for UI customizations, while
Native UI API is essentially more complex especially on Android.
**Xamarin.Android**
Native UI on Android exposes several objects to the end user which enable UI
customisations like adding menus, toolbars and performance optimisations like
WarmUp (preloading of the browser in the memory) and prefetching (preloading
of the web site before rendering).
Those exposed objects from simpler to more complex:
* CustomTabsIntent object which is enough for simple (basic) launch
of Custom Tabs (System Browser)
* CustomTabsIntent.Builder class which is intended for adding menus,
toolbars, backbuttons and more.
This object is returned by GetUI() on Android
```csharp
```
[TODO Link to code]
[TODO finish API and more info]
**Xamarin.iOS**
Native UI on iOS exposes SFSafariViewController and customizations are performed
through the API of that object.
```csharp
```
[TODO Link to code]
#### 3 Present/Launch the Login UI
This step will open a page of OAuth provider enabling user to enter the
credentials and authenticate.
NOTE: there is still discussion about API and returning object, so
this might be subject to change.
**Xamarin.Android**
```csharp
// Step 3 Present/Launch the Login UI
StartActivity(ui_object);
```
**Xamarin.iOS**
```csharp
// Step 3 Present/Launch the Login UI
PresentViewController(ui_object, true, null);
```
**Windows - Universal Windows Platform**
```csharp
this.Frame.Navigate(page_type, auth);
```
[TODO Link to code]
**Windows - WinRT - Windows Store 8.1 Windows Phone 8.1**
```csharp
this.Frame.Navigate(page_type, auth);
```
[TODO Link to code]
**Windows Phone Silverlight 8.x**
```csharp
this.NavigationService.Navigate(uri);
```
[TODO Link to code]
#### 3.2 Native UI support - Parsing URL fragment data
The main reason for introducing Native UI support for Installed Apps (mobile apps)
is security. Both Android's [Chrome] Custom Tabs and iOS SFSafariViewController
originate from (share the same codebase) the Google's Chrome browser and Apple's
Safari web browser. This codebase is constantly updated and fixed.
Furthemore both Custom Tabs and Safari View Controller have minimal API, so attacking
surface for potential attacker is smaller. Additionally, Custom Tabs have additional
features aimed at increasing performance - faster loading and prefetching.
Due to the fact that, it is impossible to obtain loaded URL from Custom Tab or
Safari View Controller after redirecting to redirect url (callback) in order to
parse OAuth data like auth token, user must use App Linking and custom url schemes
to intercept callback.
This has some repercusions that http and https schemes will not work anymore, because
Android and iOS will open default apps for those schemes and those are built in
browsers (Android Browser and Safari).
NOTE:
Android docs are showing IntentFilters with http and https schema, but after
several attempts to implement this was temporarily abandonded.
iOS will most likely open those URLs in browser, except those that were
registered with some apps based on host (Maps http://maps.google.com,
YouTube http://www.youtube.com/ etc).
Some other schemes like mailto will open on
Android Intent picker to let user choose which Intent/App will handle
scheme
iOS
To enable Native UI support 3 steps are neccessary:
1. add references to external utilities that implement NativeUI usually
nuget packages.
This step is neccessary for Android only, because CustomTabs implementation
is in `Xamarin.Android.Support.CustomTabs` nuget. `SafariServices` are part
of newer iOS operating systems.
2. register custom scheme at OS level
Operating system needs to know which application will open particular custom
url scheme. This concept is called App or Deep Linking. On Android this
registration is done via url handling Activity's IntentFilter and on iOS via
3. implement platform specific code that intercepts redirect_url with custom scheme
On Android Activity handles opening Url with custom scheme and this Activity
was registered at OS level thorugh IntentFilter in step 2. On iOS user is
supposed to implement `OpenUrl` in the `AppDelegate` class.
When browser tries to open Url with custom scheme and the browser itself is not
registered to open that scheme it will raise event on OS level and OS will check
application registrations for that specific scheme. If the application is found
url will be passed to `Activity`'s `OnCreate()` and/or `AppDelegate`'s `OpenUrl()`.
##### Preparing app for the Native UI support
For Android app add Xamarin.Android.Support.CustomTabs package through nuget
package manager.
For iOS apps - NOOP - nothing needs to be done.
Adding URL custom schema intercepting utility for parsing
Next step is to define custome scheme[s] the app can handle.
NOTE:
In the samples
xamarinauth
xamarin-auth
xamarin.auth
shemes are used.
Do NOT use those schemes, because schemes might be opened by Xamarin.Auth
sample app if they were installed (tested before).
Xamarin.Android
Add Activity with IntentFilter to catch/intercept URLs
with user's custom schema:
```csharp
[Activity(Label = "ActivityCustomUrlSchemeInterceptor", NoHistory = true, LaunchMode = LaunchMode.SingleTop)]
[
IntentFilter
(
actions: new[] { Intent.ActionView },
Categories = new[]
{
Intent.CategoryDefault,
Intent.CategoryBrowsable
},
DataSchemes = new[]
{
"com.xamarin.traditional.standard.samples.oauth.providers.android",
/*
"com.googleusercontent.apps.1093596514437-d3rpjj7clslhdg3uv365qpodsl5tq4fn",
"urn:ietf:wg:oauth:2.0:oob",
"urn:ietf:wg:oauth:2.0:oob.auto",
"http://localhost:PORT",
"https://localhost:PORT",
"http://127.0.0.1:PORT",
"https://127.0.0.1:PORT",
"http://[::1]:PORT",
"https://[::1]:PORT",
*/
},
//DataHost = "localhost",
DataPath = "/oauth2redirect"
)
]
public class ActivityCustomUrlSchemeInterceptor : Activity
{
string message;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Convert iOS NSUrl to C#/netxf/BCL System.Uri - common API
Uri uri_netfx = new Uri(uri_android.ToString());
// load redirect_url Page (send it back to Xamarin.Auth)
// for Url parsing and raising Complete or Error events
AuthenticationState.Authenticator.OnPageLoading(uri_netfx);
this.Finish();
return;
}
}
}
```
[TODO Link to code]
IntentFilter attribute will modify AndroidManifest.xml adding following node (user
could have added this node manually to application node):
```
```
[TODO Link to code]
Xamarin.iOS
Register custom schemes to Info.plist by opening editor in Advanced tab
and add schemes in URL types with Role Viewer.
This will result in following Info.plist snippet:
```xml
CFBundleURLTypes
CFBundleURLName
Xamarin.Auth Google OAuth
CFBundleURLSchemes
com.xamarin.traditional.standard.samples.oauth.providers.ios
com.googleusercontent.apps.1093596514437-cajdhnien8cpenof8rrdlphdrboo56jh
CFBundleURLTypes
Viewer
```
[TODO Link to code]
NOTE:
When editing Info.plist take care if it is auto-opened in the generic plist editor.
Generic plist editor shows "CFBundleURLSchemes" as simple "URL Schemes".
If user is using the plist editor to create the values and type in URL Schemes,
it won't convert that to CFBundleURLSchemes.
Switching to the xml editor and user will be able to see the difference.
Add code to intercept opening URL with registered custom scheme by implementing
OpenUrl method override in AppDelegate:
```csharp
public override bool OpenUrl
(
UIApplication application,
NSUrl url,
string sourceApplication,
NSObject annotation
)
{
// Convert iOS NSUrl to C#/netxf/BCL System.Uri - common API
Uri uri_netfx = new Uri(url.AbsoluteString);
// load redirect_url Page (send it back to Xamarin.Auth)
// for Url parsing and raising Complete or Error events
AuthenticationState.Authenticator.OnPageLoading(uri_netfx);
return true;
}
```
[TODO Link to code]
### 4 Using identity
## Xamarin.Forms support
Since version 1.5.0 Xamarin.Auth has built in support for Xamarin.Forms with 2
different implementations:
* with platform specific Presenters (Dependency Service, Dependency Injection)
This implementation has no dependencies on Xamarin.Forms, so it is in Xamarn.Auth
nuget package.
* with Custom Renderers
This implementation dependens on Xamarin.Forms, so it is in separate nuget
package - Xamarn.Auth.XamarinForms
#### More Information
https://developer.chrome.com/multidevice/android/customtabs
## Installing Xamarin.Auth
Xamarin.Auth can be used (installed) through
1. nuget package v >= 1.4.0.0
2. project reference (source code)
NOTE: Xamarin Component for new nuget is not ready! 2017-03-28
### Nuget package
Xamarin.Auth nuget package:
https://www.nuget.org/packages/Xamarin.Auth/
Current Version:
https://www.nuget.org/packages/Xamarin.Auth/1.3.2.7
Xamarin.Auth nuget package specification (nuspec):
### Project reference
For debuging and contributing (bug fixing) contributions Xamarin.Auth can be
used as source code for github repo:
Xamarin.Auth project (and folder structure) is based on Xamarin Components Team
internal rules and recommendations.
Xamarin.Auth Cake script file is slightly modified to enable community members
willing to help to compile Xamarin.Auth from source. Compilation is possible
both on Windows and MacOSX. If working on both platforms Cake script expects
artifacts to be build first on Windows and then on MacOSX, so nuget target
(nuget packaging) will fail if script is executed
#### Installing Cake
Installing Cake is pretty easy:
Windows
Invoke-WebRequest http://cakebuild.net/download/bootstrapper/windows -OutFile build.ps1
.\build.ps1
Mac OSX
curl -Lsfo build.sh http://cakebuild.net/download/bootstrapper/osx
chmod +x ./build.sh && ./build.sh
Linux
curl -Lsfo build.sh http://cakebuild.net/download/bootstrapper/linux
chmod +x ./build.sh && ./build.sh
#### Running Cake to Build Xamarin.Auth targets
Run cake with following command[s] to build libraries and nuget locally.
For nuget run it 1st on Windows and then on Mac (Xamarin build bots do that
and expect artifacts from Windows to be ready before packaging).
Running these targets is important for automatic package restore.
Windows
tools\Cake\Cake.exe --verbosity=diagnostic --target=libs
tools\Cake\Cake.exe --verbosity=diagnostic --target=nuget
tools\Cake\Cake.exe --verbosity=diagnostic --target=samples
Mac OSX
mono tools/Cake/Cake.exe --verbosity=diagnostic --target=libs
mono tools/Cake/Cake.exe --verbosity=diagnostic --target=nuget
Now, samples based on project references are ready to be used!
### Component
Xamarin.Auth Component support is currently under development. It is "empty shell"
component, i.e. component that uses nuget package as dependency and contains only
samples, documentation and artwork.
## Diverse
*Some screenshots assembled with [PlaceIt](http://placeit.breezi.com/).*