This example demonstrates how to integrate The SDK.

Download the Mobile Connect server side SDK project

Download the Mobile Connect server side project that contains the SDK and demo server side controller.

git clone https://github.com/Mobile-Connect/java_server_side_library.git

Note: Common steps for configuration and running the server side SDK: Java Server Side SDK setup.

Using the SDK

The Mobile Connect SDK for Java automates much of the basic housekeeping and configuration tasks of your application’s integration with Mobile Connect. Many of these functions activate in the Discovery phase, independently of the Identity Gateway endpoint your application will ultimately call, and so are described here for your reference.

Discovery

Discovery is the process of determining an end-user's Mobile Connect Identity Provider, i.e. the Operator ID Gateway. The discovery response will provide with a number of endpoints and the operator specific credentials which will need to use with this ID Gateway.
The SDK has a method that accepts user's data as parameters and needs MobileConnectConfig object initialized as part of the MobileConnectWebInterface object - that's enough to make a successful call to the Mobile Connect Discovery endpoint, and the methods attemptDiscovery and handleUrlRedirect do just that, building and making the call, and then handling the response. The SDK also takes care of caching the response for re-use in a subsequent call – subject to the configured timeout.

The attemptDiscovery method build and make discovery call:

    public MobileConnectStatus attemptDiscovery(final HttpServletRequest request,
        final String msisdn, final String mcc, final String mnc, final boolean shouldProxyCookies, final boolean includeRequestIP,
        final MobileConnectRequestOptions options)
    {
        LOGGER.info("**************************************************************\nmsisdn: " + msisdn + " \nmcc: " + mcc + " \nmnc: "+ mnc);
        ObjectUtils.requireNonNull(request, ARG_REQUEST);

        final String clientIp =
                includeRequestIP ? HttpUtils.extractClientIp(request) : null;

        final DiscoveryOptions.Builder builder =
            options == null ? new DiscoveryOptions.Builder() : options.getDiscoveryOptionsBuilder();

        final Iterable<KeyValuePair> cookies =
            shouldProxyCookies ? HttpUtils.extractCookiesFromRequest(request) : null;

        LOGGER.debug(
            "Running attemptDiscovery for msisdn={}, mcc={}, mnc={}, shouldProxyCookies={}, includeRequestIP={}, clientIp={}",
            LogUtils.mask(msisdn, LOGGER, Level.DEBUG), mcc, mnc, shouldProxyCookies, includeRequestIP, clientIp);

        final MobileConnectStatus status =
            MobileConnectInterfaceHelper.attemptDiscovery(this.discoveryService, msisdn, mcc, mnc,
                cookies, this.config, builder);

        return this.cacheIfRequired(status);
    }

The handleUrlRedirect method handle discovery response:

public MobileConnectStatus handleUrlRedirect(final HttpServletRequest request,
        final URI redirectedUrl, final DiscoveryResponse discoveryResponse,
        final String expectedState, final String expectedNonce,
        final MobileConnectRequestOptions options, final String currentVersion)
    {
        ObjectUtils.requireNonNull(request, ARG_REQUEST);

        LOGGER.debug(
            "Running handleUrlRedirect for redirectedUrl={}, expectedState={}, expectedNonce={}, clientIp={}",
            LogUtils.maskUri(redirectedUrl, LOGGER, Level.DEBUG), expectedState,
            LogUtils.mask(expectedNonce, LOGGER, Level.DEBUG), HttpUtils.extractClientIp(request));

        final MobileConnectStatus status;
        try {
            status = MobileConnectInterfaceHelper.handleUrlRedirect(this.discoveryService,
                this.jwKeysetService, this.authnService, redirectedUrl, discoveryResponse,
                expectedState, expectedNonce, this.config, options, this.jsonService,
                this.iMobileConnectEncodeDecoder,
                    VersionDetection.getCurrentVersion(currentVersion, getScopeFromOptions(options),
                            discoveryResponse.getProviderMetadata()));
        } catch (InvalidScopeException e) {
            return e.toMobileConnectStatus(currentVersion);
        }

        return this.cacheIfRequired(status);
    }

This SDK allows calls to Mobile Connect without first doing a Discovery call. It is a similar process to usual Mobile Connect Authentication but instead of calls to the Discovery Service a new function makeDiscoveryForAuthorization is used to create the discoveryOptions object.

To load the discoveryOptions object:

public DiscoveryResponse makeDiscoveryForAuthorization(final String clientSecret, final String clientKey, final String name, OperatorUrls operatorUrls)
            throws JsonDeserializationException
    {
        ObjectUtils.requireNonNull(clientSecret, "clientSecret");
        ObjectUtils.requireNonNull(clientKey, "clientKey");
        ObjectUtils.requireNonNull(name, "appName");
        ObjectUtils.requireNonNull(operatorUrls, "operator urls");

        discoveryCache = new DiscoveryCache.Builder().withJsonService(jsonService).build();
        discoveryService = new DiscoveryService.Builder()
                .withJsonService(jsonService)
                .withCache(discoveryCache)
                .withRestClient(restClient)
                .build();
        ProviderMetadata providerMetadata = new ProviderMetadata.Builder().build();
        DiscoveryResponseGenerateOptions discoveryResponseGenerateOptions = new DiscoveryResponseGenerateOptions.BuilderResponse()
                .withClientKey(clientKey)
                .withSecretKey(clientSecret)
                .withName(name)
                .withLinks(operatorUrls.getOperatorsUrls())
                .withRel(operatorUrls.getOperatorsRel()).build();

        MobileConnectRequestOptions mobileConnectRequestOptions = new MobileConnectRequestOptions.Builder()
                .withAuthOptionDiscoveryResponse(discoveryResponseGenerateOptions)
                .build();

        ObjectNode discoveryResponseWithoutRequest = mobileConnectRequestOptions.getDiscoveryResponseGenerateOptions().responseToJson();
        ObjectMapper mapper = new ObjectMapper();
        JsonNode discoveryResponseJSONTree;
        JsonNode linkToProviderMetadata = null;

        try {
            discoveryResponseJSONTree = mapper.readTree(discoveryResponseWithoutRequest.toString());
            int openIdIndex = 0;

            int max = discoveryResponseJSONTree.path("response").path("apis").path("operatorid").path("link").size();
            for (int index = 0; index < max; index++) {
                JsonNode openIdLink = discoveryResponseJSONTree.path("response").path("apis").path("operatorid").path("link").get(index).findValue("rel");
                String providerMetadataText = openIdLink.textValue();
                if (providerMetadataText.contains("openid-configuration")) {
                    openIdIndex = index;
                    break;
                }
            }
            linkToProviderMetadata = discoveryResponseJSONTree.path("response").path("apis").path("operatorid").path("link").get(openIdIndex).findValue("href");

            if (!linkToProviderMetadata.isNull()) {
                providerMetadata = discoveryService.retrieveProviderMetadata(URI.create(linkToProviderMetadata.asText()), true);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        final RestResponse post_response = new RestResponse.Builder()
                .withStatusCode(HttpStatus.SC_OK)
                .withContent(discoveryResponseWithoutRequest.toString())
                .build();

        DiscoveryResponse discoveryResponse = DiscoveryResponse.fromRestResponse(post_response, this.jsonService);
        discoveryResponse.setProviderMetadata(providerMetadata);

        return discoveryResponse;
    }

Provider Metadata

A successful call to the Mobile Connect Discovery endpoint returns the end user’s Mobile Network Operator (MNO) and describes the Mobile Connect services that MNO supports, via a URI to the MNO’s Provider Metadata. The metadata describes the Identity Gateway endpoints (Mobile Connect services) your application or service can use and how those endpoints are configured – for example, the response types an endpoint can return, the subject identifier types supported, or the Identity Services encryption algorithms in use.
Although Provider Metadata is the primary source of information detailing the Identity Gateway configuration, it does not change often, so a cached version can be used without risk of expired data causing errors. The Mobile Connect SDK handles both the querying of the Provider Metadata and the caching.

  • If the Provider Metadata URI returns no data, the cached metadata is used.
  • Where the cached data is out of date (defaulting to 15-minute intervals) a subsequent query of the URI is attempted, and in the event of a second failed response, expired cached data is used.
  • Should neither the cached data nor the Provider Metadata URI return data (such as an error upon first user login) default values are used.

Regardless of the source, the SDK parses the Provider Metadata into a discrete list of properties. See the OpenID Provider Metadata definition for a list of the metadata available, although you should note that Mobile Connect's implementation may not be exhaustive.
The ProviderMetadata object is available on DiscoveryResponse.ProviderMetadata.

Supported Services

Before your application or service can call an Identity Gateway endpoint (scope), you need to know if the MNO supports the scope you are calling. The SDK provides the method isMobileConnectServiceSupported(String scope) in the discoveryReponse, which can be accessed as follows:

boolean supported = discoveryResponse.isMobileConnectServiceSupported(“mc_authz mc_identity_signup”)

The method accepts a comma- or space-separated list of scopes, which it then checks against the list of supported scopes in the Provider Metadata.

  • If any of the passed scopes are not present in the metadata, the function returns false.
  • If the Provider Metadata is not available, or the scopes attribute is missing, null, or an empty string, the function returns an exception: Provider Metadata scopes unavailable.
  • Mobile Connect Version Compatibility

    The SDK implements version autodetection, this is a mechanism which helps to detect version by configuration parsing, provided values and additional analysis.

    Identify gateway supported versions:

    • If a Provider Metadata document is available then get a list of supported versions based on the mc_version value.
    • If the Provider Metadata document is not available the supported version will be mc_v1.1.

    Identify request version:

    • If the version value is not empty and the SDK supports this version (see note), then use this.
    • If the version value is empty or the SDK doesn’t support the selected version then the scope and list of supported versions (based the ID Gateway) will be analysed to detect the version of MC API, which can be used. Verification order:
      • If the list of supported versions contains mc_di_r2_v2.3 and the scope is valid for this version, then this version will be used.
      • Otherwise, if the list of supported versions contains mc_v2.0 and the scope is valid for this version, then this version will be used.
      • Otherwise, if list of supported versions contains mc_v1.1 and the scope is valid only for this version, then this version will be used.
      • Otherwise, if the list of supported versions contains only mc_v1.2 and the scope is valid for this version, then this version will be used (but a warning will indicate that version is deprecated).
      • If current scope doesn’t match with versions included in list of supported versions, the SDK will throw invalid scope exception.

    NOTE: mc_v1.1, mc_v1.2, mc_v2.0, mc_di_r2_v2.3 are supported.

    Versions and supported scopes:

    Version Supported Scopes
    mc_v1.1 "openid", "openid mc_india_tc", "openid mc_mnv_validate", "openid mc_mnv_validate_plus", "openid mc_attr_vm_share", "openid mc_attr_vm_share_hash"
    mc_v2.0 "openid mc_authn" "openid mc_authn", "openid mc_authz", "openid mc_identity_phonenumber", "opeind mc_identity_signup", "openid mc_identity_nationalid", "openid mc_india_tc", "openid mc_mnv_validate", "openid mc_mnv_validate_plus", "openid mc_attr_vm_share", "openid mc_attr_vm_share_hash"
    mc_di_r2_v2.3 "openid mc_authn" "openid mc_authn", "openid mc_authz", "openid mc_identity_phonenumber", "opeind mc_identity_signup", "openid mc_identity_nationalid", "openid mc_kyc_plain", "openid mc_kyc_hashed", "openid mc_india_tc", "openid mc_mnv_validate", "openid mc_mnv_validate_plus", "openid mc_attr_vm_share", "openid mc_attr_vm_share_hash"

    This algorithm is implemented in the VersionDetection class.

    The getCurrentVersion method takes three parameters:

    • version (from configuration)
    • scope (from configuration)
    • ProviderMetadata (from DiscoveryResponse).

    The method parses and verifies parameters and then returns the correct MC API version depending upon the conditions.

    public static String getCurrentVersion(String version, String scope, ProviderMetadata providerMetadata) throws InvalidScopeException {
            List<String> supportedVersions = getSupportedVersions(providerMetadata);
            if (version != null && isVersionSupported(version)) {
                if (!supportedVersions.contains(version)) {
                    LOGGER.warn(String.format("Check version. It might be unsupported ("%s")", version));
                }
                return version;
            } else {
                List<String> currentScopes = StringUtils.convertToListBySpase(scope);
                if (supportedVersions.contains(Version.MC_DI_R2_V2_3) & containsScopesV2_3(currentScopes)) {
                    return Version.MC_DI_R2_V2_3;
                } else if (supportedVersions.contains(Version.MC_V2_0) & containsScopesV2_0(currentScopes)) {
                    return Version.MC_V2_0;
                } else if (supportedVersions.contains(Version.MC_V1_1) & containsScopesV1_1(currentScopes)) {
                    return Version.MC_V1_1;
                } else if(supportedVersions.contains(Version.MC_V1_2) & supportedVersions.size() == 1 & containsScopesV2_0(currentScopes)) {
                    LOGGER.warn("Version is deprecated");
                    return Version.MC_V1_2;
                } else {
                    final InvalidScopeException scopeException = new InvalidScopeException(scope);
                    throw scopeException;
                }
            }
        }

    The VersionDetection.getCurrentVersion method calls in each method of MobileConnectInterface class to detect correct version.

    public MobileConnectStatus startAuthentication(final HttpServletRequest request,
            final DiscoveryResponse discoveryResponse, final String encryptedMsisdn, final String state,
            final String nonce, final MobileConnectRequestOptions options, final String currentVersion)
        {
            ...
    
            try {
                return MobileConnectInterfaceHelper.startAuthentication(this.authnService,
                    discoveryResponse, encryptedMsisdn, rState, rNonce, this.config, builder,
                        VersionDetection.getCurrentVersion(currentVersion, getScopeFromOptions(options),
                                discoveryResponse.getProviderMetadata()));
            } catch (InvalidScopeException e) {
                return e.toMobileConnectStatus(currentVersion);
            }
        }

    Using version the auto-detection mechanism in the MobileConnectInterface class ensures that the verifications and request generation in Authentication and Token Services are correct. Furthermore it allows the automatic processing of version, regardless of using only SDK or Server Side SDK.

    Mobile Connect Constants

    The SDK provides a number of constants for referencing the Mobile Connect services by scope. They are available at com.gsma.mobileconnect.r2.constants.scopes, and can be called using the following syntax:

    com.gsma.mobileconnect.r2.constants.scopes.MOBILE_CONNECT_IDENTITY_PHONE

    The above example calls the scope "openid mc_identity_phonenumber". You can pass multiple scopes as a space-separated string; the SDK will remove any duplicates before making the call to the Identity Gateway.

    The following constants are available:

    Mobile Connect Product Constant Identifier Literal Value
    Authentication MOBILE_CONNECT "openid"
    Authentication MOBILE_CONNECT_AUTHENTICATION "openid mc_authn"
    Authorisation MOBILE_CONNECT_AUTHORIZATION "openid mc_authz"
    Identity: Phone Number MOBILE_CONNECT_IDENTITY_PHONE "openid mc_identity_phonenumber"
    Identity: Signup MOBILE_CONNECT_IDENTITY_SIGNUP "openid mc_identity_signup"
    Identity: Signup Plus* MOBILE_CONNECT_IDENTITY_SIGNUPPLUS "openid mc_identity_signupplus"
    Identity: National ID MOBILE_CONNECT_IDENTITY_NATIONALID "openid mc_identity_nationalid"
    KYC Plain MOBILE_CONNECT_KYC_PLAIN "openid mc_kyc_plain"
    KYC Hashed MOBILE_CONNECT_KYC_HASHED "openid mc_kyc_hashed"
    ATTR VM Match MOBILE_CONNECT_ATTR_VM_MATCH "openid mc_attr_vm_match"
    ATTR VM Hash MOBILE_CONNECT_ATTR_VM_MATCH_HASH "openid mc_attr_vm_match_hash"

    *This constant is available to support possible future products.

    Login Hint Support

    You have the option to provide the login hint to the Identity Gateway using one of three formats: MSISDN, encrypted MSISDN, and PCR. Your decision on how to provide the login hint is governed by two factors:

    • The login hint formats supported by the Identity Gateway.
    • Whether you are a “Trusted Service Provider”; an unencrypted MSISDN is only accepted from a trusted provider – attempting to send one if you are not trusted returns an error.

    The Mobile Connect SDK provides functions to test for login hint support in the Identity Gateway, namely:

    • isSupportedForMSISDN
    • isSupportedForEncryptedMSISDN
    • isSupportedForPCR

    Each function checks the login_hint_methods_supported attribute in the Provider Metadata returned from the Discovery endpoint. Should the attribute be missing, the function checks the Mobile Connect Profile version supported.

    Once you have decided how to provide the login hint, the SDK offers a further three functions to build it for you:

    • generateForMSISDN (String MSISDN)
    • generateForEncryptedMSISDN (String encryptedMSISDN)
    • generateForPCR (String PCR)

    id_token Validation

    A successful response from the Identity Gateway includes an id_token – a JSON Web Token, which validates against a JSON Web Keyset (JWKS), available at a URL specified in the Provider Metadata attribute jwks_uri.

    The SDK performs a number of automatic validation actions to ensure the integrity of the response source, such as checking whether the token has expired. It also fetches the data from the jwks_uri location and stores it alongside the associated Discovery response, where it is cached. The following functions are then available to you to support id_token validation:

    • validateIdTokenSignature verifies the signature of the id_token based on the jwks_uri data. A validation returns TokenValidationResult
    • validateIdTokenClaims verifies the signature of the id_token claims. A validation returns TokenValidationResult
    • retrieveJWKS allows you to fetch all of the keys from the JWKS data.
    • returnMatchingJWKSEntries allows you to fetch specific keys matching the following parameters:

      • kty – key type (e.g. RSA)
      • alg – algorithm (e.g. RS256)
      • use – sig (signature) or enc (encryption)
      • kid – key identifier

    Using Mobile Connect Authorisation

    The SDK allows you to call the Identity Gateway with the scope parameter set to “mc_authz”, which signifies an authorisation request for a single transaction (the id_token and access token returned from the Gateway have a timeout set to zero, so expire after a single use).

    To make a successful authorisation call, you must provide the following additional parameters:

    • client_name – specifies the name of the application/service requesting authorisation. This value is taken from Options and must match the Application Short Name.
    • context – specifies the reason for the authorisation request, and should be built from the data describing the transaction requiring authorisation. The context is displayed on the authenticating (mobile) device only.
    • binding_message– specifies a reference string to display on the device from which the authorisation request was invoked, and on the authenticating (mobile) device, allowing the user to visually verify that the confirmation message originated from their transaction request.

    Note: the authorisation prompt displayed to the user combines all three parameters, which cannot exceed 93 bytes in total.

    The following example shows how to add the additional options to the authentication call described in Using Mobile Connect Authentication, resulting in a correctly configured call to the authorisation service.

    public MobileConnectStatus startAuthentication(final HttpServletRequest request,
            final DiscoveryResponse discoveryResponse, final String encryptedMsisdn, final String state,
            final String nonce, final MobileConnectRequestOptions options, final String currentVersion)
        {
            ObjectUtils.requireNonNull(request, ARG_REQUEST);
    
            final AuthenticationOptions.Builder builder = options != null
                                                          ? options.getAuthenticationOptionsBuilder()
                                                          : new AuthenticationOptions.Builder();
    
            final String rState =
                StringUtils.isNullOrEmpty(state) ? UUID.randomUUID().toString() : state;
            final String rNonce =
                StringUtils.isNullOrEmpty(nonce) ? UUID.randomUUID().toString() : nonce;
    
            LOGGER.debug(
                "Running startAuthentication for encryptedMsisdn={}, state={}, nonce={}, clientIp={}",
                LogUtils.mask(encryptedMsisdn, LOGGER, Level.DEBUG), rState,
                LogUtils.mask(rNonce, LOGGER, Level.DEBUG), HttpUtils.extractClientIp(request));
    
            try {
                return MobileConnectInterfaceHelper.startAuthentication(this.authnService,
                    discoveryResponse, encryptedMsisdn, rState, rNonce, this.config, builder,
                        VersionDetection.getCurrentVersion(currentVersion, getScopeFromOptions(options),
                                discoveryResponse.getProviderMetadata()));
            } catch (InvalidScopeException e) {
                return e.toMobileConnectStatus(currentVersion);
            }
        }

    After that client side makes redirects session and gets the code. Client side sends this code to the SDK, which uses this code for requestToken method performing.

    static MobileConnectStatus requestToken(final IAuthenticationService authnService,
            final IJWKeysetService jwKeysetService, final DiscoveryResponse discoveryResponse,
            final URI redirectedUrl, final String expectedState, final String expectedNonce,
            final MobileConnectConfig config, final MobileConnectRequestOptions options,
            final IJsonService jsonService,
            final IMobileConnectEncodeDecoder iMobileConnectEncodeDecoder)
        {
            ObjectUtils.requireNonNull(discoveryResponse, DISCOVERY_RESPONSE);
            StringUtils.requireNonEmpty(expectedState, "expectedState");
    
            long maxAge = extractMaxAge(options);
    
            if (!isUsableDiscoveryResponse(discoveryResponse))
            {
                return MobileConnectStatus.startDiscovery();
            }
    
            final String actualState = HttpUtils.extractQueryValue(redirectedUrl, "state");
            if (!expectedState.equals(actualState))
            {           
                return MobileConnectStatus.error("invalid_state",
                    "state values do not match, possible cross-site request forgery", null);
            }
            else
            {
                final String code = HttpUtils.extractQueryValue(redirectedUrl, "code");
                final String clientId = ObjectUtils.defaultIfNull(
                    discoveryResponse.getResponseData().getResponse().getClientId(),
                    config.getClientId());
                final String clientSecret = ObjectUtils.defaultIfNull(
                    discoveryResponse.getResponseData().getResponse().getClientSecret(),
                    config.getClientSecret());
                final String correlationId =
                        discoveryResponse.getResponseData().getCorrelationId();
                final String requestTokenUrl = discoveryResponse.getOperatorUrls().getRequestTokenUrl();
                final String issuer = discoveryResponse.getProviderMetadata().getIssuer();
    
                try
                {
                    final Future<RequestTokenResponse> requestTokenResponseFuture =
                        authnService.requestTokenAsync(clientId, clientSecret, correlationId,
                            URI.create(requestTokenUrl), config.getRedirectUrl(), code);
    
                    final RequestTokenResponse requestTokenResponse = requestTokenResponseFuture.get();
    
                    MobileConnectStatus status = processRequestTokenResponse(requestTokenResponse, expectedState,
                            expectedNonce, redirectedUrl, iMobileConnectEncodeDecoder, jwKeysetService,
                            discoveryResponse, clientId, issuer, maxAge, jsonService,
                            discoveryResponse.getProviderMetadata().getVersion());
                    return status;
                }
                catch (final Exception e)
                {
                    return MobileConnectStatus.error("request token", e);
                }
            }
        }

    If scope value maches "profile", "email", "adderss", "phone" or "mc_identity_phonenumber", "mc_identity_signup", "mc_identity_signupplus", "mc_identity_nationalid", "mc_kyc_plain", "mc_kyc_hashed", requestUserInfo or requestIdentity respectively will be performed and the JSON response will be returned as identity response in the the Token JSON response.

    Using Mobile Connect Identity and Attributes

    A successful call to the Authorisation endpoint returns an id_token identifying the user, and an access token that grants your application permission to request their personal information (referred to as Claims). This information contains a range of data; the exact data you can request is specified in the access token, and is limited to those Claims the end user has permitted as part of the original authorisation request.

    Note: the access token is for single use only, and expires immediately upon use.

    You request access to the Identity endpoint by specifying the appropriate scope. The SDK provides constants that you can pass when requesting specific Identity products:

    • Identity: Phone Number – MOBILE_CONNECT_IDENTITY_PHONE
    • Identity: Sign-up – MOBILE_CONNECT_IDENTITY_SIGNUP
    • Identity: National Identity – MOBILE_CONNECT_IDENTITY_NATIONALID

    Upon successful authorisation, the SDK provides an IdentityResponse with the user information JSON available as a property. The following example can be used to convert the JSON data to a class - IdentityData - which is provided with all recognised claims.

    final MobileConnectStatus response =
                this.mobileConnectWebInterface.requestIdentity(request, discoveryResponse, accessToken);
    
    final IdentityResponse identityResponse = response.getIdentityResponse();

    The following example shows how to add the additional Authorisation and Identity options to the Authentication call described in Using Mobile Connect Authentication, resulting in a correctly configured call to the Identity: Phone Number service.

    Note: calls to Identity: Sign-up and Identity: National ID are structured in exactly the same way, but using the scopes “mc_identity_signup” and “mc_identity_nationalid” as applicable.

    Add the MobileConnectRequestOptions required for Authorisation and Identity: Phone Number.

    Add the requestIdentity() and requestUserInfo() method calls to request the identity data following a successful authorisation.

    KYC Support for DI 2.3

    The SDK allows to use KYC product with the scope parameter set to "mc_kyc_plain" or "mc_kyc_hashed". Current version should be set to “mc_di_r2_v2.3”.
    To make a successful authorisation call, you must provide the KYC Claims that corresponds to the specified scope:

  • KYC Plain:
    final MobileConnectRequestOptions options = new MobileConnectRequestOptions.Builder()
                    .withAuthenticationOptions(new AuthenticationOptions.Builder()
                            .withScope("openid mc_kyc_hashed")
                            .withContext("demo context")
                            .withBindingMessage("demo binding")
                            .withClientName(clientName)
                            .withKycClaims(new KYCClaimsParameter.Builder()
                                    .withNameHashed(hashedName)
                                    .withAddressHashed(hashedAddress)
                                    .build())
                            .build())
                    .build();
  • KYC Hashed:
    final MobileConnectRequestOptions options = new MobileConnectRequestOptions.Builder()
                    .withAuthenticationOptions(new AuthenticationOptions.Builder()
                            .withScope("openid mc_kyc_hashed")
                            .withContext("demo context")
                            .withBindingMessage("demo binding")
                            .withClientName(clientName)
                            .withKycClaims(new KYCClaimsParameter.Builder()
                                    .withNameHashed(hashedName)
                                    .withAddressHashed(hashedAddress)
                                    .build())
                            .build())
                    .build();
  • You can use split claims "given_name", "family_name"; "houseno_or_housename", "postal_code", "town"; "given_name_hashed", "family_name_hashed"; "houseno_or_housename_hashed", "postal_code_hashed", "town_hashed" instead of concatenated "name"; "address"; "name_hashed"; "address_hashed". "birthdate" and "birthdate_hashed" are optional claims.
    The SDK performs a number of automatic claims validation:

    public StartAuthenticationResponse startAuthentication(final String clientId, String correlationId,
                                                               final URI authorizeUrl, final URI redirectUrl, final String state, final String nonce,
                                                               final String encryptedMSISDN, final SupportedVersions versions,
                                                               final AuthenticationOptions options, final String currentVersion)
        {
           ...
           if (options != null) {
                KYCClaimsParameter kycClaims = options.getKycClaims();
                if (kycClaims != null) {
                    boolean isNamePresent = false;
                    boolean isAddressPresent = false;
                    if (currentVersion.equals(DefaultOptions.MC_V2_3) && scope.contains(Scope.KYC_PLAIN)) {
                        isNamePresent = StringUtils.requireNonEmpty("name || given_name and family_name", kycClaims.getName(),
                                kycClaims.getGivenName(), kycClaims.getFamilyName());
                        isAddressPresent = StringUtils.requireNonEmpty("address || houseno_or_housename, postal_code, country, town",
                                kycClaims.getAddress(), kycClaims.getHousenoOrHousename(), kycClaims.getPostalCode(),
                                kycClaims.getCountry(), kycClaims.getTown());
                    }
                    if (currentVersion.equals(DefaultOptions.MC_V2_3) && scope.contains(Scope.KYC_HASHED)) {
                        isNamePresent = StringUtils.requireNonEmpty("name_hashed || given_name_hashed and family_name_hashed", kycClaims.getNameHashed(),
                                kycClaims.getGivenNameHashed(), kycClaims.getFamilyNameHashed());
                        isAddressPresent = StringUtils.requireNonEmpty("address_hashed || houseno_or_housename_hashed, postal_code_hashed, country_hashed, town_hashed",
                                kycClaims.getAddressHashed(), kycClaims.getHousenoOrHousenameHashed(), kycClaims.getPostalCodeHashed(),
                                kycClaims.getCountryHashed(), kycClaims.getTownHashed());
                    }
                    if ((isNamePresent & !isAddressPresent) | (!isNamePresent & isAddressPresent)) {
                        throw new InvalidArgumentException("(split|concatenated, plain|hashed) name or address is empty",
                                InvalidArgumentException.Disallowed.NULL_OR_EMPTY);
                    }
                }
            }
            ...
        }

    After successful validation claims are added to authorisation request as query parameter "claims". The value of claims parameter is presented as: {"premiuminfo": {"claim_name": {"value": "claim_value"}, ...}}
    Note: KYC product support is provided only by the Mobile Connect SDK. The mechanism of passing the claims is not integrated in the Server Side and should be implemented by Service Providers.