Skip to content

eunid/netid-sdk-android

Repository files navigation

netID MobileSDK for Android

About

The netID MobileSDK facilitates the use of the netID authorization and privacy management services. Alongside the SDK, this repository hosts two sample apps, demonstarting the usage of the SDK. The first one is more complete as it demonstrates complete workflows including fetching/setting of additional values and/or user information. The second one is less complex and only demonstrates the basic workflow, if you want to add the different buttons for interacting with the SDK in a more direct way.

Initialize NetIDService

The NetIdService is the main interface to communicate with the netID SDK. It handles all the communication with the backend services and provides UI elements for the authorization flow.

First, construct a configuration object of type NetIdConfig for the NetIDService:

private lateinit var netIdConfig: NetIdConfig

companion object {
    private const val clientId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
    private const val redirectUri = "https://eunid.github.io/redirectApp"
    private const val claims = "{\"userinfo\":{\"email\": {\"essential\": true}, \"email_verified\": {\"essential\": true}}}"
    private val permissionLayerConfig = null
    private val loginLayerConfig = null
}
...

netIdConfig = NetIdConfig(clientID, redirectUri, claims, permissionLayerConfig, loginLayerConfig)

The parameters have the following meaning:

Parameter Description
clientId The client id of your application. You can retrieve it from the netID Developer portal. This parameter is mandatory.
redirectUri An URI that is used by your application to catch callbacks. You can retrieve it from the netID Developer portal. This parameter is mandatory.
claims An OIDC-compliant, URL-encoded JSON string, denoting additional claims that should be set during authorization. Can be null.
permissionLayerConfig A set of strings, that can be used to customize the appearance of the layer for the permission flow. Can be null.
loginLayerConfig A set of strings, that can be used to customize the appearance of the layer for the login flow. Can be null.

Besides the clientId, the redirectUri is the most important parameter in the configuration. The redirectUri is a link that is called by the authorization service to get back to your app once the authorization process has finished. As this is a rather crucial process, the netID SDK makes use of Verified App Links to ensure proper and secure communication between the authorization service and your app. In order to make app links work, you have to provide a link in the form of an uri (e.g. https://eunid.github.io/redirectApp) and host a special file named assetlinks.json on that very same domain (in this example https://eunid.github.io/.well-known/assetlinks.json). When using Android Studio for development, there is an extra section inside the menu Tools called App Links Assistant to help create and test app links for you application as well as the corresponding asset file.

To make your application trigger on the aforementioned redirect, you must include the following snippet in your app's AndroidManifest.xml:

<activity
    android:name="net.openid.appauth.RedirectUriReceiverActivity"
    tools:node="replace"
    android:exported="true">
    <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:scheme="https"
            android:host="eunid.github.io"
            android:path="/redirectApp"/>
    </intent-filter>
</activity>

However, for your own application you have to make sure that scheme, host, and path match your very own settings.

To learn more about Verified App Links, see the corresponding documentation here.

After setting up your application in the correct way and constructing the configuration object, register your application as a listener to receive all callbacks made by the NetIdService.

NetIdService.addListener(this)

Finally, initialize the NetIdService itself with the aforementioned configuration.

NetIdService.initialize(netIdConfig, this.applicationContext)

Authorization

After the NetIDService has been initialized, subsequent calls to request authorization can be made. In the example app, you are presented with three choices as can be seen in this screenshot.

netID SDK example app - chosse authFlow

In your own app, you most likely will decide which flow to take without an user interaction. To initiate the authorization process, issue the following call to the NetIDService:

NetIdService.getAuthorizationFragment(this, authFlow, forceApp2App)
Parameter Description
activity The activity to attach this fragment to. This parameter is mandatory.
authFlow Type of flow to use, can be either NetIdAuthFlow.Permission, NetIdAuthFlow.Login or NetIdAuthFlow.LoginPermission. This parameter is mandatory.
forceApp2App If set to true, will yield an NetIdError if the are no Account Provider apps installed. Otherwise, will use app2web flow automatically. Defaults to false.

You have to provide an instance of you app's activity so that the SDK can display a view for the authorization process itself. With the parameter authFlowyou decide, if you want to use Permission, Login or Login + Permission as authorization flow. The optional parameter forceApp2App decides, if your app wants to use app2app only. If let alone, this parameter defaults to false meaning that if no Account Provider apps are installed, the SDK will automatically fall back to app2web flow. If set to true and no Account Provider apps are installed, this call will fail with an error.

Depending on the chosen flow, different views are presented to the user to decide on how to proceed with the authorization process.

Login Flow with no Account Provider Apps Permission Flow with no Account Provider Apps
netID SDK example app - login flow with app2web

Login flow without installed id apps

netID SDK example app - permission flow with app2web

Permission flow without installed id apps

As stated above, it is possible to customize certain aspects of the dialog presented for authorization. For example, the strings displayed during the login process could be changed with this configuration:

private val loginLayerConfig = LoginLayerConfig("Headline text", "Login with app %s", "Continue text")

And when using permission flow, the dialog can be customized as well:

private val permissionLayerConfig = PermissionLayerConfig(
    "custom_logo_resource_name",
    "Headline text", 
    "Legal text", 
    "Continue text")

With the first parameter, it is possible to set a custom logo resource (which will be displayed in the top left corner of the dialog). This resource is expected to be a drawable asset in the application package and is referenced by its name, not its id.

Keep in mind that you can not customize the complete legal text in the dialog. The second part of it is predefined by netID.

The SDK will figure out by itself, if Account Provider apps like GMX or web.de are installed. If so, the SDK will always prefer the app2app-flow instead of app2web when communicating with the netID authorization service. When at least one of those apps is found, the call to getAuthorizationFragment will return a slightly different layout, exposing the found apps:

Login flow with multiple Account Provider Apps

Permission flow with multiple Account Provider Apps / expanded choice menu - Default is to pre-select one App and collapse choice menu

netID SDK example app - login flow with app2app

Login flow with installed id apps

netID SDK example app - permission flow with app2app

Permission flow with installed id apps

If the user did decide on how to proceed with the login process (e.g. which Account Provider provider to use), a redirect to actually execute the authorization is called automatically.

As can be seen from the first screenshot, ui elements are organzied in layers to ease the authorization process. The SDK supports two different graphical styles, called Solid and Outline. Switching between those two styles can be done in the demo app by using the picker element at the end of the screen. Programatically you can change the style by calling:

 NetIdService.setLayerStyle(style)

Session persistence

The SDK implements session persistence. So if a user has been authorized successfully, this state stays persistent even when closing and reopening the app again.

To test this with the demo app, close the app once you are successfully authorized. Then, open the app again. After pressing the SDK initialisieren-button, your session will be restored and you are again authorized. So there will be no need to press Authorisieren again.

To get rid of the current session, NetIdService.endsession() has to be called explicitly. In the demo app, this is done by pressing Session beenden. Note, that this will delete the current session within the App only

Using the authorized service

Subsequent calls now can be made to use different aspects of the service.

NetIdService.endSession()

Use this call to end a session. On the listener onEndSession is called signaling success of the operation. All objects regarding authorization (e.g. tokens) will get discarded. However, the service itself will still be available. A new call to getAuthorizationFragment will trigger a new authorization process.

NetIdService.fetchUserInfo(this.applicationContext)

Fetches the user information object. On success onFetchUserInfo is called on the delegate, returning the requested information. Otherwise onFetchUserInfoWithError gets called, returning a description of the error.

NetIdService.fetchPermissions(this.applicationContext)

Fetches the permissions object. On success onFetchPermissions is called on the delegate, returning the requested information. Otherwise onFetchPermissionsWithError gets called, returning a description of the error.

NetIdService.updatePermissions(this.applicationContext)

Updates the permissions object. On success onUpdatePermissions is called on the delegate, returning the requested information. Otherwise onUpdatePermissionsWithError gets called, returning a description of the error.

Implementing the NetIdServiceListener

To be able to react to callbacks regarding the aforementioned functions, your application must conform to the NetIdServiceListener interface. Depending on your type of application, you must not implemnt all callbacks in full detail (e.g. if you never intent to fetch user information, you could just implement a stub here), hence we only list the most important ones here.

/**
 * Callback function that gets called when the SDK could not be initialized correctly.
 * In this case, a ``NetIdError`` is returned which holds more information about the error.
 * @param error Error description.
 */
fun onInitializationFinishedWithError(error: NetIdError?)

/**
 * Callback function that gets called when the authentication process finished successfully.
 * In this case, an access token is returned.
 * @param token Access token.
 */
fun onAuthenticationFinished(accessToken: String)

/**
 * Callback function when user information could not be retrieved.
 * In this case, a ``NetIdError`` is returned which holds more information about the error.
 * @param error Error description.
 */
fun onAuthenticationFinishedWithError(error: NetIdError)

/**
 * Callback function that gets called when a session ends.
 */
fun onSessionEnd()

/**
 * Callback function that gets called when the authentication process got canceled.
 * In this case, a ``NetIdError`` is returned which holds more information about the error.
 * @param error Error description.
 */
fun onAuthenticationCanceled(error: NetIdError)

Button workflow

As stated in the beginning, there is another way to interact with the SDK. In the so called button workflow you can decide to not use the preconfigured forms and texts but build your very own dialogs.

Therefore, the SDK gives you the opportunity to only make use of the basic functionalities to use the SDK. As a starting point, take a look at the second demo app provided in the buttonApp folder. Just like in the demo app, there is a possibility to change between different design sets to show off the different styles for the buttons. This can be done by calling the following function:

NetIdService.setButtonStyle(style)

And style can be any style provided by NetIdButtonStyle.

Style SolidWhite Style SolidGreen Style Outline
netID SDK example button app - style SolidWhite netID SDK example button app - style SolidGreen netID SDK example button app - style Outline

Of course, at first you have to initialize the SDK as in the example above.

val netIdConfig = NetIdConfig(
    clientId = clientId,
    redirectUri = redirectUri,
    claims = claims,
    promptWeb = "consent",
    permissionLayerConfig = permissionLayerConfig,
    loginLayerConfig = loginLayerConfig
)
NetIdService.addListener(this)
NetIdService.initialize(netIdConfig, this)

Then, just request the buttons you need to trigger your desired auth flow. E.g. for the permission flow:

val permissionContinueButton = NetIdService.permissionContinueButtonFragment("")
supportFragmentManager.commit {
    setReorderingAllowed(true)
    add(R.id.activityMainPermissionContainer, permissionContinueButton)
}

With the optional parameter continueTextit is possible to alter the default text to a more personal liking. If set to an empty string or omitted completely, a default will be used.

Note that if any Account Provider apps are installed, there will be the possibility to choose which one to use (triggering app2app flow). For example, to display a button for each installed app, use this code:

NetIdService.getKeysForAccountProviderApps().forEach {
    val appButton = NetIdService.accountProviderAppButtonFragment(it, NetIdAuthFlow.Permission, it)
    supportFragmentManager.commit {
        setReorderingAllowed(true)
        add(R.id.activityMainPermissionContainer, appButton)
    }
}

Again, using the optional parameter continuteText will alter the text on the button - otherwise all buttons will have the standard text displayed.

For the login and/or login+permission flow, you can request a button to initiate app2web authorization with the following call:

val loginContinueButton = NetIdService.loginContinueButtonFragment("", NetIdAuthFlow.Login)
supportFragmentManager.commit {
    setReorderingAllowed(true)
    add(R.id.activityMainLoginContainer, loginContinueButton)
}

And if you prefer app2app, you can request respective buttons for each Account Provider this way:

NetIdService.getKeysForAccountProviderApps().forEach {
    val appButton = NetIdService.accountProviderAppButtonFragment(it, NetIdAuthFlow.Login, it)
    supportFragmentManager.commit {
        setReorderingAllowed(true)
        add(R.id.activityMainLoginContainer, appButton)
    }
}

Add the library to your project

netID MobielSDK for Android is available from Maven Central. To include it in your own project, add the following dependency (with VERSION being 1.0.2 at the time of this writing):

implementation 'de.netid.mobile:netidmobilesdk:<VERSION>'