Android Quick Start Guide

By implementing the ZenKey SDK in your Android app, users can interact with the ZenKey button, initiating an authorization flow between your secure server and the ZenKey backend. To integrate the ZenKey SDK in your iOS application, follow the steps below.

1. Enroll in the ZenKey Service Provider Portal

Visit the ZenKey Service Provider Portal and create an account for your organization.

ZenKey Service Provider Portal

Once logged in:

  1. Create a Project.
  2. Designate a Security Contact.
  3. Retrieve your Client ID and Secret.

Note: Because ZenKey must verify and approve your company’s application, you may need to wait 24-48 hours before your Client ID is officially registered and deemed valid.

2. Include the ZenKey SDK in your Project

The ZenKey SDK is provided as a Gradle, Maven and Ivy reference. To use Gradle to integrate ZenKey in your project, first add the JCenter repository to your top-level build.gradle file if you do not already have it.

allprojects {  
    repositories {
         jcenter()  
         }
}

Next, add the ZenKey SDK as a dependency in your application module build.gradle file.

dependencies {  
     implementation 'com.xci.android:zenkey-sdk:0.x.y'  
}

Note: Make sure to replace the x and y above with the latest version numbers, which you can find here.

3. Add Internet Permission

If you don't already have the internet permission, add it in your Android manifest.

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET" />
    <application>
        [...]
    </application>
</manifest>

4. Configure Your Client ID

The ZenKey SDK manifest contains a placeholder for your clientId. In order to compile your app with the ZenKey SDK, you must register the zenKeyClientId placeholder value in your app build.gradle. Replace MY_CLIENT_ID in the code below with your clientId.

android {
    defaultConfig {
        manifestPlaceholders = [zenKeyClientId: 'MY_CLIENT_ID']
    }
}

5. Request Authorization Code

Authorization requests are issued by starting an authorization intent which the ZenKey app receives. To trigger an authorization request, use the ZenKey default button which handles the interaction with the identityProvider and starts the authorization intent. To do this, you will need to add ZenKeyButton to your layout.

6. Add the ZenKey Button

To use the ZenKey button, add the following to your XML layout.

         <com.xci.zenkey.sdk.widget.ZenKeyButton
             android:id="@+id/zenKeyButton"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"/>

If you use the ZenKey Button inside a fragment, you must explicitly set the fragment on the ZenKeyButton in order to receive the result inside the fragment’s onActivityResult() method. Otherwise, the result will be received in the onActivityResult() method of the host activity.

public class MyFragment extends Fragment {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_layout);
        findViewById(R.id.myZenKeyButton).setFragment(this);
    }
}

7. Receive Authorization Response

The authorization result is returned by the SDK using an Intent. In order to extract the authorization response, use the following method with the Intent containing the result or the authorization request.

    AuthorizationResponse.fromIntent(intent)

The result will come back in the data parameter of the requesting Activity/Fragment's onActivityResult(int requestCode, int resultCode, Intent data) method.

public class MyActivity extends AppCompatActivity {

    private static final int REQUEST_CODE_ZENKEY = 1234;

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       if (requestCode == REQUEST_CODE_ZENKEY) {
          if (resultCode == RESULT_OK) {
              handleAuthorizationResponse(data);
          } else {
             //Authorization canceled by user.
          }
       }
    }

    private void handleAuthorizationResponse(Intent data) {
       AuthorizationResponse response = AuthorizationResponse.fromIntent(data);
       if(response.isSuccessful()){
          //Authorization Succeed
          finishZenKeyAuthentication(response);
       } else {
           //Authorization Failed
           handleZenKeyError(response);
       }
    }

    private void finishZenKeyAuthentication(AuthorizationResponse response) {
       String authorizationCode = response.getAuthorizationCode();
       String mcc = response.getMcc();
       String mnc = response.getMnc();
       String codeVerifier = response.getCodeVerifier();
       // Send those four values to your back-end to finish the authentication process.
    }

    private void handleZenKeyError(AuthorizationResponse response) {
       AuthorizationError error = response.getError();
       switch (error){
          case AuthorizationError.INVALID_CONFIGURATION:
             break;
          case AuthorizationError.INVALID_REQUEST:
             break;
          case AuthorizationError.REQUEST_DENIED:
             break;
          case AuthorizationError.REQUEST_TIMEOUT:
             break;
          case AuthorizationError.SERVER_ERROR:
             break;
          case AuthorizationError.NETWORK_FAILURE:
             break;
          case AuthorizationError.DISCOVERY_STATE:
             break;
          case AuthorizationError.UNKNOWN:
             break;
       }
    }
}

8. API Call to Secure Server

While the ZenKey SDK handles the authorization request itself, ultimately you will need to configure a secure server that can receive the parameters from the authorization code request. Only once you receive these values may you request the carrier endpoint and issue a token request from your secure backend. Therefore, you must send an API call to your server which includes the parameters included in the authorization request. For example:

POST  
https://api.your-authorization-server.com/token
    mccmnc={mccMnc}
    &code={authorizationCode}   
    &redirect_uri={redirectUri}
    &code_verifier={codeVerifier}

9. Request Carrier Endpoints

Upon receiving the values above, your secure server now needs to get the right carrier endpoints for this user. This is done by requesting the OpenID Connect configuration with the help of two parameters: mccmnc and client_id. The mccmnc is set of 6 digits located on every SIM card identifying the country code (mcc) and operator code (mnc). Meanwhile, the client_id allows the carrier to identify your registered app.

GET
http://getdiscoveryissuer.myzenkey.com/well-known/openid_configuration?
    mccmnc=123456
    &client_id=ccid-xxxxxxxxxxxxx

The response will include all relevant endpoints.

{
    “issuer”: “https://mno.com”,
    “authorization_endpoint”: “https://mno.com/connect/authorize”,
    “token_endpoint”: https://mno.com/connect/token,
    “userinfo_endpoint”: “https://mno.com/connect/userinfo”,
…
}

10. Issue Token Request

With the user’s consent in the form of an authorization code, your secure server will request an access token from the token_endpoint discovered earlier. To configure this request:

  1. Base64 encode your client_id and client_secret:
        Base64Encode(“{client_id}:{client_secret}”)

Note: When you retrieve your client_secret from the ZenKey Service Provider Portal, for security purposes we ask that you only store your client_secret on your secure backend and allow as few trusted personnel as possible access to it.

  1. Insert this encoded value in your Authorization header:

         'Authorization': "Basic {encoded_value_here}"
  2. Specify the Content-Type as URL-encoded:

         Content-Type: application/x-www-form-urlencoded
  3. Then include the following parameters in the body of your token request:

    grant_type="authorization_code"
    code="{auth_code}"
    redirect_uri="{auth_redirect_uri}"
    code_verifier="{codeVerifier}"

To see all these components working together, see the example below:

POST /token HTTP/1.1
Host: mno.com
Authorization: Basic {encoded_value_here}
Content-Type: application/x-www-form-urlencoded

    grant_type=authorization_code
    &redirect_uri=https://www.client.com
    &code={auth_code}
    &code_verifier={codeVerifier}

11. Token Response

In addition to an Access Token, the token response will return an ID Token which includes the sub — an identifier that uniquely pairs a single user with a particular client_id. When you receive the sub, you will store this unique ID in your user database for reference. Do not transmit this sub to your client app.

Sample Token Response:

HTTP/1.1 200 OK
Content-type: application/json
Cache-control: no-cache

{
    "access_token": "....",
    "token_type": "Bearer",
    "refresh_token": "8xLOxBtZp8",
    "expires_in": 3600,
    "correlation_id”:”xxxxx”,
    "id_token": "..."
}
Decode ID Token

The ID Token will need to be decoded. Once you decode the JWT payload, you will see it contains claims about the authentication of your end user. As a best practice, you should always validate the ID Token after you have decoded it. Specifically, you should verify the signature and claims contained within the ID Token. For more information about each parameter, refer to our Server and Web Integration Guide.

Sample Decoded ID Token:

{   
    "type"="at+jwt",  
    "kid":"xxx"
}

{
    "iss": https://mno.com,
    "sub": "mccmnc-client0001",  
    "aud": "ccid-sp00001",
    "nonce": "n-0S6_WzA2Mj",
    "exp": 1311281970,
    "iat": 1311280970,
    "auth_time": 1311280969,
    "acr": "a3",
    ...
}

12. Request User Info

Upon receiving an Access Token, you may then request user info by issuing a GET request from your backend to the userinfo_endpoint discovered in Step 9.

GET /userinfo HTTP/1.1
Host: mno.com
Authorization: bearer {ACCESS_TOKEN}

The response will contain JSON with the user information requested by your scopes and approved by the user.

{

    "sub": "mccmnc-123456789",  
    "name": "Jane Doe",  
    "given_name": "Jane",  
    "family_name": "Doe",  
    "email": "janedoe@example.com",  
    "email_verified":"true",  
    "postal_code": "90210-3456",  
    "phone_number": "+13101234567",  
    "phone_number_verified":"true"  
}

Next Steps

If you don't want to set up ZenKey just yet, feel free to explore a few sample calls on our Developer Playground. This environment will help you to learn about each step in the authorization process.

ZenKey Developer Playground

For more specific information about the ZenKey app and SDK, visit the resources listed below:

Revision History

Date Published Document Version ZenKey SDK Version Description
1.31.20 0.0.01 1.0.0 First published version.

Last Update: Document Version 0.0.01, January 30, 2020