Show TOC

CustomCertificateProvider.javaLocate this document in the navigation structure

The example X.509 CustomCertificateProvider implements the  <CertificateProvider>  protocol, and so there are sample implementations for each of the methods previously described.

This section provides the example code, and walks through the flow of the example, from handling getCertificate and displaying a screen to the end user with showUI, to returning an X.509 key manager for getStoredCertificate requests, and clearing the key manager in response to deleteStoredCertificate requests.

package com.example.certificatefromfileprovider;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.net.ssl.X509KeyManager;

import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.sap.maf.html5.android.MAFLogonCoreCDVPlugin;
import com.sap.maf.tools.logon.core.LogonCore;
import com.sap.maf.tools.logon.core.LogonCoreException;
import com.sap.smp.client.android.certificateprovider.CertificateProvider;
import com.sap.smp.client.android.certificateprovider.CertificateProviderException;
import com.sap.smp.client.android.certificateprovider.CertificateProviderListener;

public class CustomCertificateProvider implements CertificateProvider {
  private CertificateProviderListener _callback = null;
  private String _alias = "smp_crt";
  private String _filePath = null;
  private String _certPwd = null;

  @Override
  public void getCertificate(CertificateProviderListener callback) {
    _callback = callback;
    try {
      // This map contains the view ID, as well as any information the view might need
      HashMap<String, Object> map = new HashMap<String, Object>();
      map.put(MAFLogonCoreCDVPlugin.VIEW_ID, "x509ProviderUI");
      // Now add a default value that will be displayed on the view.
      // This value is used in x509ProviderUI.view.js
      JSONObject settings = new JSONObject();
      try {
        settings.put("filepath", "certificate.p12");
      } catch (JSONException e) {
        // print exception to Logcat for debugging
        e.printStackTrace();
      }
      map.put("settings", settings);
      _callback.showUI(map);
    } catch (CertificateProviderException e) {
      // print exception to Logcat for debugging
      e.printStackTrace();
    }
  }

  @Override
  public void setParameters(Map parameters) {

    // Log the content of the parameters Map for debugging
    Log.e("CustomCertificateProvider", "setParameters called");
    Set keys = parameters.keySet();
    Iterator it = keys.iterator();
    while (it.hasNext()) {
      Object key = it.next();
      // assuming both key and value are strings
      Log.e("CustomCertificateProvider", "key: " + (String) key
        + " value: " + (String) parameters.get(key));
    }

    _filePath = (String) parameters.get("filepath");
    _certPwd = (String) parameters.get("password");

    try {
      CustomKeyManager keyManager = new CustomKeyManager(_filePath, _certPwd, _alias);
      _callback.onGetCertificateSuccess(keyManager);
      // We won't be able to save the filepath and password to the logon core's datavault
      // before we are registered (since it won't exist at that point) but we can save
      // the values there later.
      LogonCore logonCore = LogonCore.getInstance();
      logonCore.addObjectToStore("CustomFileCertificateProvider_filePath", _filePath);
      logonCore.addObjectToStore("CustomFileCertificateProvider_certPwd", _certPwd);
    } catch (Exception e) {
      // print exception to Logcat for debugging
      e.printStackTrace();
    }
  }

  @Override
  public void deleteStoredCertificate() {
    // We're not actually going to try to delete the certificate off the filesystem.
    // Just get rid of the values we got from the user.
    _filePath = null;
    _certPwd = null;
  }

  @Override
  public X509KeyManager getStoredCertificate() {
    X509KeyManager keyManager = null;
    if (_filePath == null) {
      // If we don't have a value for the filepath, check the logon core's datavault
      // in case we previously saved the values there.
      LogonCore logonCore = LogonCore.getInstance();
      try {
        _filePath = logonCore.getObjectFromStore("CustomFileCertificateProvider_filePath");
        _certPwd = logonCore.getObjectFromStore("CustomFileCertificateProvider_certPwd");
      } catch (LogonCoreException e) {
        // print exception to logcat for debugging
        e.printStackTrace();
      }
    }
    if (_filePath != null) {
      try {
        keyManager = new CustomKeyManager(_filePath, _certPwd, _alias);
      } catch (Exception e) {
	// print exception to Logcat for debugging
        e.printStackTrace();
      }
    }
    return keyManager;
  }

  @Override
  public void initialize(CertificateProviderListener arg0) throws CertificateProviderException {
    // If the certificate provider is used in the non-SMP case, this
    // function will be called instead of getCertificate. When
    // initialization is complete the provider must be prepared to return a
    // certificate synchronously when getStoredCertificate is called. To
    // indicate initialization is complete, call initializationComplete on
    // the CertificateProviderListener argument object.
    // This example has been implemented for the SMP registration case.
  }
}
getCertificate

When the Logon plugin is registering the application connection (a one-time event which results in the creation of a persistant X-SMP-APPCID cookie), if the UserCreationPolicy is set to "certificate", it calls getCertificate on the CertificateProvider.

setParameters

The example of the sap.ui.jsview is included in the  sample/CredentialProvider/resource  folder, but the key flow to understand is that within the view, the "Submit" button passes the JSON data from the view to an In-App Browser ("iab") event, which is captured by the Logon Plugin. The Logon Plugin then passes the JSON data to the certificate provider through setParameters.You can re-use this flow in your application that uses JavaScript or HTML views.

getStoredCertificate

The getCertificate method is intended for asynchronous, long-running tasks, which may require UI display. the getStoredCertificate method is intended for synchronous, short-running tasks, which do not require UI.

If the CertificateProvider calls a 3rd-Party API to get the identity (for example, a component that stores the keys in an encrypted blob), implement the API to return success or failure quickly. If it returns failure, then getStoredCertificate should return an error to the caller, and the Logon plugin will call the asynchronous getCertificate.

deleteStoredCertificate

Manage certificate validity on the server side — at the network edge, SAP Mobile Platform, or backend. If a certificate is expired, revoked, or otherwise invalid, a request using that certificate will get an HTTP Request Authentication error. The application should catch these invalid certificate errors, and call the refreshCertificate method exposed by the Logon plugin. When refreshCertificate is called, it will invoke this deleteStoredCertificate method.