The XignSys SDK features three main processes, the registration, the personalization and the authentication. There are also some variations or utility processes, but most of them use one of the three main processes. How a process can be started depends on the type of process.
The registration is an optional feature. Before starting to implement this feature please make sure that the XignIn-Manager you are targeting supports this feature. If the manager supports a registration via the XignSys SDK only two additional requirements must be matched. First, the key material for the manager must be present in the SDK. If you are targeting the official XignSys XignIn-Manager "xign.me" the necessary key material is provided by the SDK itself, for other manager's please refer to the chapter Key material on the topic of how to add additional key material to the SDK. After that only the manager's URL is required to start a registration, for example "https://xign.me" for the official XignSys XignIn-Manager.
The personalization and authentication processes primarily started by scanning an QR code. These QR codes may look alike but their content differ depending on whether the process that should be started is a personalization or an authentication. The chapter QR code describes how these QR codes can be handled. If the user tries to start these processes only from a mobile device (via a mobile web browser or email app) a QR Code can not be displayed. In this case the data are delivered via a Deep-Link with a custom scheme. The chapter Deep-Links describes how these links can be handled. Both the OR code and Deep-Link variant result in a base 64 encoded character sequence called processes initialization data (short pid). These pid must be provided to the SDK in order to start either a personalization or an authentication.
Note: Starting with version 8.2.0 of the XignIn-Manager the QR code contains an App-Link with the necessary data to start these processes. In older versions the QR code did only contain the raw data; version 4.0.0 of the XignSys SDK still supports older QR codes.
Info: Speaking of Deep-Links and App-Links seems to sometimes lead to some confusion about their differences. To clear up this confusion here is our understanding of them: Deep-Links are URLs with some sort of scheme that can be used to trigger an app, for example "my-scheme://path-to-something". App-Links are Deep-Links with either the scheme http or https and no other. Both can be used to trigger an app, but as for App-Links a web resource must exist in case the app is not available or the user chooses to follow the link within a web browser.
The InApp-Authentication is a special case of the normal authentication process and changes the way of how the authentication is started. As the name might suggest the InApp-Authentication can be started from within the app and does not need an external trigger. To start an InApp-Authentication a service configuration is needed. If you want to implement this feature, please refer to the chapter InApp-Authentication.
Finally, utility processes, for example change pin, add factor or request new activation, can be started directly from within the app. The only requirement is that the SDK is activated for the XignIn-Manager you are targeting (i.e., a personalization process for the XignIn-Manager was successfully completed by the user). Please refer to the chapter Utility processes on how they are started and work.
As for a XignIn-Manager with version 8.2.0 and upwards a XignSys QR Code contains an App-Link. This offers two possibilities to handle these QR codes. Firstly, a view can be provided within the app that allows the user to scan a QR code. Secondly, the app can be registered to receive the App-Link within the system. To offer the best user experience it is recommended to implement both options.
To offer the first option, a QR Code scanner view must be implemented. However, the XignSys SDK does not provide any views. To achieve this goal nevertheless, on the iOS platform Apples AVCaptureDevice API can be used. As for Android platforms, the Android SDK sadly does not offer a QR Code scanner API. Fortunately, third party libraries such as ZXing ("zebra crossing") exist.
Example implementations for both platforms are available in the XignSys SDK Demo application: iOS
ScannerView
and
Android ScannerSheetFragment
. Please note that these implementations are only for demonstration purposes and therefore do not handle all error
cases. The result of the scanner should be a URL such
as https://xign.me/in-app/process/init?action=authentication&pid=CgMy...0M1o=. This URL can directly be passed to
XignCommon.parseProcessInitializationData(data:) for parsing. The result of this function is an instance
of ProcessInitializationData, which is discussed later on in the
chapter Parsing of the Process Initialization Data.
Note: The domain of the App-Link depends on the XignIn-Manager that is targeted. It is always the same domain as the manager's front end.
To offer the second option on both platforms, an app can be registered within the system to handle App-Links. If that is done the user can scan the QR Code with the system camera (if it offers native QR Code support) or third party QR Code Scanner apps and will be promoted with an option to open the app directly.
However, in case the app is not installed on the system, the user is redirected to a fallback web page of the XignIn-Manager. This fallback page offers the user two choices. On the one hand, a link to the corresponding app in the respective store is presented, which the user can follow to install the app. On the other hand, a Deep-Link that can only be processed by the app can be used, in case the user was somehow redirected to the fallback page even if app is available on the system. That said, handling the Deep-Link directly without sending the user to the fallback page is recommended and is discussed in the next chapter Deep-Links.
To support App-Link handling on the iOS platform two configurations must be made. Unfortunately, one of them must be
done on the XignIn-Manager, therefore this can only be realised directly for on-premise XignIn-Manager installations. If
a new app should be registered on a XignIn-Manager managed by the XignSys GmbH, for example https://xign.me, you need
to contact us for that matter. Nevertheless, the following parts describe the changes that have to be done.
Firstly, as for the server side, the apple-app-site-association file provided by the XignIn-Manager must be updated.
Within this file an entry must be added which declares the app and the paths it can accept. The appIDs specify the
application identifiers for the apps. The format <Application Identifier Prefix>.<Bundle Identifier> is used for the
values in these keys. The following examples shows an apple-app-site-association that is configured for the XignSys
SDK Demo application:
JSON
{
"applinks": {
"details": [
{
"appIDs": [
"237V2SWQHT.com.xignsys.XignsysIosSdkDemo"
],
"components": [
{
"/": "/in-app/process/*",
"comment": "Used to start a process within the app, e.g. an authentication."
}
]
}
]
}
}
Note: For more information about app link handling, please consult the official documentation Supporting Associated Domains from Apple.
Secondly, the app needs to declare an entitlement to handle associated domains. This can be realised by adding the
key com.apple.developer.associated-domains and its associated values, an array of strings with the App-Links that
should be handled, to the .entitlements file of the app. The following example shows an entitlements file which
declares the handling of App-Links for the official XignSys XignIn-Manager.
XML
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:xign.me</string>
</array>
</dict>
</plist>
In the app the App-Link can then be received within the functions scene(:continue:)
and scene(:willConnectTo:options:) of the UIWindowSceneDelegate for SwiftUI applications. For applications not
utilizing SwiftUi the entry points change. Please consult the official Apple documentation
Supporting Universal Links in Your App
for that matter. The received URL from these functions can be passed
to MobileRedirectHelper.parseData(customUrl:customSchemes:hosts:) for evaluation. The function of
the MobileRedirectHelper is discussed in the chapter MobileRedirectHelper.
In order to receive App-Links within Android apps only one configuration is mandatory. An IntentFilter must be
registered for an Activity that receives the App-Link within the Android Manifest file. The following example shows
the registration of such a filter for App-Links created by the official XignSys XignIn-Manager.
XML
<activity android:name="your.package.YourActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:host="xign.me"
android:pathPrefix="/in-app/process/"
android:scheme="https"/>
</intent-filter>
</activity>
Note: The attribute
android:hostmust be changed if another XignIn-Manager is targeted. If the app has to support multiple managers oneintent-filterentry can be added for each manager.
With the IntentFilter set up an Intent containing the App-Link can be received in onResume function of the
configured Activity. The Intent can then be passed to the function parseData(customUrl:customSchemes:hosts:) of
the MobileRedirectHelper class for evaluation. The functionality of the MobileRedirectHelper is discussed in the
chapter MobileRedirectHelper.
Like for iOS, there is also a configuration that can be made on the XignIn-Manager. However, in contrast to iOS this is
only optional for Android. The XignIn-Manager provides a file named assetlinks.json. Within this file an entry can be
created for an app. If done correctly and the attribute android:autoVerify="true has been set in the IntentFilter
for the App-Link, the system will no longer present the user with a choice of which app to open for the App-Link.
Instead, the app will be opened directly, if only one app is installed on the system that is registered for the
App-Link.
The following example shows an assetlinks.json file that grants link-opening rights to an app with the application
id com.example:
JSON
[
{
"relation": [
"delegate_permission/common.handle_all_urls"
],
"target": {
"namespace": "android_app",
"package_name": "com.example",
"sha256_cert_fingerprints": [
"14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
]
}
}
]
For more information about assetlinks.json files, please refer to the official Android
documentation Verify Android App Links.
Note: The
assetlinks.jsonfile can only be edited directly for on-premise XignIn-Manager installations. If a new app should be registered on a XignIn-Manager managed by the XignSys GmbH, for examplehttps://xign.me, please contact us for that matter.
In case the user starts a personalization or an authentication solely from a mobile device, a button containing a
Deep-Link is displayed instead of the QR Code. This Deep-Link can only be opened by the app. It contains a custom scheme
and not http or https. Therefore, the app also needs to be registered to handle this Deep-Link. Starting with version
8.2.0 of the XignIn-Manager the same link is used for Android and iOS. The scheme can be configured on the
XignIn-Manager. Normally, each XignIn-Manager uses a different scheme. To avoid the problem on the iOS platform, that
the system always chooses the app that is opened directly without asking the user, multiple schemes can be configured
for the same XignIn-Manager. Meaning that each XignIn-Manager has at least one scheme that can be used by every app
targeting the manager and an optional list of schemes that only lead to a specific app. For example the official XignSys
XignIn-Manager uses the scheme xignqr, an authentication Deep-Link then looks
like: xignqr://authentication?pid=CgM...Wg%3D%3D&browser=2&source-url=https%3A%2F%2Fxign.me%2Flogin%23xin-browser%3D2.
To support Deep-Links on iOS, a custom URL with the scheme of the Deep-Link must be declared within the Info.plist
file of the app. The following example shows the content of an Info.plist file which only contains the necessary
entries to receive a Deep-Link for the scheme xignqr, extracted from the XignSys SDK Demo app.
XML
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>com.xignsys.XignsysIosSdkDemo</string>
<key>CFBundleURLSchemes</key>
<array>
<string>xignqr</string>
</array>
</dict>
</array>
</dict>
</plist>
The value of the string entry for the key CFBundleURLName has to be replaced with the apps Bundle ID and within the
array under CFBundleURLSchemes all supported schemes must be listed.
Similar to App-Links, Deep-Links can then be received within the functions scene(:continue:)
and scene(:openURLContexts:) of the UIWindowSceneDelegate in SwiftUI applications. The received URL from these
functions can be passed to MobileRedirectHelper.parseData(customUrl:customSchemes:hosts:) for evaluation. The
functionality of the MobileRedirectHelper is discussed in the chapter MobileRedirectHelper.
To receive Deep-Links on Android, an IntentFilter must be registered for an Activity that receives the link within
the Android Manifest file. The following example shows the registration of this filter for Deep-Links created by the
official XignSys XignIn-Manager.
XML
<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="authentication"
android:scheme="xignqr" />
<data
android:host="personalization"
android:scheme="xignqr" />
</intent-filter>
Similar to App-Links, Deep-Links can then be received in the onResume function of the configured Activity.
The Intent can then be passed to the function parseData(customUrl:customSchemes:hosts:) of
the MobileRedirectHelper class for evaluation. The functionality of the MobileRedirectHelper is discussed in the
chapter MobileRedirectHelper.
The Intent / Custom URL can be parsed in the app with the help of the class MobileRedirectHelper. It offers a static
function parseData(customUrl: scheme:) which converts the data into a more accessible model. The first parameter is
the custom URL as URL object on iOS and the Intent as Intent object on Android. The second parameter is the 'scheme' as
a String. If omitted the official XignIn scheme is used. The result of the function is an enum in Swift / a sealed class
in Kotlin with three cases: personalization, authentication or transaction. Every case has a parameter/property named
pid which carries the Process Initialization Data as base64 encoded String. This data can then be passed to the
function XignCommon.parseProcessInitializationData(data:) or its synchronous counterpart for parsing.
The MobileRedirectHelper is a support class that can be used to evaluate Deep-Links and App-Links of the XignIn
technology. For that purpose the MobileRedirectHelper offers a static
function parseData(customUrl:customSchemes:hosts:). This function accepts an Intent (Android) / a URL (iOS) to
evaluate. Furthermore, a list of customSchemes and hosts can be supplied. The list of customSchemes is needed for
processing Deep-Links that are not App-Links. If not specified, the list defaults to a list with only one
entry: xignqr - the custom scheme of the official XignSys XignIn-Manager. The parameter hosts is used for evaluating
App-Links and expects a list of acceptable hosts. If no hosts are given, the list is also defaulted to a list with
only one entry: xign.me - the host of the official XignSys XignIn-Manager. If a XignIn-Manager targeted besides the
official XignSys one, these two values should be specified.
The following example shows a minimalistic class with the entry points of the Deep-/App-Links and how an evaluation can
be invoked. For iOS a simple SwiftUI UIWindowSceneDelegate is shown and for Android a basic Activity.
class DocumentationExampleSceneDelegate: UIResponder, UIWindowSceneDelegate {
// this function is called for App-Links, if the app is in the background
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if let url = userActivity.webpageURL {
handleCustomURL(url)
}
}
// this function is called for Deep-Links, if the app is in the background
func scene(_ scene: UIScene, openURLContexts: Set<UIOpenURLContext>) {
if let openURLContext = openURLContexts.first {
handleCustomURL(openURLContext.url)
}
}
// this function is called if the app gets initialized
func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
if let webpageURL = connectionOptions.userActivities.first?.webpageURL {
handleCustomURL(webpageURL)
} else if let customUrl = connectionOptions.urlContexts.first?.url {
handleCustomURL(customUrl)
}
// TODO: build your scene
}
func handleCustomURL(_ url: URL) {
if let mobileRedirectData: MobileRedirectData = MobileRedirectHelper.parseData(
url: url,
// list of Deep-Link schemes that should be accepted
customSchemes: [
// the scheme for the official XignSys XignIn-Manager
MobileRedirectHelper.mobileRedirectSchemeXignqr,
// your custom scheme
"your-custom-scheme"
],
// list of host names for App-Links that should be accepted
hosts: [
// the host name of the official XignSys XignIn-Manager
MobileRedirectHelper.mobileRedirectHostXignme,
// your / another XignIn-Manager host name
"your-managers-domain"
]
) {
switch mobileRedirectData {
case .personalization(
processInitializationData: let processInitializationData,
sourceUrl: let sourceUrl,
browser: let browser
):
// Extract the raw process initialization data
// and start a personalization process after parsing.
return
case .authentication(
processInitializationData: let processInitializationData,
sourceUrl: let sourceUrl,
browser: let browser
):
// Extract the raw process initialization data
// and start an authentication process after parsing.
return
case .transaction(
processInitializationData: let processInitializationData,
sourceUrl: let sourceUrl,
browser: let browser
):
// Extract the raw process initialization data
// and start a transaction process after parsing.
return
}
} else {
// the url did not contain any matching data or
// is not one of the XignIn technology
}
}
}
class DocumentationExampleActivity : Activity() {
override fun onResume() {
super.onResume()
val intent = intent
if (intent != null) {
this.intent = null
val mobileRedirectData: MobileRedirectData? = MobileRedirectHelper.parseData(
intent = intent,
// list of Deep-Link schemes that should be accepted
customSchemes = listOf(
// the scheme for the official XignSys XignIn-Manager
MobileRedirectHelper.MOBILE_REDIRECT_SCHEME_XIGNQR,
// your custom scheme
"your-custom-scheme"
),
// list of hostname for App-Links that should be accepted
hosts = listOf(
// the host name of the official XignSys XignIn-Manager
MobileRedirectHelper.MOBILE_REDIRECT_HOST_XIGNME,
// your / another XignIn-Manager host name
"your-managers-domain"
)
)
when (mobileRedirectData) {
is MobileRedirectData.Personalization -> {
// Extract the raw process initialization data
// and start a personalization process after parsing.
}
is MobileRedirectData.Authentication -> {
// Extract the raw process initialization data
// and start an authentication process after parsing.
}
is MobileRedirectData.Transaction -> {
// Extract the raw process initialization data
// and start a transaction process after parsing.
}
null -> {
// the intent did not contain any matching data or
// is not one of the XignSys technology
}
}
}
}
}
The function parseData(customUrl:customSchemes:hosts:) returns an instance of MobileRedirectData or nil/null, if
the given data do not match, are invalid or are not supported by the XignIn technology. The MobileRedirectData are a
sealed class in Kotlin or an enum in Swift. The cases specify which process can be started with the data. Note that this
function is written lightweight, so that it can be run on the UI thread and therefore does not fully parse the process
initialization data. Every case contains three parameters, processInitializationData, sourceUrl and browser. The
processInitializationData can be used to start a process of the XignSys SDK by
invoking XignCommon.parseProcessInitializationData(data:), which is discussed in the next
chapter Parsing of the Process Initialization Data. The sourceUrl
and browser are optional (nullable) and indicate, whether the app must be "closed" after the process or not.
Meaning, if the sourceUrl is present the started process (personalization / authentication) is not finished yet, even
though the process within the app itself is completed. For example, in case of the OIDC (OpenID Connect) registration
flow the user is presented with a personalization QR Code (Deep-Link) directly in the web browser. However, after the
personalization is finished within the app, the user must return to the browser session so the last step of the OIDC
flow can be completed.
The sourceUrl contains the browser URL the user originated from. It can be used to open the browser. This is only
relevant for iOS, because on Android the app can just be finished, in case a sourceUrl is present. For iOS
the MobileRedirectHelper also offers the function open(browser:sourceUrl:completionHandler:) which can be used to
ask the system to open the sourceUrl within the detected browser. However, due to technical limitations, this
detection is not a hundred percent reliable. Not every browser can be supported and even if it were, there is no
guarantee for the user to be directed to the same tab. Therefore, notifying the user to manually switch back to the
browser tab from which the process was started is highly recommended, if a sourceUrl is present.
The Process Initialization Data (short pid) can be parsed by invoking
XignCommon.parseProcessInitializationData(data:). This function accepts either the content of a XignSys QR Code, an
App-Link, or the base64 encoded process initialization data from MobileRedirectData.processInitializationData. The
following example illustrates this operation:
private func parsePid(pidAsBase64String: String) throws {
let xignCommon: XignCommon = XignSdk.shared.xignCommon
let pid: ProcessInitializationData
do {
pid = try xignCommon.parseProcessInitializationDataSynchronous(data: pidAsBase64String)
} catch {
// TODO: handle errors here
throw YourError.yourErrorCase
}
switch pid {
case .personalization(let personalizationInitializationData):
// TODO: start a personalization with the personalizationInitializationData
YourImplementation.startPersonalizationProcess(personalizationInitializationData)
case .authentication(let authenticationInitializationData):
// TODO: start a authentication with the authenticationInitializationData
YourImplementation.startAuthenticationProcess(authenticationInitializationData)
case .transaction(let transactionInitializationData):
// TODO: start a transaction with the transactionInitializationData
YourImplementation.startTransactionProcess(transactionInitializationData)
}
}
private fun parsePid(pidAsBase64String: String) {
val xignCommon: XignCommon = XignSdk.shared.xignCommon
val pid: ProcessInitializationData = try {
xignCommon.parseProcessInitializationDataSynchronous(data = pidAsBase64String)
} catch (e: XignSdkException) {
// TODO: handle errors here
throw YourException()
}
when (pid) {
is PersonalizationInitializationData -> {
// TODO: start a personalization with the personalizationInitializationData
YourImplementation.startPersonalizationProcess(pid)
}
is AuthenticationInitializationData -> {
// TODO: start a authentication with the authenticationInitializationData
YourImplementation.startAuthenticationProcess(pid)
}
is TransactionInitializationData -> {
// TODO: start a transaction with the transactionInitializationData
YourImplementation.startTransactionProcess(pid)
}
}
}
The result of the parsing process is an instance of ProcessInitializationData, which type is an enum in Swift and a
sealed class in Kotlin. The enum has three cases personalization, authentication and transaction which contain
the needed data PersonalizationInitializationData, AuthenticationInitializationData
or TransactionInitializationData. In Kotlin the concrete implementations of the sealed class are already one of the
needed data. These data can be used to start the corresponding process via
invoking Personalizer.decryptPersonalizationInitializationData(), Authenticator.startAuthentication()
and Authenticator.startTransaction() respectively. The process are discussed further in the
chapters Personalization and Authentication.
Note: Transactions are currently under development and therefore do not need to be processed.