-
Notifications
You must be signed in to change notification settings - Fork 352
Details
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.
- 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
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]
- 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
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.
Issues
Samples (with nuget references) from the repo separated for faster development:
https://github.com/moljac/Xamarin.Auth.Samples.NugetReferences/
https://forums.xamarin.com/search?search=auth
https://forums.xamarin.com/search?search=xamarin.auth
http://stackoverflow.com/search?q=xamarin.auth
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 flow (process) is setup in 4 major steps:
-
Server side setup for OAuth service provider
To name some:
-
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.
-
Facebook
-
Microsoft
-
Fitbit
Fitbit is good for testing, because it allows arbitrary values for redirect_url.
-
-
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)
-
Creating and optionally customising UI
-
Presenting/Launching UI and authenticating user
-
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. -
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
-
Triggering Events based on OAuth data
Parsing subsytem of the Authenticator will parse OAuth data and raise appropriate events based on returned data
-
-
Using identity
-
Using protected resources (making calls)
-
Saving account info
-
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 covers 2 Xamarin technologies - traditional/standard (Xamarin.Android, Xamarin.iOS) and Xamarin.Forms. The library implements nuget "bait and switch" technology.
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.
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:
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]
In order to receive OAuth events Authenticator object must subscribe to the events.
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.
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:
// Step 2.1 Creating Login UI
Android.Content.Intent ui_object = Auth1.GetUI(this);
[TODO Link to code]
On iOS:
// 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
// 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
// Step 2.1 Creating Login UI
System.Type page_type = auth.GetUI();
[TODO Link to code]
On Windows Phone Silverlight 8.x
// Step 2.1 Creating Login UI
System.Uri uri = auth.GetUI ();
[TODO Link to code]
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
[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.
[TODO Link to code]
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
// Step 3 Present/Launch the Login UI
StartActivity(ui_object);
Xamarin.iOS
// Step 3 Present/Launch the Login UI
PresentViewController(ui_object, true, null);
Windows - Universal Windows Platform
this.Frame.Navigate(page_type, auth);
[TODO Link to code]
Windows - WinRT - Windows Store 8.1 Windows Phone 8.1
this.Frame.Navigate(page_type, auth);
[TODO Link to code]
Windows Phone Silverlight 8.x
this.NavigationService.Navigate(uri);
[TODO Link to code]
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:
-
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. -
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
-
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 theAppDelegate
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 toActivity
'sOnCreate()
and/orAppDelegate
'sOpenUrl()
.
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:
[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):
<activity android:label="ActivityCustomUrlSchemeInterceptor" android:name="md5f8c707217af032b51f5ca5f983d46c8c.ActivityCustomUrlSchemeInterceptor">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="localhost" />
<data android:scheme="xamarinauth" />
<data android:scheme="xamarin-auth" />
<data android:scheme="xamarin.auth" />
</intent-filter>
</activity>
[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:
<!--
Info.plist
-->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Xamarin.Auth Google OAuth</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.xamarin.traditional.standard.samples.oauth.providers.ios</string>
<string>com.googleusercontent.apps.1093596514437-cajdhnien8cpenof8rrdlphdrboo56jh</string>
</array>
<key>CFBundleURLTypes</key>
<string>Viewer</string>
</dict>
</array>
[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:
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]
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
https://developer.chrome.com/multidevice/android/customtabs
Xamarin.Auth can be used (installed) through
- nuget package v >= 1.4.0.0
- project reference (source code)
NOTE: Xamarin Component for new nuget is not ready! 2017-03-28
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):
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 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
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!
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.
Some screenshots assembled with PlaceIt.