Identity Management

Introduction

The Identity Management service allows you to add authentication and authorization to your mobile app.

  • Secure your mobile app using the industry standard OpenID Connect protocol

  • Add access control to your app based on user’s group membership

  • Easily implement SSO, multi-factor authentication and Social Login support

  • Back-end support for identity brokering and user federation

See the Keycloak documentation for more info.

Identity Management Terminology

This section describes terminology that is associated with Identity Management.

SSO

Single Sign On, the ability to share a login between multiple services

OpenID Connect

a standard for providing identity on top of OAuth 2.0

Keycloak

Red Hat’s implementation of SSO and OpenID used as the identity provider

Client ID

is the client identifier for OpenID Connect requests, a simple alpha-numeric string

User Attributes

additional properties for user accounts (besides name and email) managed by Keycloak

Prerequisites

Setting Up the Identity Management Mobile Service

Provisioning the Identity Management Service

  1. Log into the OpenShift console.

  2. Create a new project or choose an existing project.

  3. Click Add to Project and choose Browse Catalog from the options.

    You can filter the catalog items to only show mobile specific items by clicking the Mobile tab.

  4. Click Services and choose the Identity Management service.

    catalog mobile services
  5. Follow the wizard for provisioning that service.

    If prompted to Create a Binding, choose Do not bind at this time

    When provisioning an Identity Management service, you are prompted to set the following configuration:

    • Keycloak admin username: Username for Keycloak administration

    • Keycloak admin password: Password for the Keycloak admin user

    • Name of the Keycloak realm: Name of the keycloak realm. (defaults to current namespace)

      A realm manages a set of users, credentials, roles, and groups. A user belongs to and logs into a realm. Realms are isolated from one another and can only manage and authenticate the users that they control.
    • Connect to an existing shared service: Select if you want to use an existing service and you have the URL and credentials to use that service.

    • URL of the shared service: Enter a value if you want to use an existing shared service.

Once the wizard steps are completed, navigate to the Project Overview in OpenShift to see the newly provisioned service. Provisioning a service may take some time.

Binding a Mobile Client

To use mobile services, you must represent your mobile app in OpenShift using a Mobile Client, and that Mobile Client must be associated with the mobile service. This association is called binding and once it’s done, your mobile app can use that service immediately.

The association between a Mobile Client and Identity Management Service uses the Service Broker bind feature.

To associate a Mobile Client with a mobile service:

Procedure

  1. Navigate to the Overview of your OpenShift project.

  2. Select the Mobile Client name listed in the Mobile Clients section.

  3. Navigate to Mobile Services tab.

    mobile clients services all unprovisioned
  4. Click Create Binding and follow the Create Binding wizard to associate the Mobile Client with the Identity Management Service.

  5. Fill out the binding parameters required by the Identity Management Service.

  6. Choose the Keycloak client type. The default is public which allows the client to request tokens while type bearer should be used to bind to services that only need to verify tokens.

    The public client type should be used to bind to Mobile Clients because they only need to request tokens, but not verify them. When binding to other services you should use client type bearer unless they also need to authenticate.

The Identity Management service will now be expandable, details about the service can be viewed.

mobile clients services all idm provisioned

Configuring the Service

The following section will guide you through configuring the schema of the redirect url and web origin for a client in Keycloak. This is required to enable OpenID authentication. For an explanation of these terms, see Keycloak Documentation.

Choose the schema of a redirect url

Android

It is recommended to use the package name of the Android app as the schema of the redirect url to avoid conflicts. (e.g. com.aerogear.androidshowcase)

iOS

It is recommended to use the Bundle Identifier of the iOS app as the schema of the redirect url. (e.g. org.aerogear.ios-showcase-template)

Cordova

The schema of the redirect url should be http://localhost/*.

Xamarin

Depending on the platform, set the redirect as described in either the Android or the iOS tab.

Configuring Keycloak

  1. Log into the OpenShift console and navigate to the Project Overview.

  2. Navigate to the Mobile Client screen.

  3. Select the Mobile Services tab.

  4. If a binding to the Identity Management service is in progress, a spinning icon is displayed to the right of the Identity Management entry. Wait for the binding process to complete.

  5. If the Keycloak Realm URL URL is not visible, expand the Identity Management Service by clicking the > icon.

  6. Click on the Keycloak Realm URL link to open the Keycloak Administration Console.

  7. Log in to the Administration console using the credentials you specified at Provisioning (defaults to admin:admin)

  8. Select Clients from the menu.

  9. Select your client from the list of clients. The name of your client is derived from the name of the Mobile Client, the name of the mobile development platform and the client type, for example myapp-android-public.

  10. Add <schema>:/callback as an additional entry to Valid Redirect URIs. See Choose the schema of a redirect url to determine the value for <schema>.

  11. Add <schema> as an additional entry to Web Origins. See Choose the schema of a redirect url to determine the value for <schema>.

  12. Save your changes.

  13. Create a new user account as described in Creating a New User.

  14. Set up credentials for the new user as described in User Credentials.

Downloading the Mobile Services Configuration File

  1. Navigate to your project in OpenShift.

  2. On the Overview screen, expand your Mobile Client to view the CLIENT INFO.

  3. Copy the configuration to your clipboard.

  4. Save the contents of the clipboard to a new file called mobile-services.json.

    The mobile-services.json file is the link between your provisioned services on OpenShift and the mobile app you are developing. This file provides all required configuration to initialise the various SDKs and get them hooked up/connected to the back-end services.
  5. Follow the next specific additional instructions depending on your platform:

Android

Locate this file at the following location in your application project:

app/src/main/assets/mobile-services.json

iOS

Locate this file at the following location in your application project:

<app directory>/mobile-services.json

Make sure this file is visible in Xcode, add the file if necessary.
Cordova

Locate this file at the following location in your application project:

src/mobile-services.json

Xamarin

Locate this file at the following location in your application project:

Resources/mobile-services.json

Setting up Identity Management service SDK

This section will help you to set up the Identity Management service SDK in your App.

Importing the libraries
Android
  1. Add the following dependency in your app’s build.gradle:

    dependencies {
        implementation "org.aerogear:android-auth:1.0.0"
    }
iOS
  1. Add the dependency to your Podfile:

    target '[TARGET NAME]' do
        pod 'AGSAuth', '1.0.0'
    end
  2. Update the dependencies:

    $ pod install
  3. Import and instantiate AGSAuth to start using the SDK:

    import AGSAuth
    
    let auth = AGSAuth()
Cordova

Install the AeroGear Auth package from NPM:

$ npm install @aerogear/auth
Xamarin
  1. Install NuGet.

  2. Install the AeroGear Core package:

    dotnet add package AeroGear.Mobile.Core --version 1.0.0
  3. For Android run:

    dotnet add package AeroGear.Mobile.Core.Platform.Android --version 1.0.0
    dotnet add package AeroGear.Mobile.Auth.Platform.Android --version 1.0.0
  4. For iOS run:

    dotnet add package AeroGear.Mobile.Core.Platform.iOS --version 1.0.0
    dotnet add package AeroGear.Mobile.Auth.Platform.iOS --version 1.0.0

Initializing the SDK

Android
  1. Retrieve the auth service:

    AuthService authService = MobileCore.getInstance().getService(AuthService.class);
  2. Specify the redirect URL. It is recommended to use the package name of your app.

    AuthServiceConfiguration authServiceConfig = new AuthServiceConfiguration
        .AuthConfigurationBuilder()
        .withRedirectUri("org.aerogear.mobile.example:/callback")
        .build();
  3. Before the auth service can be used init must be invoked once in an app

    authService.init(context, authServiceConfig);
iOS

Set your custom configuration to the auth service instance, making sure the redirect URL matches the App’s Bundle Id.

// create the authentication config
let authenticationConfig = AuthenticationConfig(redirectURL: "org.aerogear.mobile.example:/callback")
try! AgsAuth.instance.configure(authConfig: authenticationConfig, useExternalUserAgent: false)
Cordova

Import and initialize Auth:

const Auth = require('@aerogear/auth').Auth;

const authService = new Auth();
const initOptions = { onLoad: "login-required" };

authService.init(initOptions)
    .then(() => {
        // successful init & authentication
    })
    .catch((err) => {
        // initialization error
    });

You can pass login-required or check-sso to the init function. login-required will authenticate the client if the user is logged in to Keycloak or display the login page if not. check-sso will only authenticate the client if the user is already logged in. If the user is not logged in the browser will be redirected back to the application and remain unauthenticated. By default, the check-sso option is used.

Initialization will also perform authentication
Xamarin
  1. Create an intent filter for the net.openid.appauth.RedirectUriReceiverActivity activity. This step is required for Xamarin Android and allows the login browser to redirect back to your App. Add this to your AndroidManifest.xml:

    <activity android:name="net.openid.appauth.RedirectUriReceiverActivity" android:exported="true"  android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round">
        <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:scheme="org.aerogear.mobile.example" />
        </intent-filter>
    </activity>
  2. Initialize the Auth module

    1. For an Android app (MainActivity.cs):

      var app = new App();
      MobileCoreAndroid.Init(app.GetType().Assembly,ApplicationContext);
      var authService = AuthService.InitializeService();
      var authConfig = AuthenticationConfig.Builder.RedirectUri("org.aerogear.mobile.example:/callback").Build();
      authService.Configure(authConfig);
      For Android an Intent filter should be configured with the callback URL specified in AuthenticateOptions in the App’s AndroidManifest.xml. See the example app.
    2. For an iOS app (FinishedLaunching method of AppDelegate.cs):

      var app = new App();
      MobileCore core = MobileCoreIOS.Init(app.GetType().Assembly);
      var authService = AuthService.InitializeService();
      var authConfig = AuthenticationConfig.Builder.RedirectUri("org.aerogear.mobile.example:/callback").Build();
      authService.Configure(authConfig);

Adding User Authentication to your Mobile App

This section describes how to perform user authentication for the supported platforms. On authentication a browser window will open and prompt the user for login credentials.

Implementing authentication

The following examples show how to implement authentication using the Aerogear SDK on all the supported platforms.

Android
  1. Provide an implementation of Callback which is defined in the Aerogear SDK and used to handle asynchronous results:

    Callback authCallback = new Callback<UserPrincipal>() {
        @Override
        public void onSuccess(UserPrincipal principal) {
            ...
        }
    
        @Override
        public void onError(Throwable error) {
            ...
        }
    };
  2. Retrieve an instance of the AuthService and use the login method to hand over to the login browser:

    AuthService authService = MobileCore.getInstance().getService(AuthService.class);
    
    // Build the options object and start the authentication flow
    DefaultAuthenticateOptions options = new DefaultAuthenticateOptions(myActivity, LOGIN_RESULT_CODE);
    
    authService.login(options, authCallback);
  3. Override onActivityResult to handle the result from the browser. It’s important to pass the intent back to the Auth service:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == LOGIN_RESULT_CODE) {
            AuthService authService = MobileCore.getInstance().getService(AuthService.class);
            authService.handleAuthResult(data);
        }
    }
    This handler should always invoke handleAuthResult, providing the Intent. This will exchange the temporary tokens returned from login for long-lived tokens and will provide a UserPrincipal which can be used to access a users details. If this is not invoked you will not have access to the UserPrincipal.
  4. The callback provided to login will be invoked.

iOS
  1. Use the login method to hand over to the login browser:

    AgsAuth.instance.login(presentingViewController: self, onCompleted: onLoginComplete)
    
    func onLoginComplete(user: User?, err: Error?) {
        if let error = err {
            return
        }
    
        let currentUser = user
    }
  2. Allow your application to handle the redirect in AppDelegate:

    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey: Any] = [:]) -> Bool {
        do {
            return try AgsAuth.instance.resumeAuth(url: url as URL)
        } catch AgsAuth.Errors.serviceNotConfigured {
            print("AeroGear auth service is not configured")
        } catch {
            fatalError("Unexpected error: \(error).")
        }
        return false
    }
Cordova

Authentication will be performed on initialization as described here. To manually redirect to the login screen, use:

authService.login().then(() => {
    // Login success
}).catch(() => {
    // Login error
});;
Xamarin
  1. Use the Authenticate method to hand over to the login browser:

    IAuthService authService = MobileCore.Instance.GetInstance<IAuthService>();
    
    var authOptions = DependencyService.Get<IAuthenticateOptionsProvider>().GetOptions();
    authService.Authenticate(authOptions).ContinueWith(user =>
    {
        // Get the authenticated User from the provided Task.
        Console.WriteLine(user.Result);
    
        // Change view to user details. No need to handle the user result here, it will be available through
        // authService.CurrentUser()
        Device.BeginInvokeOnMainThread(() => ((RootPage)(App.Current.MainPage)).ChangePage(new UserDetails()));
    });

Adding Log Out Option to your Mobile App

The following section describes how to perform a logout.

Android
  1. Get an instance of the auth service and retrieve the current user:

    AuthService authService = MobileCore.getInstance().getService(AuthService.class);
    UserPrincipal currentUser = authService.currentUser();
  2. Implement Callback and call logout:

authService.logout(currentUser, new Callback<UserPrincipal>() {
    @Override
    public void onSuccess() {
        // User Logged Out Successfully and local Auth tokens were Deleted
    }

    @Override
    public void onError(Throwable error) {
        // An error occurred during logout
    }
});
iOS
  1. Implement the logout callback:

    func onLogoutComplete(_: Error?) {
        ...
    }
  2. Call logout and pass the callback:

    do {
        try AgsAuth.instance.logout(onCompleted: self.onLogoutComplete)
    } catch {
        fatalError("Error logging out: \(error).")
    }
Cordova

To logout invoke the logout function:

authService.logout().then(() => {
    // When the logout succeeded the local tokens obtained during authentication are deleted
});
Xamarin

To logout invoke the Logout method:

var authService = MobileCore.Instance.GetInstance<IAuthService>();
authService.Logout(authService.CurrentUser()).ContinueWith(result =>
{
    Device.BeginInvokeOnMainThread(() => ((RootPage)(App.Current.MainPage)).ChangePage(new GoodbyePage()));
});
To perform backchannel or federated logouts, you must enable the Backchannel Logout option for the federated identity provider. More information is available in the Keycloak documentation under OICD Identity Providers.

Additional Information

Adding Access Control to your Mobile App

Once a UserPrincipal has been retrieved, the roles of the user can be listed and checked. This can be used to perform client side access control, such as hiding UI components related to actions the user doesn’t have permissions to perform.

Roles are divided into two types. Resource roles which belong to the client the user has authenticated against, and Realm roles which belong to the realm the client is in.

Android
  1. Retrieve the authenticated user:

    // authService already initialized.
    AuthService authService = MobileCore.getInstance().getService(AuthService.class);
    UserPrincipal currentUser = authService.currentUser();
  2. Use hasRealmRole and hasResourceRole to check for roles:

    boolean hasAdminPermissions = currentUser.hasRealmRole("user_admin");
    boolean isModerator = currentUser.hasResourceRole("my_resource", "user_moderator");
iOS
  1. Retrieve the authenticated user:

    let currentUser = try AgsAuth.instance.currentUser()
  2. The user roles are available on the authenticated user:

    let clientRoles = currentUser.clientRoles
    let realmRoles = currentUser.realmRoles
  3. Use hasRealmRole and hasClientRole to check for roles:

    let hasAdminRole = currentUser.hasRealmRole("admin")
    let hasModeratorRole = currentUser.hasClientRole(client: "my_client", role: "moderator")
Cordova

Get the realm roles from the auth service:

const realmRoles = authService.getRealmRoles();
No function to retrieve the resource roles is currently exported but you can use extract to get a handle to the underlying keycloak-js instance to retrieve the roles from there. Have a look at their documentation here.
Xamarin
  1. Retrieve the authenticated user:

    // auth service is already initialised
    var user = MobileCore.Instance.GetInstance<IAuthService>().CurrentUser();
  2. Use getRoles to retrieve all roles from the user:

    // auth service is already initialised
    var roles = user.getRoles();
  3. Use HasRealmRole and HasResourceRole to check for roles:

    bool isAdmin = user.HasRealmRole("user_admin");
    bool isModerator = user.HasResourceRole("my_resource", "user_moderator");

Adding Single Sign-On (SSO) to your Mobile App

The Auth SDK uses OpenID Connect Authorization Code Flow to achieve SSO via a mobile device browser.

Prerequisites

  • Two Mobile Clients bound to the Identity Management service

  • Two mobile apps built and running on the same device that are using the AeroGear SDK Auth module

Using SSO with the Device Browser

For this guide, assume that your two apps are called Email App and Messaging App.

  1. Ensure the "Remember Me" option in Keycloak is turned on. In the admin UI click on Realm Settings section on the left hand side, and then click on Login. Turn on Remember Me.

  2. Now that your two iOS apps and Keycloak clients are setup, sign into the Email App with the user you have previously created. You should be redirected to your device browser which should have loaded the Keycloak login page.

  3. Next, enter in your credentials, make sure check the Remember Me option and login. You have now been authenticated on the Email App via the browser.

  4. Finally, try sign into the Messaging App and you should be automatically logged in as you have been previously authenticated in the Email App via the same browser.

Known Issues

On iOS 11 and above, Apple has introduced SFAuthenticationSession for apps to perform SSO, instead of using the system Safari browser. However, there are a few known issues with this new feature and sometimes user may have to enter their credentials again in other apps, even if they have already logged in once previously in one of the apps.

Monitoring the Identity Management Service

Prerequisites

  • The Mobile Metrics Service and Identity Management Service must be provisioned in the same OpenShift project to access data.

Overview

After the Mobile Metrics Service (includes Grafana for visualization and the Prometheus monitoring system) and Identity Management Service are provisioned, you should be able to see the "Keycloak Metrics" in the list of available dashboards (navigate to Grafana’s exposed URL → Log in → Home → Select Keycloak Metrics).

Dashboard panel descriptions

The Keycloak dashboard consists of several panels which give you an overview of the specific events, such as the number of registered users, memory usage etc.

Below you will find a detailed description of each panel and its values.

Singlestat Panels

Singlestat panels show you the main summary of a single data series.

  • Total Registrations: Total number of registered (non-admin) users. This number comprises all successful registrations made via various providers, e.g. Keycloak, Github, Facebook etc.

  • Total Logins: Total number of successful logins (only non-admin users) over all providers.

  • Total Login Errors: Total number of failed login attempts.

  • Current Memory: The amount of memory currently used by the Identity Management Service

Graph panels

Used to show how certain values change over time, e.g. the number of successful logins.

  • Logins: Overview of the successful logins over time

  • Login Errors: Overview of the failed login attempts over time

  • Memory Usage: The values in this graph represents the following:

    • Used: The amount of memory currently used by the Identity Management Service

    • Commited: The amount of memory that is guaranteed to be available for use (by JVM)

    • Max: The maximum amount of memory that can be used for memory management

Pie Charts

Used to show the distribution of data, e.g. the number of logins per identity provider.

  • Logins Per Provider: Overview of the successful (non-admin) user logins per provider

  • Registrations Per Provider: Overview of the successful (non-admin) user registrations per provider.