This pages shows you how to setup .Net Demo (Server Side SDK) App using discovery and without discovery.

Content:

  • Configuring and running Demo App in With Discovery Mode
  • Using Mobile Connect Server Side SDK With Discovery
  • Configuring and running Demo App in Without Discovery Mode
  • Using Mobile Connect Server Side SDK Without Discovery
  • Using common Mobile Connect Server Side SDK functionality
  • Configuring and running the server side SDK in With Discovery Mode

    1. Register an account or login to the Mobile Connect Developer Portal and create an application to obtain your sandbox credentials.
    2. Download the Mobile Connect server side project.

      git clone https://github.com/Mobile-Connect/.net_server_side_library.git
    3. Note: if you operate in the EU then you should use EU Discovery Service domain in discovery url: https://eu.discover.mobileconnect.io.

      Open the configuration file: [local path]\mobile-connect-demos\GSMA.MobileConnect.Demo.ServerSide\App_Data\OperatorData.json to pass required parameter values for with discovery mode.

      Here are 11 parameters:

      {
        "clientID": your client Id,
        "clientSecret": your client Secret,
        "clientName": your client Name,
        "discoveryURL": your Discovery endpoint,
        "redirectURL": "<protocol>://<hostname>/server_side_api/discovery_callback",
        "xRedirect": "True",
        "includeRequestIP": "False",
        "apiVersion": api version: "mc_v1.1", "mc_v2.0" or "mc_di_r2_v2.3",
        "scope": scope,
        "acrValues":  acr_values,
        "MaxDiscoveryCacheSize": max cache size
      }

    4. Open sector_identifier_uri.json file and specify the value of sector_identifier_uri with a single JSON array of redirect_uri values.
      ["<protocol>://<hostname>/server_side_api/discovery_callback"]
    5. Download and install any missing dependencies.
    6. Build the project. You can configure your application (clientID, clientSecret, discoveryURL, redirectURL). You can also configure your parameters for auth request (xRedirect, . includeRequestIP, apiVersion, scope, acrValues). And You can configure cache size (maxDiscoveryCacheSize) and if you want to run or not to run get user info request and get identity request (userInfo, identity).
    7. Run GSMA.MobileConnect.ServerSide.Web or publish using 'Web Deploy' and deploy application to your server using IIS
    8. Prepare client side application (IOS or Android application) or Demo App for Server Side application.

    Using Mobile Connect Server Side SDK with Discovery

    Client side application allows to sends a request to server side application in three modes: msisdn, mcc_mnc, none

    Example request:
    If you are using only msisdn the request to your server side part will be: http://localhost:8080/server_side_api/start_discovery?msisdn=447700900907
    When you are using mcc and mnc it will be: http://localhost:8080/server_side_api/start_discovery?mcc=907&mnc=07
    If you choose None mode: http://localhost:8080/server_side_api/start_discovery
    Also sourceIp can be included to request: http://localhost:8080/server_side_api/start_discovery?sourceIp=10.0.0.7

    Client side application sends a GET request with client data to server side application. Then server side application makes StartDiscovery method call with your data from configuration file. This method calls AttemptDiscovery method with your parameters from config file. And then StartAuthentication method perfoms for getting authentication URL.

            [HttpGet]
            [Route("start_discovery")]
            public async Task<IHttpActionResult> StartDiscovery(string msisdn = "", string mcc = "", string mnc = "")
            {
                GetParameters();
                string sourceIp = Request.Headers.Any(h => h.Key.Equals("X-Source-IP")) ?
                    Request.Headers.GetValues("X-Source-IP").ToList().FirstOrDefault() :
                    string.Empty;
    
                var requestOptions = new MobileConnectRequestOptions { ClientIP = sourceIp };
    
                var status = await _mobileConnect.AttemptDiscoveryAsync(
                    Request, msisdn, mcc, mnc, false, _includeRequestIP, requestOptions);
    
                _requestMessage = Request;
    
                if (HandleErrorMsg(status) == true)
                {
                    status = await _mobileConnect.AttemptDiscoveryAsync(
                        Request, null, null, null, false, false, requestOptions);
                }
    
                if (status.DiscoveryResponse != null && 
                    status.DiscoveryResponse.ResponseCode == Utils.Constants.Response_OK)
                {
                    CachedParameters.sdkSession = status.SDKSession;
                    var authResponse = await StartAuthentication(
                        Request, status.SDKSession, status.DiscoveryResponse.ResponseData.subscriber_id);
    
                    return authResponse;
                }
                else
                {
                    return GetHttpMsgWithRedirect(status, status.ErrorCode);
                }
            }

    To generate the request parameters it uses GetParameters method:

    public void GetParameters(string clientID = "", string clientSecret = "", string discoveryURL = "", string redirectURL = "",
                string xRedirect = "", string includeRequestIP = "", string scope = "", string apiVersion = "")
            {
                _apiVersion = apiVersion;
                _includeRequestIP = includeRequestIP.Equals("True");
                _cache = new ConcurrentCache();
                _restClient = new RestClient();
                _mobileConnectConfig = new MobileConnectConfig()
                {
                    ClientId = clientID,
                    ClientSecret = clientSecret,
                    DiscoveryUrl = discoveryURL,
                    RedirectUrl = redirectURL,
                    XRedirect = xRedirect.Equals("True") ? "APP" : "False"
                };
                _mobileConnect = new MobileConnectWebInterface(_mobileConnectConfig, _cache, _restClient);
            }

    Note:If discovery request with msisdn, mcc_mnc or source ip fails - method perform Discovery UI flow to discover operator.

    1) If you selected the msisdn mode: stateDiscoveryCallback method is called. This method calles HandleUrlRedirectAsync (where a token will receive) and also RequestIdentity or RequestUserInfo if it was specified in the configuration. After you follow the redirect, and pass consent confirmation screen, redirect will be proceed by server side DiscoveryCallback method:

         
    
    [HttpGet]
            [Route("discovery_callback")]
            public async Task<IHttpActionResult> DiscoveryCallback(
                string state = null, 
                string error = null, 
                string description = null)
            {
                if (!string.IsNullOrEmpty(error))
                {
                    if (!string.IsNullOrEmpty(state))
                    {
                        return await StartDiscovery();
                    }
    
                    return CreateResponse(MobileConnectStatus.Error(error, description, new Exception()));
                }
    
                var requestOptions = new MobileConnectRequestOptions
                {
                    AcceptedValidationResults = Authentication.TokenValidationResult.Valid |
                        Authentication.TokenValidationResult.IdTokenValidationSkipped
                };
    
                var cachedInfo = responseChecker.getData(state);
                var authConnectStatus = await _mobileConnect.HandleUrlRedirectAsync(
                    Request, 
                    Request.RequestUri, 
                    cachedInfo.Result.sdkSession, 
                    state,
                    cachedInfo.Result.nonce, 
                    requestOptions);
    
                if (HandleErrorMsg(authConnectStatus))
                {
                    RemoveSessionFromCache(discoveryCache, cachedInfo.Result.discoveryOptions);
                    return CreateResponse(MobileConnectStatus.Error(
                        ErrorCodes.InvalidArgument, authConnectStatus.ErrorMessage, new Exception()));
                }
    
                MobileConnectStatus response = null;
                var idTokenResponseModel = 
                    JsonConvert.DeserializeObject<IdTokenResponse>(authConnectStatus.TokenResponse.DecodedIdTokenPayload);
    
                if (idTokenResponseModel.nonce.Equals(cachedInfo.Result.nonce))
                {
                    if (_operatorParams.identity.Equals("True"))
                    {
                        response = await RequestUserInfo(state, authConnectStatus.TokenResponse.ResponseData.AccessToken);
                        return CreateIdentityResponse(response, authConnectStatus);
                    }
                    else if (_operatorParams.userInfo.Equals("True"))
                    {
                        response = await RequestIdentity(state, authConnectStatus.TokenResponse.ResponseData.AccessToken);
                        return CreateIdentityResponse(response, authConnectStatus);
                    }
                }
                else
                {
                    response = MobileConnectStatus.Error(
                        ErrorCodes.InvalidArgument, "nonce is incorrect", new Exception());
                }
    
                return CreateResponse(response);
            }

    2) mcc_mnc mode.
    3) none mode.

    If you selected the mcc_mnc mode or none mode:
    you will be redirected to the operator selection page. Here you can type your msisdn and process page.
    After getting URL with code and state parameters application calls token endpoint with received data and get token, that could be used in authentication process in your web application. This is proceed by MCC_MNC_DiscoveryCallback method.

      
    [HttpGet]
            [Route("discovery_callback")]
            public async Task<IHttpActionResult> MCC_MNC_DiscoveryCallback(string mcc_mnc, string subscriber_id = "")
            {
                var requestOptions = new MobileConnectRequestOptions { ClientIP = "" };
                var mcc_mncArray = mcc_mnc.Split(new char[] { '_' });
                var mcc = mcc_mncArray[0];
                var mnc = mcc_mncArray[1];
                var status = await _mobileConnect.AttemptDiscoveryAsync(
                    _requestMessage, "", mcc, mnc, true, _includeRequestIP, requestOptions);
    
                if (status.DiscoveryResponse != null)
                {
                    CachedParameters.sdkSession = status.SDKSession;
                    var authResponse = await StartAuthentication(
                        _requestMessage, status.SDKSession, subscriber_id);
                    return authResponse;
    
                  
                }
                else
                {
                    return GetHttpMsgWithRedirect(status, status.ErrorMessage);
                }
            }

    Discovery caching

    Discovery response is cached in server side with following rules:
    1) After succeed Discovery request, Discovery response is cached with used mcc/mnc, msisdn or sourceIp.
    2) Expiration time for Discovery Response cache is the same as "ttl" field in Discovery Response - if Discovery Response expired - that deleted from cache.
    3) Next requests for Discovery with the same mcc/mnc, msisdn or sourceIp - Discovery request shouldn't be performed, Discovery response should be taken from cache.
    4) If auth call respond with error - Discovery Response deleted from cache, and server side redirect you to Discovery UI.

    Using Mobile Connect Authentication/Authorisation

    The server side 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). Y

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

    • client_name – specifies the name of the application/service requesting authorisation.
    • 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

    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.

    private string StartAuth(
                DiscoveryResponse discoveryResponse, 
                string subscriberId,
                HttpRequestMessage request,
                string msisdn,
                string mcc,
                string mnc,
                string sourceIp)
            {
                string scope = OperatorParams.scope;
    
                var options = new MobileConnectRequestOptions
                {
                    Scope = scope,
                    Context = ApiVersion.Equals(Utils.Constants.VERSION2_0) || ApiVersion.Equals(Utils.Constants.VERSION2_3) ? Utils.Constants.ContextBindingMsg : null,
                    BindingMessage = ApiVersion.Equals(Utils.Constants.VERSION2_0) || ApiVersion.Equals(Utils.Constants.VERSION2_3) ? Utils.Constants.ContextBindingMsg : null,
                    ClientName = OperatorParams.clientName,
                    AcrValues = OperatorParams.acrValues
                };
    
                var status =
                    MobileConnect.StartAuthentication(request, discoveryResponse, subscriberId, null, null, options, ApiVersion);
    
                if (HandleErrorMsg(status))
                {
                    return null;
                }
    
                SetSessionCache(status, msisdn, mcc, mnc, sourceIp);
                return status.Url;
            }
    
            private void GetParameters()
            {
                OperatorParams = ReadAndParseFiles.ReadFile(Utils.Constants.OperatorDataFilePath);
                ApiVersion = OperatorParams.apiVersion;
                IncludeRequestIp = OperatorParams.includeRequestIP.Equals("True");
    
                MobileConnectConfig = new MobileConnectConfig()
                {
                    ClientId = OperatorParams.clientID,
                    ClientSecret = OperatorParams.clientSecret,
                    DiscoveryUrl = OperatorParams.discoveryURL,
                    RedirectUrl = OperatorParams.redirectURL,
                    XRedirect = OperatorParams.xRedirect.Equals("True") ? "APP" : "False"
                };
            }

    Also, please, see

  • Using common Mobile Connect Server Side SDK functionality
  • Configuring and running the server side SDK in Without Discovery Mode

    1. Register an account or login to the Mobile Connect Developer Portal and create an application to obtain your sandbox credentials.
    2. Download the Mobile Connect server side project.

      git clone https://github.com/Mobile-Connect/.net_server_side_library.git
    3. Note: if you operate in the EU then you should use EU Discovery Service domain in discovery url: https://eu.discover.mobileconnect.io.

      Open the configuration file: [local path]\mobile-connect-demo\src\main\resources\config\OperatorData.json to pass required parameter values for without discovery mode:

      {
        "clientID": your client Id,
        "clientSecret": your client Secret,
        "clientName": your client Name,
        "discoveryURL": your Discovery endpoint,
        "redirectURL": "<protocol>://<hostname>/server_side_api/discovery_callback",
        "xRedirect": "True",
        "includeRequestIP": "True",
        "apiVersion": api version: "mc_v1.1", "mc_v2.0" or "mc_di_r2_v2.3",
        "scope": scope,
        "acrValues": acr_values,
        "MaxDiscoveryCacheSize": max cache size,
        "operatorUrls": {
          "authorizationUrl": authorize endpoint,
          "requestTokenUrl": token endpoint,
          "userInfoUrl": userinfo endpoint,
          "premiumInfoUri": premiuminfo endpoint,
          "providerMetadataUri": provider metadata endpoint
        }
      }

    4. Open sector_identifier_uri.json file and specify the value of sector_identifier_uri with a single JSON array of redirect_uri values.
      ["<protocol>://<hostname>/server_side_api/discovery_callback"]
    5. Download and install any missing dependencies.
    6. Build the project. You can configure your application (clientID, clientSecret, discoveryURL, redirectURL). You can also configure your parameters for auth request (xRedirect, . includeRequestIP, apiVersion, scope, acrValues). And You can configure cache size (maxDiscoveryCacheSize) and if you want to run or not to run get user info request and get identity request (userInfo, identity).
    7. Run GSMA.MobileConnect.ServerSide.Web or publish using 'Web Deploy' and deploy application to your server using IIS
    8. Prepare client side application (IOS or Android application) or Demo App for Server Side application.

    Using Mobile Connect without Discovery

    The server side SDK allows you to call methods that get additional parameters from a JSON configuration file. Once the end user has entered MSISDN and intitiated session from the client side, the server side SDk builds the call to the Authorize endpoint. A successful authentication returns an id_token containing the user’s PCR, which is unpacked and available for verification against your user register.

    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 async Task<DiscoveryResponse> MakeDiscoveryForAuthorization(string clientId, string clientSecret,
                string appName, OperatorUrls operatorsUrl)
            {
                Validate.RejectNullOrEmpty(clientId, "clientId");
                Validate.RejectNullOrEmpty(clientSecret, "clientSecret");
                Validate.RejectNull(operatorsUrl, "operatorsUrl");
    
                var discoveryService = new DiscoveryService(new DiscoveryCache(), _client);
    
                var providerMetadata = new ProviderMetadata();
    
                var discoveryGenerateResponseOptions = new DiscoveryResponseGenerateOptions(clientSecret, clientId, appName, operatorsUrl.GetListOfUrls(), operatorsUrl.GetListOfRels());
    
                var restResponse = new RestResponse()
                {
                    StatusCode = HttpStatusCode.OK,
                    Content = discoveryGenerateResponseOptions.GetJsonResponse()
                };
    
                try
                {
                    var index = 0;
                    var length = discoveryGenerateResponseOptions.Response.response.apis.operatorid.link.Count;
                    for (var i = 0; i < length; i++)
                    {
                        if (discoveryGenerateResponseOptions.Response.response.apis.operatorid.link[i].rel != LinkRels.OPENID_CONFIGURATION) continue;
                        index = i;
                        break;
                    }
    
                    var providerMetadataLink = discoveryGenerateResponseOptions.Response.response.apis.operatorid.link[index].href;
    
                    if (providerMetadataLink != null)
                    {
                        providerMetadata = await discoveryService.RetrieveProviderMetada(providerMetadataLink);
                    }
                }
                catch (Exception exception)
                {
    
                    throw exception;
                }
    
                var discoveryResponse = new DiscoveryResponse(restResponse);
                discoveryResponse.ProviderMetadata = providerMetadata;
    
                return discoveryResponse;
            }

    Using Mobile Connect Authentication/Authorisation

    Client side application sends a GET request with MSISDN to server side application.
    Example request:

    http://localhost:8080/server_side_api/start_discovery_manually?msisdn=your_msisdn

    Then server side application makes StartAuthenticationWithoutDiscovery method call for getting authentication URL.

       public async Task<IHttpActionResult> StartAuthenticationWithoutDiscovery(string msisdn = "")
            {
                MobileConnect = new MobileConnectWebInterface(MobileConnectConfig, SessionCache, DiscoveryCache);
                GetParameters();
    
                DiscoveryResponse discoveryResponse = null;
                MobileConnectStatus status;
    
               
                discoveryResponse = await MobileConnect.GenerateDiscoveryManually(OperatorParams.clientID, OperatorParams.clientSecret, OperatorParams.clientName, OperatorParams.operatorUrls);
    
                string url = CallStartAuth(discoveryResponse, msisdn, Request);
    
                return GetHttpMsgWithRedirect(url);
            }

    Authentication/Authorize mechanism, the mechanism of sending the token request and making calls to the Identity and UserInfo endpoints are similar to mechanisms in modes that support discovery requests.

    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 server side provides constants that you can pass when requesting specific Identity products:

    • Identity: Phone Number – MOBILECONNECTIDENTITYPHONE
    • Identity: Sign-up – MOBILECONNECTIDENTITYSIGNUP
    • Identity: National Identity – MOBILECONNECTIDENTITYNATIONALID

    Upon successful authorisation, the server side 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.