Custom SMS error display

Feb 23 at 11:28 AM
We've implemented custom SMS MFA using provided sample.
However, it is not clear how to alert the user in case if SMS sending was not successful (e.g. SMS gateway servers are down).

It is pretty straightforward that Windows Event Log event can be generated to alert system administrators, so they will look and fix the issue - but the end user is not aware that his SMS will never arrive.

Looks like return value of GetUserCodeWithExternalSystem() method is never actually used or checked.

Any hints here?
Feb 23 at 8:27 PM
Hi KKorn

I'll try to give you a few inputs.

Before talking about code, I would give you some information.

We have chosen to not implement sending SMS but to provide an API for several reasons:
  • We consider (like many security experts) that sending code TOTP via mobile phone is not secure.
    NIST is no longer recommending two-factor authentication systems that use SMS, because of their many insecurities.
    In the latest draft of its Digital Authentication Guideline, there's the line:
    using SMS is deprecated, and will no longer be allowed in future releases of this guidance.
in the example made with Azure MFA (PhoneFactor sms provider), we have disabled the function TWO_WAY (reception and return of the code over the phone) because he arrived we got 2 times a code from 2 different numbers.
Microsoft should be a little more strict in this case... it's operators who returns the code "à la main" ?? or the NSA :)
  • to stay more secure, the API requires that the user types code in the page after having received an sms.
  • There are a lot of suppliers allowing the sending of sms, all have their own API, often based on a request/response soap or rest call, there is no guarantee the quality of service.
About the IExternalOTPProvider API
  • is very basic, sending user information, user Culture, and the info to connect to the provider (the configuration file CDATA)
  • returning a positive code, this is the TOTP transmitted by SMS and notified by the provider
  • returning 0, there's an error (no detail is provided to the user notifying simply invalid authentication)
  • This API launched by a Task is synchronous. so it's to your implementation to manage the delivery of the various parameters of calls and provide effective receipt of a valid code.
Azure / PhoneFactors
  • Based on the SDK provided, but largely cleaned...
  • A synchronous message is sent and waits for a response using a mutex.
  • There is no specific timeout on the mutex, what duration to choose ? 5 minutes ? as on emails ? but it's possible
  • CreateMessage -> authentication phase for the supplier // no timeout on the mutex
  • SendMessage -> transmission phase of message requesting the code // synchronous
    • ReceiveResponse -> receive the code (loop with a mutex in case of error)
/// <summary>
    /// InternalAuthenticate method implementation 
    /// </summary>
    private static bool InternalAuthenticate(PhoneFactorParams pfAuthParams, bool asynchronous, out string otp, out int call_status, out int error_id)
        if (pfAuthParams.CountryCode.Length == 0) 
            pfAuthParams.CountryCode = "1";
        if (pfAuthParams.Hostname.Length == 0) 
            pfAuthParams.Hostname = "adfsmfa-hostname";
        if (pfAuthParams.IpAddress.Length == 0) 
            pfAuthParams.IpAddress = "";
        pfAuthParams.Mode = pfAuthParams.Mode.ToLower();
        if (pfAuthParams.Mode != MODE_SMS_TWO_WAY_OTP && pfAuthParams.Mode != MODE_SMS_TWO_WAY_OTP_PLUS_PIN  && pfAuthParams.Mode != MODE_SMS_ONE_WAY_OTP && pfAuthParams.Mode != MODE_SMS_ONE_WAY_OTP_PLUS_PIN)
            pfAuthParams.Mode = MODE_SMS_ONE_WAY_OTP;

        otp = "";
        call_status = 0;
        error_id = 0;

        string auth_message = CreateMessage(pfAuthParams, asynchronous);

        int tries = 1;
        if (mMutex.WaitOne()) // __Here you can specify a timeout__ : mMutex.WaitOne(300000) // 5 minutes
                tries = mTargets.Count + 1; 
        for (int i = 0; i < tries; i++)
            string response;
            if (SendMessage(mCurrentTarget, auth_message, out response))
                string request_id_out = "";
                bool authenticated = ReceiveResponse(response, out request_id_out, out otp, out call_status, out error_id);
                return authenticated;
                if (mMutex.WaitOne()) // __Here you can specify a timeout__ : mMutex.WaitOne(300000) // 5 minutes
                        mCurrentTarget = mTargets.Dequeue().ToString();
        return false;
Note that we use a nuget package to validate the format of the phone number transmited.
If your user do not receive the code perhaps the phone number is not valid or transmitted to another person in the world !

You can debug your extension with Visual Studio Remote Debugger. attach to process Microsoft.IdentityServer.ServiceHost.exe

We hope this can help you

Feb 24 at 10:52 AM
Hi KKorn

Yes, you're right !
There's nos status displayed to the user when sending emails or sms.
Let us few days to implement a status page for the user, and timeout parameter for the api.

Thank you
Feb 24 at 11:12 AM
Hi redhook!
Thanks, will wait for the fix.
Also, what we want to check here is a rather simple thing - if SMS gateway API has not failed right at this moment (e.g. we POST-ed a request and got a "500 internal server error" in reply). It is usually a matter of tenths of second to get that status - so no complex mutex waiting logic is needed.
Querying for SMS status and confirming delivery is indeed a non-trivial task, and thankfully it is not what we need now.
Feb 26 at 9:24 PM
Hi KKorn

A new version is available (
See remarks in download page

Mar 15 at 1:31 PM
Thanks a lot, now it is much more clear to the user if it does not make sense to wait for SMS if it failed.

Also, as the error message text is "Error sending toast notification : {0}", is there any intent to customize the message displayed in some future version?
May 13 at 9:25 PM

We have working hard to provide a new version for this summer (perhaps we post a beta version in june).

The message are compiled in ressources files, so, for performance and security reasons it's not possible to change messages without modifying the ressources files and Rebuild a new Version.

If you don't want to make your own solution, i propose that you can send to us the translations et messages you like to have.
But these translations must remain "generic".

Marked as answer by redhook on 6/21/2017 at 10:46 AM