/// <summary> /// GetUserCodeWithExternalSystem method implementation for Azure MFA /// </summary> public int GetUserCodeWithExternalSystem(string upn, string phonenumber, string smstext, ExternalOTPProvider externalsys, CultureInfo culture) { ResourcesLocale Resources = new ResourcesLocale(culture.LCID); String NumberStr = phonenumber; int CountryCode = 0; ulong NationalNumber = 0; string extension = string.Empty; PhoneNumberUtil phoneUtil = PhoneNumberUtil.GetInstance(); PhoneNumber NumberProto = phoneUtil.Parse(NumberStr, culture.TwoLetterISOLanguageName.ToUpper()); CountryCode = NumberProto.CountryCode; NationalNumber = NumberProto.NationalNumber; if (NumberProto.HasExtension) { extension = NumberProto.Extension; } PhoneFactor.Initialize(externalsys); PhoneFactorParams Params = new PhoneFactorParams(); Params.Username = upn; Params.CountryCode = CountryCode.ToString(); Params.Phone = NationalNumber.ToString(); Params.Extension = extension; Params.ApplicationName = "IdentityServer"; Params.Sha1Salt = externalsys.Sha1Salt; if (externalsys.IsTwoWay) { Params.SmsText = string.Format(Resources.GetString(ResourcesLocaleKind.Azure, "SMSTwoWayMessage"), externalsys.Company); Params.Mode = PhoneFactor.MODE_SMS_TWO_WAY_OTP; } else { Params.SmsText = string.Format(Resources.GetString(ResourcesLocaleKind.Azure, "SMSMessage"), externalsys.Company); Params.Mode = PhoneFactor.MODE_SMS_ONE_WAY_OTP; } int callStatus; int errorId; string otp = string.Empty; if (PhoneFactor.Authenticate(Params, out otp, out callStatus, out errorId, externalsys.Timeout)) { if (externalsys.IsTwoWay) { return((int)AuthenticationResponseKind.SmsTwoWayOTP); } else { return(Convert.ToInt32(otp)); } } else { return((int)AuthenticationResponseKind.Error); } }
/// <summary> /// CreateMessage method implmentation /// </summary> private static string CreateMessage(PhoneFactorParams pfAuthParams, bool asynchronous) { bool sms = 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; bool two_way = pfAuthParams.Mode == MODE_SMS_TWO_WAY_OTP || pfAuthParams.Mode == MODE_SMS_TWO_WAY_OTP_PLUS_PIN; bool otp = pfAuthParams.Mode == MODE_SMS_TWO_WAY_OTP || pfAuthParams.Mode == MODE_SMS_ONE_WAY_OTP; bool phone_app = pfAuthParams.Mode == MODE_PHONE_APP_PIN || pfAuthParams.Mode == MODE_PHONE_APP_STANDARD; bool phone_app_pin = pfAuthParams.Mode == MODE_PHONE_APP_PIN; XmlDocument doc = new XmlDocument(); // start message // <pfpMessage></pfpMessage> XmlElement root = doc.CreateElement("pfpMessage"); root.SetAttribute("version", "1.5"); doc.AppendChild(root); // message header // <header></header> XmlElement header = doc.CreateElement("header"); root.AppendChild(header); XmlElement source = doc.CreateElement("source"); header.AppendChild(source); XmlElement component = doc.CreateElement("component"); component.SetAttribute("type", "pfsdk"); source.AppendChild(component); XmlElement element = doc.CreateElement("host"); element.SetAttribute("ip", pfAuthParams.IpAddress); element.SetAttribute("hostname", pfAuthParams.Hostname); component.AppendChild(element); // request // <request></request> XmlElement request = doc.CreateElement("request"); Random random = new Random(); if (pfAuthParams.RequestId == null || pfAuthParams.RequestId.Length == 0) { pfAuthParams.RequestId = random.Next(10000).ToString(); } request.SetAttribute("request-id", pfAuthParams.RequestId); request.SetAttribute("language", pfAuthParams.Language); request.SetAttribute("async", asynchronous ? "1" : "0"); request.SetAttribute("response-url", pfAuthParams.ResponseUrl); root.AppendChild(request); XmlElement auth_request = doc.CreateElement("authenticationRequest"); if (sms) { auth_request.SetAttribute("mode", "sms"); } request.AppendChild(auth_request); XmlElement customer = doc.CreateElement("customer"); auth_request.AppendChild(customer); element = doc.CreateElement("licenseKey"); element.InnerText = LICENSE_KEY; customer.AppendChild(element); element = doc.CreateElement("groupKey"); element.InnerText = GROUP_KEY; customer.AppendChild(element); element = doc.CreateElement("countryCode"); element.InnerText = pfAuthParams.CountryCode; auth_request.AppendChild(element); element = doc.CreateElement("authenticationType"); element.InnerText = "pfsdk"; auth_request.AppendChild(element); element = doc.CreateElement("username"); element.InnerText = pfAuthParams.Username; auth_request.AppendChild(element); element = doc.CreateElement("phonenumber"); element.SetAttribute("userCanChangePhone", "no"); element.InnerText = pfAuthParams.Phone; if (pfAuthParams.Extension != null && pfAuthParams.Extension.Length != 0) { element.SetAttribute("extension", pfAuthParams.Extension); } auth_request.AppendChild(element); element = doc.CreateElement("allowInternationalCalls"); element.InnerText = pfAuthParams.AllowInternationalCalls ? "yes" : "no"; auth_request.AppendChild(element); element = doc.CreateElement("applicationName"); element.InnerText = pfAuthParams.ApplicationName; auth_request.AppendChild(element); XmlElement pin_info = doc.CreateElement("pinInfo"); XmlElement pin_element = doc.CreateElement("pin"); if (pfAuthParams.Mode == MODE_SMS_TWO_WAY_OTP_PLUS_PIN) { string pinFormat; string pinFormatted; if (pfAuthParams.Sha1PinHash.Length == 0) { pinFormat = "plainText"; pinFormatted = pfAuthParams.Pin; } else { pinFormat = "sha1"; pinFormatted = pfAuthParams.Sha1PinHash; } pin_element.SetAttribute("pinFormat", pinFormat); if (pfAuthParams.Sha1PinHash.Length != 0) { pin_element.SetAttribute("sha1Salt", pfAuthParams.Sha1Salt); } pin_element.SetAttribute("pinChangeRequired", "no"); pin_element.InnerText = pinFormatted; } if (sms) { XmlElement sms_info = doc.CreateElement("smsInfo"); sms_info.SetAttribute("direction", two_way ? "two-way" : "one-way"); sms_info.SetAttribute("mode", otp ? "otp" : "otp-pin"); element = doc.CreateElement("message"); element.InnerText = pfAuthParams.SmsText; sms_info.AppendChild(element); if (pfAuthParams.Mode == MODE_SMS_TWO_WAY_OTP_PLUS_PIN) { sms_info.AppendChild(pin_element); } auth_request.AppendChild(sms_info); pin_info.SetAttribute("pinMode", MODE_STANDARD); } else if (phone_app) { XmlElement phone_app_auth_info = doc.CreateElement("phoneAppAuthInfo"); phone_app_auth_info.SetAttribute("mode", "standard"); XmlElement device_tokens = doc.CreateElement("deviceTokens"); element = doc.CreateElement("deviceToken"); if (pfAuthParams.NotificationType.Length > 0) { element.SetAttribute("notificationType", pfAuthParams.NotificationType); } element.InnerText = pfAuthParams.DeviceToken; device_tokens.AppendChild(element); phone_app_auth_info.AppendChild(device_tokens); element = doc.CreateElement("phoneAppAccountName"); element.InnerText = pfAuthParams.AccountName; phone_app_auth_info.AppendChild(element); if (phone_app_pin) { element = doc.CreateElement("pin"); element.SetAttribute("pinChangeRequired", "0"); string pinFormat; string pinFormatted; if (pfAuthParams.Sha1PinHash.Length == 0) { pinFormat = "plainText"; pinFormatted = pfAuthParams.Pin; } else { pinFormat = "sha1"; pinFormatted = pfAuthParams.Sha1PinHash; } element.SetAttribute("pinFormat", pinFormat); if (pfAuthParams.Sha1PinHash.Length != 0) { element.SetAttribute("sha1Salt", pfAuthParams.Sha1Salt); } element.InnerText = pinFormatted; phone_app_auth_info.AppendChild(element); } XmlElement phone_app_messages = doc.CreateElement("phoneAppMessages"); element = doc.CreateElement("message"); element.SetAttribute("type", "authenticateButton"); element.InnerText = "Authenticate"; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "authenticationDenied"); element.InnerText = "PhoneFactor authentication denied."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "authenticationSuccessful"); element.InnerText = "You have successfully authenticated using PhoneFactor."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "cancelButton"); element.InnerText = "Cancel"; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "closeButton"); element.InnerText = "Close"; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "denyAndReportFraudButton"); element.InnerText = "Deny and Report Fraud"; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "denyButton"); element.InnerText = "Deny"; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "fraudConfirmationNoBlock"); element.InnerText = "Your company's fraud response team will be notified."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "fraudConfirmationWithBlock"); element.InnerText = "Your account will be blocked preventing further authentications and the company's fraud response team will be notified."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "fraudReportedNoBlock"); element.InnerText = "Fraud reported."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "fraudReportedWithBlock"); element.InnerText = "Fraud reported and account blocked."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "notification"); element.InnerText = "You have received a PhoneFactor authentication request."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "reportFraudButton"); element.InnerText = "Report Fraud"; phone_app_messages.AppendChild(element); if (pfAuthParams.Mode == MODE_PHONE_APP_STANDARD) { element = doc.CreateElement("message"); element.SetAttribute("type", "standard"); element.InnerText = "Tap Authenticate to complete your authentication."; } else { element = doc.CreateElement("message"); element.SetAttribute("type", "confirmPinField"); element.InnerText = "Confirm PIN"; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "newPinField"); element.InnerText = "New PIN"; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pin"); element.InnerText = "Enter your PIN and tap Authenticate to complete your authentication."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pinAllSameDigits"); element.InnerText = "Your PIN cannot contain 3 or more repeating digits."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pinExpired"); element.InnerText = "Your PIN has expired. Please enter a new PIN to complete your authentication."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pinField"); element.InnerText = "PIN"; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pinHistoryDuplicate"); element.InnerText = "Your PIN cannot be the same as one of your recently used PINs. Please choose a different PIN."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pinLength"); element.InnerText = "Your PIN must be a minimum of 4 digits."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pinMismatch"); element.InnerText = "New PIN and Confirm PIN must match."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pinRetry"); element.InnerText = "Incorrect PIN. Please try again."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pinSequentialDigits"); element.InnerText = "Your PIN cannot contain 3 or more sequential digits ascending or descending."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "pinSubsetOfPhone"); element.InnerText = "Your PIN cannot contain a 4 digit subset of your phone number or backup phone number."; phone_app_messages.AppendChild(element); element = doc.CreateElement("message"); element.SetAttribute("type", "saveButton"); element.InnerText = "Save"; } phone_app_auth_info.AppendChild(phone_app_messages); auth_request.AppendChild(phone_app_auth_info); } auth_request.AppendChild(pin_info); return(doc.InnerXml); }
/// <summary> /// InternalAuthenticate method implementation /// </summary> private static bool InternalAuthenticate(PhoneFactorParams pfAuthParams, bool asynchronous, out string otp, out int call_status, out int error_id, int timeout = 300) { if (pfAuthParams.CountryCode.Length == 0) { pfAuthParams.CountryCode = "1"; } if (pfAuthParams.Hostname.Length == 0) { pfAuthParams.Hostname = "adfsmfa-hostname"; } if (pfAuthParams.IpAddress.Length == 0) { pfAuthParams.IpAddress = "255.255.255.255"; } 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_PHONE_APP_STANDARD && pfAuthParams.Mode != MODE_PHONE_APP_PIN) { pfAuthParams.Mode = MODE_SMS_ONE_WAY_OTP; // pfAuthParams.Mode = MODE_STANDARD; } otp = ""; call_status = 0; error_id = 0; // pfAuthParams.Pin = "7812"; string auth_message = CreateMessage(pfAuthParams, asynchronous); int tries = 1; if (mMutex.WaitOne(timeout * 1000)) { try { tries = mTargets.Count + 1; } finally { mMutex.ReleaseMutex(); } } 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); } else { if (mMutex.WaitOne(timeout * 1000)) { try { mTargets.Enqueue(mCurrentTarget); mCurrentTarget = mTargets.Dequeue().ToString(); } finally { mMutex.ReleaseMutex(); } } } } return(false); }
/// <summary> /// InternalAuthenticate method implementation /// </summary> private static bool InternalAuthenticate(PhoneFactorParams pfAuthParams, bool asynchronous, out int call_status, out int error_id, int timeout = 300) { string otp = ""; return(InternalAuthenticate(pfAuthParams, asynchronous, out otp, out call_status, out error_id, timeout)); }
/// <summary> /// Authenticate method implementation overload /// </summary> public static bool Authenticate(PhoneFactorParams pfAuthParams, out int callStatus, out int errorId, int timeout = 300) { return(InternalAuthenticate(pfAuthParams, false, out callStatus, out errorId, timeout)); }
/// <summary> /// GetCodeWithExternalSystem method implmentation /// </summary> public NotificationStatus GetCodeWithExternalSystem(Registration reg, ExternalOTPProvider externalsys, CultureInfo culture, out int otp) { azure_strings.Culture = culture; String NumberStr = reg.PhoneNumber; int CountryCode = 0; ulong NationalNumber = 0; string extension = string.Empty; PhoneNumberUtil phoneUtil = PhoneNumberUtil.GetInstance(); PhoneNumber NumberProto = phoneUtil.Parse(NumberStr, culture.TwoLetterISOLanguageName.ToUpper()); CountryCode = NumberProto.CountryCode; NationalNumber = NumberProto.NationalNumber; if (NumberProto.HasExtension) { extension = NumberProto.Extension; } PhoneFactor.Initialize(externalsys); PhoneFactorParams Params = new PhoneFactorParams(); Params.Username = reg.UPN; Params.CountryCode = CountryCode.ToString(); Params.Phone = NationalNumber.ToString(); Params.Extension = extension; Params.ApplicationName = "IdentityServer"; Params.Sha1Salt = externalsys.Sha1Salt; if (externalsys.IsTwoWay) { Params.SmsText = string.Format(azure_strings.SMSTwoWayMessage, externalsys.Company); Params.Mode = PhoneFactor.MODE_SMS_TWO_WAY_OTP; } else { Params.SmsText = string.Format(azure_strings.SMSMessage, externalsys.Company); Params.Mode = PhoneFactor.MODE_SMS_ONE_WAY_OTP; } int callStatus; int errorId; string xotp = string.Empty; if (PhoneFactor.Authenticate(Params, out xotp, out callStatus, out errorId, externalsys.Timeout)) { if (externalsys.IsTwoWay) { otp = Convert.ToInt32(NotificationStatus.ResponseSMSReply); return(NotificationStatus.ResponseSMSReply); } else { otp = Convert.ToInt32(xotp); return(NotificationStatus.ResponseSMSOTP); } } else { otp = 0; return(NotificationStatus.Error); } }