/// <summary>
        /// Check the OTP an does the real authentication
        /// </summary>
        /// <param name="proofData">the date from the HTML fild</param>
        /// <param name="authContext">The autch context which contains secrued parametes.</param>
        /// <returns>True if auth is done and user can be validated</returns>
        bool ValidateProofData(IProofData proofData, IAuthenticationContext authContext)
        {
            if (proofData == null || proofData.Properties == null || !proofData.Properties.ContainsKey("otpvalue"))
            {
                throw new ExternalAuthenticationException("Error - no answer found", authContext);
            }

            if (!ssl)
            {
                ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
            }

            try
            {
                string otpvalue = (string)proofData.Properties["otpvalue"];
                // fix for #14 and #15
                string session_user   = (string)authContext.Data["userid"];
                string session_realm  = (string)authContext.Data["realm"];
                string transaction_id = (string)authContext.Data["transaction_id"];
                // end fix
#if DEBUG
                Debug.WriteLine(debugPrefix + "OTP Code: " + otpvalue + " User: "******" Server: " + session_realm + " Transaction_id: " + transaction_id);
#endif
                return(otp_prov.getAuthOTP(session_user, otpvalue, session_realm, transaction_id));
            }
            catch
            {
                throw new ExternalAuthenticationException("Error - can't validate the otp value", authContext);
            }
        }
Esempio n. 2
0
        private string ValidateProofData(IProofData proofData, IAuthenticationContext authContext)
        {
            if (proofData == null || proofData.Properties == null || !proofData.Properties.ContainsKey("captcha"))
            {
                throw new ExternalAuthenticationException("请输入短信验证码!", authContext);
            }
            var code = (string)proofData.Properties["captcha"];

            return(CommonHelper.Request("get", apiinfo.API_CheckVerifyCode + "?phone=" + phone + "&code=" + code));
        }
        /// <summary>
        /// Deserializes the SAML response data.
        /// </summary>
        /// <param name="proofData">The AD FS proof data.</param>
        /// <param name="context">The context.</param>
        /// <returns>A Second Factor Authentication Response.</returns>
        public static SecondFactorAuthResponse Deserialize(IProofData proofData, IAuthenticationContext context)
        {
            if (!proofData.Properties.ContainsKey("_SAMLResponse"))
            {
                throw new ArgumentException("Missing '_SAMLResponse' POST parameter");
            }

            var response = new SecondFactorAuthResponse(new Saml2Id($"_{context.ContextId}"), proofData.Properties["_SAMLResponse"].ToString());

            return(response);
        }
 public DummyAdapterPresentation(IAuthenticationContext context, IProofData proofData, HttpListenerRequest request, out Claim[] claims)
 {
     this.context = context;
     DummyLogger.Log(string.Format("ActivityId: {0}, ContextId: {1}, Lcid: {2}", context.ActivityId, context.ContextId, context.Lcid));
     this.proofData = proofData;
     DummyLogger.Log(string.Format("ProofData: {0}", proofData.Properties.Count));
     this.request = request;
     DummyLogger.Log(string.Format("ServiceName: {0}, Uri: {1}, UserHostName: {2}, UserHostAddress: {3}", request.ServiceName, request.Url.AbsoluteUri, request.UserHostName, request.UserHostAddress));
     this.claims    = new Claim[1];
     this.claims[0] = new Claim("dummyType", "dummyValue");
     claims         = this.claims;
     DummyLogger.Log(string.Format("Claims: {0}", claims.Length));
 }
 public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, System.Net.HttpListenerRequest request, out System.Security.Claims.Claim[] claims)
 {
     claims = null;
     IAdapterPresentation result = null;
     string pin = proofData.Properties["pin"].ToString();
     if (pin == "98765")
     {
         System.Security.Claims.Claim claim = new System.Security.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
         claims = new System.Security.Claims.Claim[] { claim };
     }
     else
     {
         result = new SimplePINAdapterPresentation("Authentication failed.", false);
     }
     return result;
 }
Esempio n. 6
0
        private string _str(IProofData o)
        {
            if (o == null)
            {
                return("null");
            }
            StringBuilder sb = new StringBuilder(32); // TODO: update on change

            sb.Append("{");
            foreach (KeyValuePair <string, object> pair in o.Properties)
            {
                sb.Append(pair.Key).Append(":\"").Append(pair.Value).Append("\"; ");
            }
            sb.Append("}");
            return(sb.ToString());
        }
Esempio n. 7
0
        static bool ValidateProofOTPCode(IProofData proofData, IAuthenticationContext authContext)
        {
            if (proofData.Properties.ContainsKey("OTPCode"))
            {
                OTPCodeAnswer       = (string)proofData.Properties["OTPCode"];
                Debug.OTPCodeAnswer = OTPCodeAnswer;
            }

            if (!String.IsNullOrEmpty(OTPCodeAnswer) && OTPCodeAnswer == OTPCode)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Esempio n. 8
0
        static bool ValidateProofPIN(IProofData proofData, IAuthenticationContext authContext)
        {
            if (proofData.Properties.ContainsKey("PIN"))
            {
                PinAnswer       = (string)proofData.Properties["PIN"];
                Debug.PinAnswer = PinAnswer;
            }

            if (!String.IsNullOrEmpty(PinAnswer) && PinAnswer == PIN)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Esempio n. 9
0
        static bool ValidateProofData(IProofData proofData, IAuthenticationContext authContext)
        {
            if (proofData == null || proofData.Properties == null || !proofData.Properties.ContainsKey("OTP"))
            {
                throw new ExternalAuthenticationException("Error - please input an answer", authContext);
            }

            var otp = (string)proofData.Properties["OTP"];

            if (otp == answer)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Esempio n. 10
0
        private bool ValidateProofDataAsync(IProofData proofData, IAuthenticationContext context, out string response)
        {
            string userPrincipalName  = (string)context.Data[USERUPN];
            string registeredTokenIDs = (string)context.Data[REGISTEREDTOKENIDS];

            if (proofData == null ||
                proofData.Properties == null ||
                !proofData.Properties.ContainsKey("yubikeyotp"))
            {
                throw new ExternalAuthenticationException("Invalid submission - no proof data provided", context);
            }

            string otp = proofData.Properties["yubikeyotp"] as string;

            log.Debug("[{0}] Extracted otp {1} from proof data", context.ActivityId, otp ?? "(null)");

            if (string.IsNullOrEmpty(otp) || otp.Length < 13)
            {
                response = "Invalid One-Time Password received";
                return(false);
            }

            // extract the first 12 characters of the token id and convert to all lowercase
            string tokenID = otp.Substring(0, 12).ToLower();

            if (Array.IndexOf(registeredTokenIDs.Split(','), tokenID) == -1)
            {
                response = string.Format("Token ID ({0}) not associated with {1}", tokenID, userPrincipalName);
                return(false);
            }

            var client       = new YubicoClient(yubico_api_client_id, yubico_api_secret_key);
            var yubicoAnswer = client.VerifyAsync(otp).GetAwaiter().GetResult();

            if (yubicoAnswer == null || yubicoAnswer.Status != YubicoResponseStatus.Ok)
            {
                response = yubicoAnswer.Status.ToString();
                return(false);
            }

            response = "Authenticated completed successfully";
            return(true);
        }
Esempio n. 11
0
        /// <summary>
        /// Check the OTP and do the real authentication
        /// </summary>
        /// <param name="proofData">the data from the HTML field</param>
        /// <param name="authContext">The auth context which contains secured parametes</param>
        /// <returns>True if auth is done and user can be validated</returns>
        private bool ValidateProofData(IProofData proofData, IAuthenticationContext authContext)
        {
            if (authContext is null)
            {
                authContext = new AuthenticationContext();
            }

            if (proofData == null || proofData.Properties == null || !proofData.Properties.ContainsKey("otpvalue"))
            {
                throw new ExternalAuthenticationException($"ValidateProofData() OTP not found for {authContext.Data["userid"]}", authContext);
            }

            if (!ssl)
            {
#pragma warning disable CA5359 // Do Not Disable Certificate Validation
                ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
#pragma warning restore CA5359 // Do Not Disable Certificate Validation
            }

            try
            {
                string otpvalue       = (string)proofData.Properties["otpvalue"];
                string session_user   = (string)authContext.Data["userid"];
                string session_realm  = (string)authContext.Data["realm"];
                string transaction_id = authContext.Data.ContainsKey("transaction_id") ? (string)authContext.Data["transaction_id"] : "";
#if DEBUG
                Debug.WriteLine($"{Helper.debugPrefix} ValidateProofData() user {session_user}, OTP {otpvalue}, realm {session_realm}, transaction {transaction_id}");
#endif
                // if we're running a server farm and BeginAuthentication was called on a different server
                if (otp_prov is null)
                {
                    otp_prov = new OTPprovider(privacyIDEAurl);
                }
                return(otp_prov.ValidateOTP(session_user, otpvalue, session_realm, transaction_id));
            }
            catch (Exception ex)
            {
#if DEBUG
                Debug.WriteLine($"{Helper.debugPrefix} ValidateProofData() exception: {ex.Message}");
#endif
                throw new ExternalAuthenticationException($"ValidateProofData() exception: {ex.Message}", authContext);
            }
        }
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext authContext, IProofData proofData, HttpListenerRequest request, out Claim[] outgoingClaims)
        {
            outgoingClaims = new Claim[0];
            if (ValidateProofData(proofData, authContext))
            {
                //authn complete - return authn method
                outgoingClaims = new[]
                     {
                     // Return the required authentication method claim, indicating the particular authentication method used.
                     new Claim( "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod",
                     "http://schemas.microsoft.com/ws/2012/12/authmethod/otp" )
                     };

                return null;
            }
            else
            {
                //authn not complete - return new instance of IAdapterPresentationForm derived class
                return new AdapterPresentation(Resources.TokenValidationFailedMessage);
            }
        }
Esempio n. 13
0
        private bool ValidateProofDataAsync(IProofData proofData, IAuthenticationContext context, out string response)
        {
            if (proofData == null ||
                proofData.Properties == null ||
                !proofData.Properties.ContainsKey("yubikeyotp"))
            {
                throw new ExternalAuthenticationException("Invalid submission - no proof data provided", context);
            }

            string otp = proofData.Properties["yubikeyotp"] as string;

            log.Debug("Extracted otp {0} from proof data", otp ?? "(null)");

            if (string.IsNullOrEmpty(otp) || otp.Length < 13)
            {
                response = "Authentication failed: Invalid One-Time Password received";
                return(false);
            }

            string tokenID = otp.Substring(0, 12);

            if (!registeredTokenIDs.Contains(tokenID))
            {
                response = string.Format("Authentication failed: Token ID ({0}) not associated with {1}", tokenID, upn);
                return(false);
            }

            var client       = new YubicoClient(yubico_api_client_id, yubico_api_secret_key);
            var yubicoAnswer = client.VerifyAsync(otp).GetAwaiter().GetResult();

            if (yubicoAnswer == null || yubicoAnswer.Status != YubicoResponseStatus.Ok)
            {
                response = string.Format("Authentication failed: {0}", yubicoAnswer.Status.ToString());
                return(false);
            }

            response = "Authenticated completed successfully";
            return(true);
        }
        private bool ValidateProofData(IProofData proofData, IAuthenticationContext authContext)
        {
            if (proofData == null || proofData.Properties == null || !proofData.Properties.ContainsKey(TOKEN_FORM_FIELD_NAME))
            {
                throw new ExternalAuthenticationException(Resources.TokenNotFoundMessage, authContext);
            }

            string key = GetEncodedSecretKey(this.upn);

            Totp otp = new Totp(Base32.Base32Encoder.Decode(key));

            long step;

            bool isVerified = otp.VerifyTotp((string)proofData.Properties[TOKEN_FORM_FIELD_NAME], out step, new VerificationWindow(previous: 1, future: 1));

            if (!isVerified)
            {
                return(false);
            }

            string cacheKey = this.upn + "_" + step.ToString();

            if (this.cache.Get(cacheKey) != null)
            {
                throw new ExternalAuthenticationException(String.Format(Resources.TokenAlreadyUsedMessage, "[" + this.upn + "] [" + step.ToString() + "]"), authContext);
            }
            else
            {
                var policy = new CacheItemPolicy()
                {
                    AbsoluteExpiration = DateTime.Now.Add(new TimeSpan(0, 1, 0))
                };
                this.cache.AddOrGetExisting(new CacheItem(cacheKey, "used"), policy);
            }

            return(true);
        }
Esempio n. 15
0
        private bool ValidateProofData(IProofData proofData, IAuthenticationContext context, out string response)
        {
            if (proofData == null ||
                proofData.Properties == null ||
                !proofData.Properties.ContainsKey("yubikeyotp"))
            {
                throw new ExternalAuthenticationException("Invalid submission - no proof data provided", context);
            }

            string token = proofData.Properties["yubikeyotp"] as string;

            if (string.IsNullOrEmpty(token) || token.Length < 13)
            {
                response = "Authentication failed: Bad One-Time Password";
                return(false);
            }

            string tokenID = token.Substring(0, 12);

            if (!registeredTokenIDs.Contains(tokenID))
            {
                response = string.Format("Authentication failed: Unknown YubiKey ID ({0})", tokenID);
                return(false);
            }

            YubicoAnswer yubicoAnswer = new YubicoRequest().Validate(token);

            response = yubicoAnswer.Status.ToString();

            if (!yubicoAnswer.IsValid)
            {
                response = string.Format("Authentication failed: {0}", response);
            }

            return(yubicoAnswer.IsValid);
        }
Esempio n. 16
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext authContext, IProofData proofData, HttpListenerRequest request, out Claim[] outgoingClaims)
        {
            Debug.Caller   = "TryEndAuthentication";
            outgoingClaims = new Claim[0];

            if (proofData == null || proofData.Properties == null || (!proofData.Properties.ContainsKey("PIN") && !proofData.Properties.ContainsKey("OTPCode")))
            {
                throw new ExternalAuthenticationException("Error - no answer found", authContext);
            }

            if (!ValidateProofPIN(proofData, authContext))
            {
                //authentication not complete - return new instance of IAdapterPresentationForm derived class
                return(new SmsPresentationFormPin(Debug));
            }

            if (!ValidateProofOTPCode(proofData, authContext))
            {
                //authentication not complete - return new instance of IAdapterPresentationForm derived class
                return(new SmsPresentationFormOtp(Debug));
            }

            outgoingClaims = new[]
            {
                // Return the required authentication method claim, indicating the particulate authentication method used.
                new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://example.com/myauthenticationmethod1")
            };

            return(null);
        }
        private bool ValidateProofData(IProofData proofData, IAuthenticationContext authContext)
        {
            if (proofData == null || proofData.Properties == null || !proofData.Properties.ContainsKey(TOKEN_FORM_FIELD_NAME))
            {
                throw new ExternalAuthenticationException(Resources.TokenNotFoundMessage, authContext);
            }

            string key = GetEncodedSecretKey(this.upn);

            Totp otp = new Totp(Base32.Base32Encoder.Decode(key));

            long step;

            bool isVerified = otp.VerifyTotp((string)proofData.Properties[TOKEN_FORM_FIELD_NAME], out step, new VerificationWindow(previous: 1, future: 1));

            if (!isVerified) { return false; }

            string cacheKey = this.upn + "_" + step.ToString();

            if (this.cache.Get(cacheKey) != null)
            {
                throw new ExternalAuthenticationException(String.Format(Resources.TokenAlreadyUsedMessage, "[" + this.upn + "] [" + step.ToString() + "]"), authContext);
            }
            else
            {
                var policy = new CacheItemPolicy() { AbsoluteExpiration = DateTime.Now.Add(new TimeSpan(0, 1, 0)) };
                this.cache.AddOrGetExisting(new CacheItem(cacheKey, "used"), policy);
            }

            return true;
        }
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, System.Net.HttpListenerRequest request, out System.Security.Claims.Claim[] claims)
        {
            if (proofData?.Properties == null ||
                !proofData.Properties.ContainsKey("ChallengeQuestionAnswer") ||
                context?.Data == null ||
                !context.Data.ContainsKey("upn") ||
                string.IsNullOrEmpty((string)context.Data["upn"]))
            {
                throw new ExternalAuthenticationException("No answer found or corrupted context.", context);
            }

            claims = null;
            IAdapterPresentation result = null;

            var upn  = (string)context.Data["upn"];
            var code = (string)proofData.Properties["ChallengeQuestionAnswer"];

            var secretKey = _secretStorageProvider.GetSecretKey(upn);

            if (TotpAuthenticator.CheckCode(upn, secretKey.Key, code, _usedCodeProvider))
            {
                var claim = new System.Security.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");

                claims = new[] { claim };

                if (!secretKey.Activated)
                {
                    secretKey.Activated = true;

                    _secretStorageProvider.SetSecretKey(upn, secretKey);
                }
            }
            else
            {
                result = new AdapterPresentation();
            }

            return(result);
        }
Esempio n. 19
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, HttpListenerRequest request, out Claim[] outgoingClaims)
        {
            AdapterPresentation authResponse = null;
            string responseMessage           = null;

            outgoingClaims = new Claim[0];

            log.Debug("Authentication beginning for {0}", this.upn);

            bool isValidated = ValidateProofDataAsync(proofData, context, out responseMessage);

            log.Debug(responseMessage);

            if (!isValidated)
            {
                authResponse = new AdapterPresentation(responseMessage, false);
            }
            else
            {
                outgoingClaims = new[]
                {
                    new Claim(
                        "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod",
                        "http://schemas.microsoft.com/ws/2012/12/authmethod/otp"
                        )
                };
            }

            return(authResponse);
        }
Esempio n. 20
0
 /// <summary>
 /// This method is called by ADFS when this Authentication Adapter should perform the actual authentication.
 /// </summary>
 /// <param name="context"></param>
 /// <param name="proofData">
 /// Dictionary of strings to objects, that represents whatever you have asked the client for during
 /// the BeginAuthentication method
 /// </param>
 /// <param name="request"></param>
 /// <param name="claims">
 /// If the Authentication Adapter has successfully performed the authentication, this variable should contain
 /// at least one claim with type http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod.
 /// The value of this claim should contain the method of authentication used. It must be one of the values
 /// listed in the AuthenticationMethods parameter of <see cref="DemoMetadata"/>.
 /// </param>
 /// <returns></returns>
 public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData,
                                                  HttpListenerRequest request, out System.Security.Claims.Claim[] claims)
 {
     claims = new Claim[0];
     return(new DemoPresentationForm());
 }
Esempio n. 21
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, System.Net.HttpListenerRequest request, out System.Security.Claims.Claim[] claims )
        {
            claims = null;
            IAdapterPresentation result = null;
            string userName = proofData.Properties["upn"].ToString();
            string pin = proofData.Properties["pin"].ToString();
            string pollingEndpoint = proofData.Properties["pollingEndpoint"].ToString();

            string windir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
            System.Configuration.ExeConfigurationFileMap fileMap = new System.Configuration.ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = windir + "\\ADFS\\OktaMFA-ADFS.dll.config";
            System.Configuration.Configuration cfg =
            System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, System.Configuration.ConfigurationUserLevel.None);
            string oktaTenant = cfg.AppSettings.Settings["Tenant"].Value;
            string authToken = cfg.AppSettings.Settings["apiKey"].Value;
            string baseUrl = oktaTenant + "/api/v1/";

            string pinSuccess = "no";
            string verifyResult = "false";

            HttpWebRequest upnRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userName);
            upnRequest.Headers.Add("Authorization", authToken);
            upnRequest.Method = "GET";
            upnRequest.ContentType = "application/json";
            var upnResponse = (HttpWebResponse)upnRequest.GetResponse();
            var idReader = new StreamReader(upnResponse.GetResponseStream());
            var id = idReader.ReadToEnd();

            RootObject userProfile = JsonConvert.DeserializeObject<RootObject>(id);

            string userID = userProfile.id.ToString();

            HttpWebRequest factorRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors");
            factorRequest.Headers.Add("Authorization", authToken);
            factorRequest.Method = "GET";
            factorRequest.ContentType = "application/json";
            factorRequest.Accept = "application/json";
            var factorResponse = (HttpWebResponse)factorRequest.GetResponse();
            var factorReader = new StreamReader(factorResponse.GetResponseStream());
            var factorList = factorReader.ReadToEnd();

            RootObject[] factors = JsonConvert.DeserializeObject<RootObject[]>(factorList);
            string factorID = "";
            foreach (RootObject factor in factors)
            {
                if (factor.provider == "OKTA" && factor.factorType == "push")
                {
                    //   string pushfactorID = factor.id;
                    //    HttpWebRequest pushRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors/" + pushfactorID + "/verify");
                    //    pushRequest.Headers.Add("Authorization", authToken);
                    //    pushRequest.Method = "POST";
                    //    pushRequest.ContentType = "application/json";
                    //    pushRequest.Accept = "application/json";
                    //    pushRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36";
                    //    var pushResponse = (HttpWebResponse)pushRequest.GetResponse();
                    //    var pushReader = new StreamReader(pushResponse.GetResponseStream());
                    //    var pushStatus = pushReader.ReadToEnd();
                    //    RootObject pushResult = JsonConvert.DeserializeObject<RootObject>(pushStatus);
                    //    string pollingEndpoint = pushResult._links.poll.href.ToString();

                    int attemptPoll = 1;
                    while (verifyResult == "false" && attemptPoll <= 20 && pinSuccess == "no")
                    {
                        HttpWebRequest verifyRequest = (HttpWebRequest)WebRequest.Create(pollingEndpoint);
                        verifyRequest.Headers.Add("Authorization", authToken);
                        verifyRequest.Method = "GET";
                        verifyRequest.ContentType = "application/json";
                        verifyRequest.Accept = "application/json";
                        verifyRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36";
                        var pushAnswer = (HttpWebResponse)verifyRequest.GetResponse();
                        var pushStatus2 = new StreamReader(pushAnswer.GetResponseStream());
                        var pushStatus3 = pushStatus2.ReadToEnd();
                        RootObject pushWait = JsonConvert.DeserializeObject<RootObject>(pushStatus3);
                        if (pushWait.factorResult == "SUCCESS")
                        {
                            verifyResult = "true";
                            Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                            claims = new Claim[] { claim };
                            return result;
                        }
                        else
                        {
                            attemptPoll++;

                        }

                    }
                    return result;

                }
                if (factor.provider == "OKTA" && factor.factorType == "token:software:totp" && verifyResult == "false" && pin != "")
                {
                    factorID = factor.id;
                    HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors/" + factorID + "/verify");
                    httprequest.Headers.Add("Authorization", authToken);
                    httprequest.Method = "POST";
                    httprequest.ContentType = "application/json";
                    otpCode otpCode = new otpCode
                    { passCode = pin };
                    string otpString = JsonConvert.SerializeObject(otpCode);
                    using (var streamWriter = new StreamWriter(httprequest.GetRequestStream()))
                    {

                        streamWriter.Write(otpString);
                    }
                    try
                    {
                       var httpResponse = (HttpWebResponse)httprequest.GetResponse();
                        if (httpResponse.StatusCode.ToString() == "OK" && pin != "" )
                        {
                            pinSuccess = "yes";
                            Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                            claims = new Claim[] { claim };
                            return result;
                        }

                       // using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                      //  {
                     //       var factorResult = streamReader.ReadToEnd();
                     //   }

                    }
                    catch (WebException we)
                    {
                        var failResponse = we.Response as HttpWebResponse;
                        if (failResponse == null)
                            throw;
                        result = new AdapterPresentation("Authentication failed.", proofData.Properties["upn"].ToString(), false);
                    }
                }

            }

            //HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors/" + factorID + "/verify");
            //httprequest.Headers.Add("Authorization", authToken);
            //httprequest.Method = "POST";
            //httprequest.ContentType = "application/json";
            //otpCode otpCode = new otpCode
            //{ passCode = pin };
            //string otpString = JsonConvert.SerializeObject(otpCode);
            //using (var streamWriter = new StreamWriter(httprequest.GetRequestStream()))
            //{

            //    streamWriter.Write(otpString);
            //}
            //try
            //{
            //    var httpResponse = (HttpWebResponse)httprequest.GetResponse();
            //    if (httpResponse.StatusCode.ToString() == "OK")
            //    {
            //     System.Security.Claims.Claim claim = new System.Security.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
            //     claims = new System.Security.Claims.Claim[] { claim };

            //    }
            //    using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            //    {
            //        var factorResult = streamReader.ReadToEnd();
            //    }

            //}
            //catch (WebException we)
            //{
            //    var failResponse = we.Response as HttpWebResponse;
            //    if (failResponse == null)
            //        throw;
            //    result = new AdapterPresentation("Authentication failed.", proofData.Properties["upn"].ToString(), false);
            //}
            if (pinSuccess == "yes" || verifyResult == "true")
            {
                Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                claims = new Claim[] { claim };
                return result;
            }
            else
            {
                result = new AdapterPresentation("Authentication failed.", proofData.Properties["upn"].ToString(), false);
            }
            return result;
        }
        /// <summary>
        /// Validates the SAML response and set the necessary claims.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="proofData">The post back data.</param>
        /// <param name="request">The request.</param>
        /// <param name="claims">The claims.</param>
        /// <returns>A form if the the validation fails or claims if the validation succeeds.</returns>
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, HttpListenerRequest request, out Claim[] claims)
        {
            this.log.Debug("Enter TryEndAuthentication");
            this.log.DebugFormat("context.ActivityId='{0}'; context.ContextId='{1}'; conext.Lcid={2}", context.ActivityId, context.ContextId, context.Lcid);
            foreach (var d in context.Data)
            {
                this.log.DebugFormat("conext.Data: '{0}'='{1}'", d.Key, d.Value);
            }

            foreach (var p in proofData.Properties)
            {
                this.log.DebugFormat("proofData.Properties: '{0}'='{1}'", p.Key, p.Value);
            }

            claims = null;
            try
            {
                var response       = SecondFactorAuthResponse.Deserialize(proofData, context);
                var authnRequestId = $"_{ context.ContextId}";
                this.log.InfoFormat("Received response for request with id '{0}'", authnRequestId);
                var samlResponse = new Saml2Response(response.SamlResponse, new Saml2Id(authnRequestId));
                if (samlResponse.Status != Saml2StatusCode.Success)
                {
                    return(new AuthFailedForm(samlResponse.StatusMessage));
                }

                claims = SamlService.VerifyResponseAndGetAuthenticationClaim(samlResponse);
                foreach (var claim in claims)
                {
                    this.log.DebugFormat(
                        "claim.Issuer='{0}'; claim.OriginalIssuer='{1}; claim.Type='{2}'; claim.Value='{3}'",
                        claim.Issuer,
                        claim.OriginalIssuer,
                        claim.Type,
                        claim.Value);
                    foreach (var p in claim.Properties)
                    {
                        this.log.DebugFormat("claim.Properties: '{0}'='{1}'", p.Key, p.Value);
                    }
                }

                this.log.InfoFormat("Successfully processed response for request with id '{0}'", authnRequestId);
                return(null);
            }
            catch (Exception ex)
            {
                this.log.ErrorFormat("Error while processing the saml response. Details: {0}", ex);
                return(new AuthFailedForm());
            }
        }
Esempio n. 23
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, HttpListenerRequest request, out Claim[] outgoingClaims)
        {
            AdapterPresentation authResponse = null;
            string responseMessage           = null;

            outgoingClaims = new Claim[0];

            // retrieve context data stored earlier
            string userPrincipalName = (string)context.Data[USERUPN];

            log.Debug("[{0}] Authentication beginning for {1}", context.ActivityId, userPrincipalName);
            bool isValidated = ValidateProofDataAsync(proofData, context, out responseMessage);

            if (!isValidated)
            {
                log.Info("Authentication failed for {0} - {1}", userPrincipalName, responseMessage);
                authResponse = new AdapterPresentation(responseMessage, false);
            }
            else
            {
                log.Info("Authentication successful for {0}", userPrincipalName);

                outgoingClaims = new[]
                {
                    new Claim(
                        "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod",
                        "http://schemas.microsoft.com/ws/2012/12/authmethod/otp"
                        )
                };
            }

            return(authResponse);
        }
 /// <summary>
 /// Function call after the user hits submit - it proofs the values (OTP pin)
 /// </summary>
 /// <param name="authContext"></param>
 /// <param name="proofData"></param>
 /// <param name="request"></param>
 /// <param name="outgoingClaims"></param>
 /// <returns></returns>
 public IAdapterPresentation TryEndAuthentication(IAuthenticationContext authContext, IProofData proofData, HttpListenerRequest request, out Claim[] outgoingClaims)
 {
     outgoingClaims = new Claim[0];
     if (ValidateProofData(proofData, authContext))
     {
         //authn complete - return authn method
         outgoingClaims = new[]
         {
             // Return the required authentication method claim, indicating the particulate authentication method used.
             new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp")
         };
         return(null);
     }
     else
     {
         //authentication not complete - return new instance of IAdapterPresentationForm derived class and the generic error message
         return(new AdapterPresentationForm(true, message, uidefinition));
     }
 }
Esempio n. 25
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, System.Net.HttpListenerRequest request, out System.Security.Claims.Claim[] claims)
        {
            claims = null;
            IAdapterPresentation result = null;
            string userName = proofData.Properties["upn"].ToString();
            string userID = proofData.Properties["userID"].ToString();
            string pin = proofData.Properties["pin"].ToString();

            string windir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
            System.Configuration.ExeConfigurationFileMap fileMap = new System.Configuration.ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = windir + "\\ADFS\\OktaMFA-ADFS.dll.config";

            System.Configuration.Configuration cfg =
            System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, System.Configuration.ConfigurationUserLevel.None);
            string oktaTenant = cfg.AppSettings.Settings["Tenant"].Value;
            string authToken = cfg.AppSettings.Settings["apiKey"].Value;
            string baseUrl = oktaTenant + "/api/v1/";
            string pinSuccess = "no";
            string verifyResult = "false";

            HttpWebRequest factorRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors");
            factorRequest.Headers.Add("Authorization", authToken);
            factorRequest.Method = "GET";
            factorRequest.ContentType = "application/json";
            factorRequest.Accept = "application/json";
            var factorResponse = (HttpWebResponse)factorRequest.GetResponse();
            var factorReader = new StreamReader(factorResponse.GetResponseStream());
            var factorList = factorReader.ReadToEnd();

            RootObject[] factors = JsonConvert.DeserializeObject<RootObject[]>(factorList);
            string factorID = "";
            foreach (RootObject factor in factors)
            {

                if (factor.factorType == "sms")
                {
                    factorID = factor.id;
                    HttpWebRequest verifyRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors/" + factorID + "/verify");
                    verifyRequest.Headers.Add("Authorization", authToken);
                    verifyRequest.Method = "POST";
                    verifyRequest.ContentType = "application/json";

                    otpCode otpCode = new otpCode
                    { passCode = pin };
                    string otpString = JsonConvert.SerializeObject(otpCode);
                    using (var streamWriter = new StreamWriter(verifyRequest.GetRequestStream()))
                    {

                        streamWriter.Write(otpString);
                    }

                    try
                    {
                        var verifyResponse = (HttpWebResponse)verifyRequest.GetResponse();
                        if (verifyResponse.StatusCode.ToString() == "OK" && pin != "")
                        {
                            pinSuccess = "yes";
                            Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                            claims = new Claim[] { claim };
                            return result;
                        }

                    }
                    catch (WebException we)
                    {
                        var failResponse = we.Response as HttpWebResponse;
                        if (failResponse == null)
                            throw;
                        result = new AdapterPresentation("Authentication was unsuccessful, did you enter the sms code correctly?", proofData.Properties["upn"].ToString(), false, proofData.Properties["userID"].ToString());
                    }
                }

            }

            if (pinSuccess == "yes")
            {
                Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                claims = new Claim[] { claim };
                return result;
            }
            else
            {
                result = new AdapterPresentation("Authentication was unsuccessful, did you enter the sms code correctly?", proofData.Properties["upn"].ToString(), false, proofData.Properties["userID"].ToString());
            }
            return result;
        }
Esempio n. 26
0
        /// <summary>
        /// Called when our form is submitted.
        /// </summary>
        /// <param name="authContext"></param>
        /// <param name="proofData"></param>
        /// <param name="request"></param>
        /// <param name="outgoingClaims"></param>
        /// <returns></returns>
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext authContext, IProofData proofData,
                                                         HttpListenerRequest request, out Claim[] outgoingClaims)
        {
            Log("TryEndAuthentication");
            // Early exit if step 2 can be skipped
            if (authContext != null)
            {
                if ((string)GetFromDict(authContext.Data, "authSuccess", "") == "1")
                {
                    outgoingClaims = Claims();
                    return(null);
                }
            }
            outgoingClaims = new Claim[0];

            if (proofData == null || proofData.Properties == null)
            {
                throw new ExternalAuthenticationException("Error - ProofData is empty", authContext);
            }

            if (this.privacyIDEA == null)
            {
                Error("PrivacyIDEA is not initialized!");
                throw new ExternalAuthenticationException("PrivacyIDEA is not initialized!", authContext);
            }

            Dictionary <string, object> contextDict = authContext.Data;
            Dictionary <string, object> proofDict   = proofData.Properties;

            Log("ProofData: " + string.Join(", ", proofData.Properties));
            Log("AuthContext: " + string.Join(", ", authContext.Data));

            // Prepare form to return, fill with values from proofData
            var    form                = new AdapterPresentationForm();
            string otp                 = (string)GetFromDict(proofDict, "otp");
            string mode                = (string)GetFromDict(proofDict, "mode");
            string modeChanged         = (string)GetFromDict(proofDict, "modeChanged");
            string pushAvailable       = (string)GetFromDict(proofDict, "pushAvailable");
            string message             = (string)GetFromDict(proofDict, "message");
            string webAuthnSignRequest = (string)GetFromDict(proofDict, "webAuthnSignRequest");
            string domain              = (string)GetFromDict(proofDict, "domain");

            string strAuthCounter = (string)GetFromDict(proofDict, "authCounter", "0");

            if (!string.IsNullOrEmpty(strAuthCounter))
            {
                form.AuthCounter = (int.Parse(strAuthCounter) + 1).ToString();
            }

            form.Message       = message;
            form.Mode          = mode;
            form.PushAvailable = pushAvailable;

            if (!string.IsNullOrEmpty(webAuthnSignRequest))
            {
                form.WebAuthnSignRequest = webAuthnSignRequest;
            }

            string transactionid = (string)GetFromDict(contextDict, "transactionid");
            string user          = (string)GetFromDict(contextDict, "userid");

            if (modeChanged == "1")
            {
                return(form);
            }

            // Do the authentication according to the mode we are in
            PIResponse response = null;

            if (mode == "push")
            {
                if (privacyIDEA.PollTransaction(transactionid))
                {
                    // Push confirmed, finish the authentication via /validate/check using an empty otp
                    // https://privacyidea.readthedocs.io/en/latest/tokens/authentication_modes.html#outofband-mode
                    response = privacyIDEA.ValidateCheck(user, "", transactionid, domain);
                }
                else
                {
                    // Else push not confirmed yet
                    form.ErrorMessage = "Authenication not confirmed yet!";
                }
            }
            else if (mode == "webauthn")
            {
                string origin           = (string)GetFromDict(proofDict, "origin");
                string webauthnresponse = (string)GetFromDict(proofDict, "webAuthnSignResponse");

                if (string.IsNullOrEmpty(origin) || string.IsNullOrEmpty(webauthnresponse))
                {
                    Error("Incomplete data for WebAuthn authentication: WebAuthnSignResponse or Origin is missing!");
                    form.ErrorMessage = "Could not complete WebAuthn authentication. Try again or use another token type.";
                }
                else
                {
                    response = privacyIDEA.ValidateCheckWebAuthn(user, transactionid, webauthnresponse, origin, domain);
                }
            }
            else
            {
                // Mode == OTP
                response = privacyIDEA.ValidateCheck(user, otp, transactionid, domain);
            }

            // If we get this far, the login data provided was wrong, an error occured or another challenge was triggered.
            bool newChallenge = false;

            if (response != null)
            {
                if (response.Challenges.Count > 0)
                {
                    newChallenge = true;
                    form         = ExtractChallengeDataToForm(response, form, authContext);
                }
                else if (response.Value)
                {
                    outgoingClaims = Claims();
                    return(null);
                }
                else
                {
                    Log("Response value was false!");
                    // Set the error message from the response or a default
                    form.ErrorMessage = (!string.IsNullOrEmpty(response.ErrorMessage)) ? response.ErrorMessage + " (" + response.ErrorCode + ")"
                        : "Wrong OTP value!";
                }
            }
            else
            {
                // In case of unconfirmed push response will be null too. Therefore, set the message only if there is none yet.
                if (string.IsNullOrEmpty(form.ErrorMessage))
                {
                    form.ErrorMessage = "The authentication server could not be reached.";
                    Error("Reponse from server was null!");
                }
            }

            // Set a generic error if none was set yet and no new challenge was triggered
            if (string.IsNullOrEmpty(form.ErrorMessage) && !newChallenge)
            {
                form.ErrorMessage = "An error occured.";
            }
            // Return form with error or new challenge
            return(form);
        }
Esempio n. 27
0
        static bool ValidateProofData(IProofData proofData, IAuthenticationContext authContext)
        {
            if (proofData == null || proofData.Properties == null || !proofData.Properties.ContainsKey("OTP"))
            {
                throw new ExternalAuthenticationException("Error - please input the OTP", authContext);
            }

            var otp = (string)proofData.Properties["OTP"];

            //Retrieve the YubiKey id stored in the user's AD object
            //Can be set with ADSI Edit or ADUC (Advanced view)
            DirectoryEntry    entry      = new DirectoryEntry();
            DirectorySearcher mySearcher = new DirectorySearcher(entry, "(&(objectClass=user)(objectCategory=person)(userPrincipalName=" + upn + "))");
            SearchResult      dirResult  = mySearcher.FindOne();
            string            yubikeyId  = (string)dirResult.Properties["extensionAttribute10"][0];

            var nonce = GenerateNonce(20);
            //First 12 digits/letters of OTP is the id for the YubiKey
            var userId = otp.Substring(0, 12);

            EventLog.WriteEntry("Application", "UPN: " + upn + " YubiId: " + yubikeyId, EventLogEntryType.Information);
            //Verify the user id portion of the YubiKey matches what's stored in AD
            if (userId != yubikeyId.Substring(8))
            {
                EventLog.WriteEntry("Application", "YubiKey lookup in AD failed for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }

            byte[] hmacKey = Convert.FromBase64String(apiKey);
            //Parameters need to be in alphabetical order to generate a valid signature
            var hmac = GenerateSignature($"id={authId}&nonce={nonce}&otp={otp}", hmacKey);

            var queryString = ($"?id={authId}&otp={otp}&nonce={nonce}&h={hmac}");
            var url         = $"{server}{queryString}";


            HttpClient client   = new HttpClient();
            var        response = client.GetAsync(new Uri(url)).Result;
            string     content  = response.Content.ReadAsStringAsync().Result;

            string[] separators = new string[] { "\r\n" };
            string[] result     = content.Split(separators, StringSplitOptions.RemoveEmptyEntries);

            string outNonce     = string.Empty;
            string outHmac      = string.Empty;
            string outStatus    = string.Empty;
            string outTimeStamp = string.Empty;
            string outSl        = string.Empty;
            string outOtp       = string.Empty;

            foreach (string x in result)
            {
                if (x.StartsWith("h="))
                {
                    outHmac = x.Substring(2);
                }
                if (x.StartsWith("t="))
                {
                    outTimeStamp = x.Substring(2);
                }
                if (x.StartsWith("status="))
                {
                    outStatus = x.Substring(7);
                }
                if (x.StartsWith("nonce="))
                {
                    outNonce = x.Substring(6);
                }
                if (x.StartsWith("sl="))
                {
                    outSl = x.Substring(3);
                }
                if (x.StartsWith("otp="))
                {
                    outOtp = x.Substring(4);
                }
            }

            //Need the response parameters in alphabetical order for verifying signature
            var responseList = new SortedDictionary <string, string>
            {
                { "t", outTimeStamp },
                { "nonce", outNonce },
                { "sl", outSl },
                { "status", outStatus },
                { "otp", outOtp }
            };

            StringBuilder queryBuilder = null;

            foreach (var pair in responseList)
            {
                if (queryBuilder == null)
                {
                    queryBuilder = new StringBuilder();
                }
                else
                {
                    queryBuilder.Append("&");
                }
                queryBuilder.AppendFormat("{0}={1}", pair.Key, pair.Value);
            }

            var serverSignature = queryBuilder.ToString();
            var signatureCheck  = GenerateSignature(serverSignature, hmacKey);

            if (outNonce != nonce)
            {
                //Nonce mismatch
                EventLog.WriteEntry("Application", "YubiKey nonce mismatch for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }
            if (outHmac != signatureCheck)
            {
                //Signature mismatch (server sent a different signature than expected)
                EventLog.WriteEntry("Application", "YubiKey signature mismatch for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }

            if (outStatus == "OK")
            {
                //All is good
                EventLog.WriteEntry("Application", "YubiKey OK for UPN: " + upn, EventLogEntryType.Information);
                return(true);
            }
            if (outStatus == "BAD_OTP")
            {
                //OTP not valid
                EventLog.WriteEntry("Application", "YubiKey BAD OTP for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }
            if (outStatus == "REPLAYED_OTP")
            {
                //OTP has already been used
                EventLog.WriteEntry("Application", "YubiKey REPLAYED OTP for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }
            if (outStatus == "BAD_SIGNATURE")
            {
                //Signature was incorrect
                EventLog.WriteEntry("Application", "YubiKey BAD SIGNATURE for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }
            if (outStatus == "MISSING_PARAMETER")
            {
                //Something missing
                EventLog.WriteEntry("Application", "YubiKey MISSING PARAMETER for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }
            if (outStatus == "NO_SUCH_CLIENT")
            {
                //Incorrect client
                EventLog.WriteEntry("Application", "YubiKey NO SUCH CLIENT for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }
            if (outStatus == "OPERATION_NOT_ALLOWED")
            {
                EventLog.WriteEntry("Application", "YubiKey OPERATION NOT ALLOWED for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }
            if (outStatus == "BACKEND_ERROR")
            {
                //Something wrong server side (Yubico)
                EventLog.WriteEntry("Application", "YubiKey BACKEND ERROR for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }
            if (outStatus == "NOT_ENOUGH_ANSWERS")
            {
                EventLog.WriteEntry("Application", "YubiKey NOT ENOUGH ANSWERS for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }
            if (outStatus == "REPLAYED_REQUEST")
            {
                EventLog.WriteEntry("Application", "YubiKey REPLAYED REQUEST for UPN: " + upn, EventLogEntryType.Information);
                return(false);
            }

            return(false);
        }
Esempio n. 28
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, System.Net.HttpListenerRequest request, out System.Security.Claims.Claim[] claims)
        {
            claims = null;
            IAdapterPresentation result = null;
            string userName             = proofData.Properties["upn"].ToString();
            string userID = proofData.Properties["userID"].ToString();
            string pin    = proofData.Properties["pin"].ToString();

            string windir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);

            System.Configuration.ExeConfigurationFileMap fileMap = new System.Configuration.ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = windir + "\\ADFS\\OktaMFA-ADFS.dll.config";

            System.Configuration.Configuration cfg =
                System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, System.Configuration.ConfigurationUserLevel.None);
            string oktaTenant   = cfg.AppSettings.Settings["Tenant"].Value;
            string authToken    = cfg.AppSettings.Settings["apiKey"].Value;
            string baseUrl      = oktaTenant + "/api/v1/";
            string pinSuccess   = "no";
            string verifyResult = "false";

            HttpWebRequest factorRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors");

            factorRequest.Headers.Add("Authorization", authToken);
            factorRequest.Method      = "GET";
            factorRequest.ContentType = "application/json";
            factorRequest.Accept      = "application/json";
            var factorResponse = (HttpWebResponse)factorRequest.GetResponse();
            var factorReader   = new StreamReader(factorResponse.GetResponseStream());
            var factorList     = factorReader.ReadToEnd();

            RootObject[] factors  = JsonConvert.DeserializeObject <RootObject[]>(factorList);
            string       factorID = "";

            foreach (RootObject factor in factors)
            {
                if (factor.factorType == "sms")
                {
                    factorID = factor.id;
                    HttpWebRequest verifyRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors/" + factorID + "/verify");
                    verifyRequest.Headers.Add("Authorization", authToken);
                    verifyRequest.Method      = "POST";
                    verifyRequest.ContentType = "application/json";


                    otpCode otpCode = new otpCode
                    {
                        passCode = pin
                    };
                    string otpString = JsonConvert.SerializeObject(otpCode);
                    using (var streamWriter = new StreamWriter(verifyRequest.GetRequestStream()))
                    {
                        streamWriter.Write(otpString);
                    }

                    try
                    {
                        var verifyResponse = (HttpWebResponse)verifyRequest.GetResponse();
                        if (verifyResponse.StatusCode.ToString() == "OK" && pin != "")
                        {
                            pinSuccess = "yes";
                            Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                            claims = new Claim[] { claim };
                            return(result);
                        }
                    }
                    catch (WebException we)
                    {
                        var failResponse = we.Response as HttpWebResponse;
                        if (failResponse == null)
                        {
                            throw;
                        }
                        result = new AdapterPresentation("Authentication was unsuccessful, did you enter the sms code correctly?", proofData.Properties["upn"].ToString(), false, proofData.Properties["userID"].ToString());
                    }
                }
            }

            if (pinSuccess == "yes")
            {
                Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                claims = new Claim[] { claim };
                return(result);
            }
            else
            {
                result = new AdapterPresentation("Authentication was unsuccessful, did you enter the sms code correctly?", proofData.Properties["upn"].ToString(), false, proofData.Properties["userID"].ToString());
            }
            return(result);
        }
Esempio n. 29
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, System.Net.HttpListenerRequest request, out System.Security.Claims.Claim[] claims)
        {
            claims = null;
            IAdapterPresentation result = null;
            string userName             = proofData.Properties["upn"].ToString();
            string pin             = proofData.Properties["pin"].ToString();
            string pollingEndpoint = proofData.Properties["pollingEndpoint"].ToString();

            string windir = Environment.GetFolderPath(Environment.SpecialFolder.Windows);

            System.Configuration.ExeConfigurationFileMap fileMap = new System.Configuration.ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = windir + "\\ADFS\\OktaMFA-ADFS.dll.config";
            System.Configuration.Configuration cfg =
                System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, System.Configuration.ConfigurationUserLevel.None);
            string oktaTenant = cfg.AppSettings.Settings["Tenant"].Value;
            string authToken  = cfg.AppSettings.Settings["apiKey"].Value;
            string baseUrl    = oktaTenant + "/api/v1/";

            string pinSuccess   = "no";
            string verifyResult = "false";

            HttpWebRequest upnRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userName);

            upnRequest.Headers.Add("Authorization", authToken);
            upnRequest.Method      = "GET";
            upnRequest.ContentType = "application/json";
            var upnResponse = (HttpWebResponse)upnRequest.GetResponse();
            var idReader    = new StreamReader(upnResponse.GetResponseStream());
            var id          = idReader.ReadToEnd();

            RootObject userProfile = JsonConvert.DeserializeObject <RootObject>(id);

            string userID = userProfile.id.ToString();

            HttpWebRequest factorRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors");

            factorRequest.Headers.Add("Authorization", authToken);
            factorRequest.Method      = "GET";
            factorRequest.ContentType = "application/json";
            factorRequest.Accept      = "application/json";
            var factorResponse = (HttpWebResponse)factorRequest.GetResponse();
            var factorReader   = new StreamReader(factorResponse.GetResponseStream());
            var factorList     = factorReader.ReadToEnd();

            RootObject[] factors  = JsonConvert.DeserializeObject <RootObject[]>(factorList);
            string       factorID = "";

            foreach (RootObject factor in factors)
            {
                if (factor.provider == "OKTA" && factor.factorType == "push")
                {
                    //   string pushfactorID = factor.id;
                    //    HttpWebRequest pushRequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors/" + pushfactorID + "/verify");
                    //    pushRequest.Headers.Add("Authorization", authToken);
                    //    pushRequest.Method = "POST";
                    //    pushRequest.ContentType = "application/json";
                    //    pushRequest.Accept = "application/json";
                    //    pushRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36";
                    //    var pushResponse = (HttpWebResponse)pushRequest.GetResponse();
                    //    var pushReader = new StreamReader(pushResponse.GetResponseStream());
                    //    var pushStatus = pushReader.ReadToEnd();
                    //    RootObject pushResult = JsonConvert.DeserializeObject<RootObject>(pushStatus);
                    //    string pollingEndpoint = pushResult._links.poll.href.ToString();


                    int attemptPoll = 1;
                    while (verifyResult == "false" && attemptPoll <= 20 && pinSuccess == "no")
                    {
                        HttpWebRequest verifyRequest = (HttpWebRequest)WebRequest.Create(pollingEndpoint);
                        verifyRequest.Headers.Add("Authorization", authToken);
                        verifyRequest.Method      = "GET";
                        verifyRequest.ContentType = "application/json";
                        verifyRequest.Accept      = "application/json";
                        verifyRequest.UserAgent   = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36";
                        var        pushAnswer  = (HttpWebResponse)verifyRequest.GetResponse();
                        var        pushStatus2 = new StreamReader(pushAnswer.GetResponseStream());
                        var        pushStatus3 = pushStatus2.ReadToEnd();
                        RootObject pushWait    = JsonConvert.DeserializeObject <RootObject>(pushStatus3);
                        if (pushWait.factorResult == "SUCCESS")
                        {
                            verifyResult = "true";
                            Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                            claims = new Claim[] { claim };
                            return(result);
                        }
                        else
                        {
                            attemptPoll++;
                        }
                    }
                    return(result);
                }
                if (factor.provider == "OKTA" && factor.factorType == "token:software:totp" && verifyResult == "false" && pin != "")
                {
                    factorID = factor.id;
                    HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors/" + factorID + "/verify");
                    httprequest.Headers.Add("Authorization", authToken);
                    httprequest.Method      = "POST";
                    httprequest.ContentType = "application/json";
                    otpCode otpCode = new otpCode
                    {
                        passCode = pin
                    };
                    string otpString = JsonConvert.SerializeObject(otpCode);
                    using (var streamWriter = new StreamWriter(httprequest.GetRequestStream()))
                    {
                        streamWriter.Write(otpString);
                    }
                    try
                    {
                        var httpResponse = (HttpWebResponse)httprequest.GetResponse();
                        if (httpResponse.StatusCode.ToString() == "OK" && pin != "")
                        {
                            pinSuccess = "yes";
                            Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                            claims = new Claim[] { claim };
                            return(result);
                        }

                        // using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
                        //  {
                        //       var factorResult = streamReader.ReadToEnd();
                        //   }
                    }
                    catch (WebException we)
                    {
                        var failResponse = we.Response as HttpWebResponse;
                        if (failResponse == null)
                        {
                            throw;
                        }
                        result = new AdapterPresentation("Authentication failed.", proofData.Properties["upn"].ToString(), false);
                    }
                }
            }

            //HttpWebRequest httprequest = (HttpWebRequest)WebRequest.Create(baseUrl + "users/" + userID + "/factors/" + factorID + "/verify");
            //httprequest.Headers.Add("Authorization", authToken);
            //httprequest.Method = "POST";
            //httprequest.ContentType = "application/json";
            //otpCode otpCode = new otpCode
            //{ passCode = pin };
            //string otpString = JsonConvert.SerializeObject(otpCode);
            //using (var streamWriter = new StreamWriter(httprequest.GetRequestStream()))
            //{

            //    streamWriter.Write(otpString);
            //}
            //try
            //{
            //    var httpResponse = (HttpWebResponse)httprequest.GetResponse();
            //    if (httpResponse.StatusCode.ToString() == "OK")
            //    {
            //     System.Security.Claims.Claim claim = new System.Security.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
            //     claims = new System.Security.Claims.Claim[] { claim };

            //    }
            //    using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
            //    {
            //        var factorResult = streamReader.ReadToEnd();
            //    }

            //}
            //catch (WebException we)
            //{
            //    var failResponse = we.Response as HttpWebResponse;
            //    if (failResponse == null)
            //        throw;
            //    result = new AdapterPresentation("Authentication failed.", proofData.Properties["upn"].ToString(), false);
            //}
            if (pinSuccess == "yes" || verifyResult == "true")
            {
                Claim claim = new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                claims = new Claim[] { claim };
                return(result);
            }
            else
            {
                result = new AdapterPresentation("Authentication failed.", proofData.Properties["upn"].ToString(), false);
            }
            return(result);
        }
Esempio n. 30
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, HttpListenerRequest request, out Claim[] claims)
        {
            claims = new Claim[0];

            if (ValidateProofData(proofData, context))
            {
                //authn complete - return authn method
                claims = new[]
                {
                    new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod",
                              "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/hardwaretoken")
                };

                return(null);
            }
            else
            {
                return(new YubiKeyMFAPresentationForm());
            }
        }
Esempio n. 31
0
        // Authentication should perform the actual authentication and return at least one Claim on success.
        // proofData contains a dictionnary of strings to objects that have been asked in the BeginAuthentication
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext ctx, IProofData proofData, System.Net.HttpListenerRequest request, out Claim[] claims)
        {
            string formAction, upn, msspTransId, logInfo;
            int    state;

            if (proofData.Properties.ContainsKey("Retry"))
            {
                formAction = "Retry";
            }
            else
            {
                try {
                    formAction = (string)proofData.Properties["Action"];
                } catch (KeyNotFoundException) {
                    formAction = null;
                }
            };
            //if (formAction == null && proofData.Properties.ContainsKey("SignOut")) {
            //    // if user modifies URL manually during a session, the Cancel action is not captured by ADFS but leaks to this method
            //    formAction = "SignOut";
            //};
            logger.TraceEvent(TraceEventType.Verbose, 0, "TryEndAuthentication(act:" + formAction + ", ctx:" + _str(ctx) + ", prf:" + _str(proofData) + ", req:" + _str(request));
            Logging.Log.TryEndAuthenticationStart(formAction, _str(ctx), _str(proofData), _str(request));
            CultureInfo culture = new CultureInfo(ctx.Lcid);

            upn   = (string)ctx.Data[USERUPN];
            state = (int)ctx.Data[STATE];
            try
            {
                // msspTransId is expected to be absent in some error cases, e.g. error 107
                msspTransId = (string)ctx.Data[MSSPTRXID];
            }
            catch (KeyNotFoundException)
            {
                msspTransId = null;
            };
            logInfo = "upn:\"" + upn + "\", msspTransId:\"" + msspTransId + "\"";

            claims = null;
            if (formAction == "Continue")
            {
                switch (state)
                {
                case 3:
                    logger.TraceEvent(TraceEventType.Information, 0, "AUTHN_OK: " + logInfo + ", state:" + state);
                    Logging.Log.AuthenticationSuccess(state, (int)ctx.Data[STATE], upn, msspTransId);
                    claims = ClaimsHwToken;
                    return(null);

                case 1:
                case 31:
                    // fall through for looping below
                    break;

                default:
                    logger.TraceEvent(TraceEventType.Error, 0, "BAD_STATE: " + logInfo + ", state:" + state);
                    Logging.Log.AuthenticationFail(state, (int)ctx.Data[STATE], upn, msspTransId, "BAD_STATE");
                    return(new AdapterPresentation(AuthView.AuthError, cfgAdfs, "action:\"Conitnue\"; state:" + state));
                }

                // check session age, i.e. timespan(Now, authBegin)
                int ageSeconds = (int)((DateTime.UtcNow.Ticks / 10000 - (long)ctx.Data[AUTHBEGIN]) / 1000);
                if (ageSeconds >= cfgMid.RequestTimeOutSeconds)
                {
                    ctx.Data[STATE] = 13;
                    logger.TraceEvent(TraceEventType.Information, 0, "AUTHN_TIMEOUT_CONT: " + logInfo + ", state:" + ctx.Data[STATE] + ", age:" + ageSeconds);
                    Logging.Log.AuthenticationTimeout(state, (int)ctx.Data[STATE], ageSeconds, upn, msspTransId);
                    return
                        (((int)ctx.Data[SESSTRIES] < cfgAdfs.SessionMaxTries) ?
                         new AdapterPresentation(AuthView.RetryOrCancel, cfgAdfs, "Timeout.") : // TODO: construct new ErrorCode for easier I18N
                         new AdapterPresentation(AuthView.AuthError, cfgAdfs, "Timeout."));
                }

                AuthRequestDto req = new AuthRequestDto();
                req.PhoneNumber    = (string)ctx.Data[MSISDN];
                req.DataToBeSigned = (string)ctx.Data[DTBS];
                bool needCheckUserSerialNumber =
                    !cfgMid.UserSerialNumberPolicy.HasFlag(UserSerialNumberPolicy.allowAbsence) ||
                    !cfgMid.UserSerialNumberPolicy.HasFlag(UserSerialNumberPolicy.allowMismatch) ||
                    cfgMid.UserSerialNumberPolicy.HasFlag(UserSerialNumberPolicy.warnMismatch);

                if (needCheckUserSerialNumber /* cfgMid.UserSerialNumberPolicy != UserSerialNumberPolicy.ignore */ && ctx.Data.ContainsKey(UKEYSN))
                {
                    req.UserSerialNumber = (string)ctx.Data[UKEYSN];
                }
                AuthResponseDto rsp;
                for (int i = ageSeconds; i <= cfgMid.RequestTimeOutSeconds; i += cfgMid.PollResponseIntervalSeconds)
                {
                    rsp = getWebClient().PollSignature(req, msspTransId);
                    switch (rsp.Status.Code)
                    {
                    case ServiceStatusCode.SIGNATURE:
                    case ServiceStatusCode.VALID_SIGNATURE:
                        ctx.Data[STATE] = 10;
                        logger.TraceEvent(TraceEventType.Information, 0, "AUTHN_OK: " + logInfo + ", state:" + ctx.Data[STATE] + ", i:" + i);
                        Logging.Log.AuthenticationSuccess(state, (int)ctx.Data[STATE], upn, msspTransId);
                        // EventLog.WriteEntry(EVENTLOGSource, "Authentication success for " + upn, EventLogEntryType.SuccessAudit, 100);
                        claims = ClaimsHwToken;
                        return(null);

                    case ServiceStatusCode.OUSTANDING_TRANSACTION:
                        ctx.Data[STATE] = 11;
                        logger.TraceEvent(TraceEventType.Verbose, 0, "AUTHN_PENDING: " + logInfo + ", state:" + ctx.Data[STATE] + ", i:" + i);
                        Logging.Log.AuthenticationPending(state, (int)ctx.Data[STATE], upn, msspTransId);
                        System.Threading.Thread.Sleep(1000);
                        break;

                    case ServiceStatusCode.EXPIRED_TRANSACTION:
                        ctx.Data[STATE] = 13;
                        logger.TraceEvent(TraceEventType.Information, 0, "AUTHN_TIMEOUT_MID: " + logInfo + ", state:" + ctx.Data[STATE] + ", i:" + i);
                        Logging.Log.AuthenticationFail(state, (int)ctx.Data[STATE], upn, msspTransId, Enum.GetName(typeof(ServiceStatusCode), rsp.Status.Code));
                        return(new AdapterPresentation(AuthView.RetryOrCancel, cfgAdfs, rsp));

                    case ServiceStatusCode.PB_SIGNATURE_PROCESS:
                        ctx.Data[STATE] = 13;
                        logger.TraceEvent(TraceEventType.Information, 0, "AUTHN_SIGN_PROCESS: " + logInfo + ", state:" + ctx.Data[STATE] + ", i:" + i);
                        Logging.Log.AuthenticationFail(state, (int)ctx.Data[STATE], upn, msspTransId, Enum.GetName(typeof(ServiceStatusCode), rsp.Status.Code));
                        return(new AdapterPresentation(AuthView.RetryOrCancel, cfgAdfs, rsp));

                    case ServiceStatusCode.USER_CANCEL:
                        ctx.Data[STATE] = 14;
                        logger.TraceEvent(TraceEventType.Information, 0, "AUTHN_CANCEL: " + logInfo + ", state:" + ctx.Data[STATE] + ", i:" + i);
                        Logging.Log.AuthenticationCancel(state, (int)ctx.Data[STATE], upn, msspTransId);
                        return(new AdapterPresentation(AuthView.RetryOrCancel, cfgAdfs, rsp));

                    default:
                        ctx.Data[STATE] = 12;
                        logger.TraceEvent(TraceEventType.Error, 0, "TECH_ERROR: " + logInfo + ", state:" + ctx.Data[STATE] + ", srvStatusCode:" + (int)rsp.Status.Code
                                          + ", srvStatusMsg:\"" + rsp.Status.Message + "\", srvStatusDetail:\"" + (string)rsp.Detail + "\"");
                        if (rsp.Status.Color == ServiceStatusColor.Yellow || rsp.Status.Color == ServiceStatusColor.Green)
                        {
                            Logging.Log.AuthenticationFail(state, (int)ctx.Data[STATE], upn, msspTransId, Enum.GetName(typeof(ServiceStatusCode), rsp.Status.Code));
                        }
                        else
                        {
                            Logging.Log.AuthenticationTechnicalError(state, (int)ctx.Data[STATE], upn, msspTransId, Enum.GetName(typeof(ServiceStatusCode), rsp.Status.Code), (string)rsp.Detail);
                        };
                        return(new AdapterPresentation(AuthView.AuthError, cfgAdfs, rsp));
                    }
                }
                ;  // for-loop

                ctx.Data[STATE] = 13;
                logger.TraceEvent(TraceEventType.Information, 0, "AUTHN_TIMEOUT_ADFS: " + logInfo + ", state:" + ctx.Data[STATE]);
                Logging.Log.AuthenticationTimeout(state, (int)ctx.Data[STATE], cfgMid.RequestTimeOutSeconds, upn, msspTransId);
                return(new AdapterPresentation(AuthView.RetryOrCancel, cfgAdfs, "Timeout."));
            }
            else if (formAction == "Retry")
            {
                switch (state)
                {
                case 13:
                case 5:
                case 35:
                case 4:
                case 14:
                case 34:
                {           // check session age and number of retries
                    int ageSeconds = (int)((DateTime.UtcNow.Ticks / 10000 - (long)ctx.Data[SESSBEGIN]) / 1000);
                    if (ageSeconds >= cfgAdfs.SessionTimeoutSeconds)
                    {
                        logger.TraceEvent(TraceEventType.Information, 0, "AUTHN_SESSION_TIMEOUT: " + logInfo + ", state:" + ctx.Data[STATE] + ", age:" + ageSeconds);
                        Logging.Log.SessionTimeout(state, (int)ctx.Data[STATE], ageSeconds, upn, msspTransId);
                        ctx.Data[STATE] = 22;
                    }
                    else if ((int)ctx.Data[SESSTRIES] >= cfgAdfs.SessionMaxTries)
                    {
                        logger.TraceEvent(TraceEventType.Information, 0, "AUTHN_SESSION_OVERTRIES: " + logInfo + ", state:" + ctx.Data[STATE]);
                        Logging.Log.SessionTooMuchRetries(state, (int)ctx.Data[STATE], (int)ctx.Data[SESSTRIES], upn, msspTransId);
                        ctx.Data[STATE] = 22;
                    }
                    ;
                    if ((int)ctx.Data[STATE] == 22)
                    {
                        return(new AdapterPresentation(AuthView.AutoLogout, cfgAdfs));
                    }
                }
                    // start a new asynchronous RequestSignature
                    AuthRequestDto req = new AuthRequestDto();
                    req.PhoneNumber  = (string)ctx.Data[MSISDN];
                    req.UserLanguage = (UserLanguage)Enum.Parse(typeof(UserLanguage), resMgr.GetString(RES_LANG, culture));
                    string uiTrxId = Util.BuildRandomBase64Chars(cfgAdfs.LoginNonceLength);
                    req.DataToBeSigned = _buildMobileIdLoginPrompt(req.UserLanguage, culture, uiTrxId);
                    req.TimeOut        = cfgMid.RequestTimeOutSeconds;
                    bool needCheckUserSerialNumber =
                        !cfgMid.UserSerialNumberPolicy.HasFlag(UserSerialNumberPolicy.allowAbsence) ||
                        !cfgMid.UserSerialNumberPolicy.HasFlag(UserSerialNumberPolicy.allowMismatch) ||
                        cfgMid.UserSerialNumberPolicy.HasFlag(UserSerialNumberPolicy.warnMismatch);
                    if (needCheckUserSerialNumber /* cfgMid.UserSerialNumberPolicy != UserSerialNumberPolicy.ignore */ && ctx.Data.ContainsKey(UKEYSN))
                    {
                        req.UserSerialNumber = (string)ctx.Data[UKEYSN];
                    }
                    ctx.Data[AUTHBEGIN] = DateTime.UtcNow.Ticks / 10000;
                    AuthResponseDto rsp = getWebClient().RequestSignature(req, true /* async */);
                    ctx.Data[SESSTRIES] = (int)ctx.Data[SESSTRIES] + 1;
                    string logMsg = "svcStatus:" + (int)rsp.Status.Code + ", mssTransId:\"" + rsp.MsspTransId + "\", state:";

                    switch (rsp.Status.Code)
                    {
                    case ServiceStatusCode.VALID_SIGNATURE:
                    case ServiceStatusCode.SIGNATURE:
                        ctx.Data[STATE]     = 33;
                        ctx.Data[MSSPTRXID] = rsp.MsspTransId;
                        logger.TraceEvent(TraceEventType.Verbose, 0, logMsg + ctx.Data[STATE]);
                        Logging.Log.AuthenticationSuccess(state, (int)ctx.Data[STATE], upn, msspTransId);
                        return(new AdapterPresentation(AuthView.TransferCtx, cfgAdfs));

                    case ServiceStatusCode.REQUEST_OK:
                        ctx.Data[STATE]     = 31;
                        ctx.Data[MSSPTRXID] = rsp.MsspTransId;
                        ctx.Data[DTBS]      = req.DataToBeSigned;
                        logger.TraceEvent(TraceEventType.Verbose, 0, logMsg + ctx.Data[STATE]);
                        Logging.Log.AuthenticationContinue(state, (int)ctx.Data[STATE], upn, msspTransId);
                        return(new AdapterPresentation(AuthView.SignRequestSent, cfgAdfs, req.PhoneNumber, uiTrxId, cfgMid.PollResponseDelaySeconds * 1000));

                    case ServiceStatusCode.USER_CANCEL:
                        ctx.Data[STATE] = 34;
                        logger.TraceEvent(TraceEventType.Verbose, 0, logMsg + ctx.Data[STATE]);
                        Logging.Log.AuthenticationCancel(state, (int)ctx.Data[STATE], upn, msspTransId);
                        return(new AdapterPresentation(AuthView.RetryOrCancel, cfgAdfs, rsp));

                    case ServiceStatusCode.EXPIRED_TRANSACTION:
                    case ServiceStatusCode.PB_SIGNATURE_PROCESS:
                        ctx.Data[STATE] = 35;
                        logger.TraceEvent(TraceEventType.Verbose, 0, logMsg + ctx.Data[STATE]);
                        Logging.Log.AuthenticationFail(state, (int)ctx.Data[STATE], upn, msspTransId, Enum.GetName(typeof(ServiceStatusCode), rsp.Status.Code));
                        return(new AdapterPresentation(AuthView.RetryOrCancel, cfgAdfs, rsp));

                    default:
                        ctx.Data[STATE] = 32;
                        logger.TraceEvent((rsp.Status.Color == ServiceStatusColor.Yellow ? TraceEventType.Warning : TraceEventType.Error),
                                          0, logMsg + ctx.Data[STATE] + ", errMsg:\"" + rsp.Status.Message + "\", errDetail:\"" + rsp.Detail + "\"");
                        Logging.Log.AuthenticationTechnicalError(state, (int)ctx.Data[STATE], upn, msspTransId, Enum.GetName(typeof(ServiceStatusCode), rsp.Status.Code), rsp.Detail.ToString());
                        return(new AdapterPresentation(AuthView.AuthError, cfgAdfs, rsp));
                    }
                    ;

                default:
                    logger.TraceEvent(TraceEventType.Error, 0, "BAD_STATE: " + logInfo + ", state:" + state);
                    Logging.Log.AuthenticationFail(state, (int)ctx.Data[STATE], upn, msspTransId, "BAD_STATE");
                    return(new AdapterPresentation(AuthView.AuthError, cfgAdfs, "action:\"Retry\"; state:" + state));
                }
            }
            //else if (formAction == "SignOut")
            //{
            //    logger.TraceEvent(TraceEventType.Verbose, 0, "SIGNOUT: " + logInfo + "; state:" + state);
            //    return new AdapterPresentation(AuthView.AutoLogout, cfgAdfs); // could lead to endless-loop
            //}
            else
            {
                logger.TraceEvent(TraceEventType.Error, 0, "Unsupported formAction: " + formAction);
                Logging.Log.AuthenticationBadForm(state, (int)ctx.Data[STATE], upn, msspTransId, formAction);
                return(new AdapterPresentation(AuthView.AuthError, cfgAdfs, new AuthResponseDto(ServiceStatusCode.GeneralClientError)));
            }
        }
Esempio n. 32
0
 public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, HttpListenerRequest request, out Claim[] claims)
 {
     DummyLogger.Log("IAuthenticationAdapter.TryEndAuthentication");
     return(new DummyAdapterPresentation(context, proofData, request, out claims));
 }
Esempio n. 33
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext authContext, IProofData proofData, HttpListenerRequest request, out Claim[] outgoingClaims)
        {
            outgoingClaims = new Claim[0];
            string errorMssg = ValidateProofData(proofData, authContext);

            if (string.IsNullOrWhiteSpace(errorMssg))
            {
                outgoingClaims = new[]
                {
                    new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod",
                              "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/hardwaretoken")
                };

                return(null);
            }
            else
            {
                return(new CustomPresentationForm(phoneMssg, errorMssg));
            }
        }
        /// <summary>
        /// Called by AD FS to perform the actual authentication.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="proofData"></param>
        /// <param name="request"></param>
        /// <param name="claims"></param>
        /// <returns> If the Authentication Adapter has successfully performed
        /// the authentication a claim of type
        /// http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod
        /// is returned
        /// </returns>
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, System.Net.HttpListenerRequest request, out System.Security.Claims.Claim[] claims)
        {
            claims = null;
            IAdapterPresentation result = null;

            // Ensure the submitted form isn't empty.
            if (proofData == null || proofData.Properties == null || !proofData.Properties.ContainsKey("pin"))
            {
                if (this.debugLogging)
                {
                    Logging.LogMessage("Either proofData is null or does not contain required property");
                }
                throw new ExternalAuthenticationException(resMgr.GetString("Error_InvalidPIN", new System.Globalization.CultureInfo(context.Lcid)), context);
            }
            string pin      = proofData.Properties["pin"].ToString();
            string userName = this.identityClaim.Split('\\')[1];

            // Construct RADIUS auth request.
            var authPacket = radiusClient.Authenticate(userName, pin);

            byte[] bIP = IPAddress.Parse(appConfig.NasAddress).GetAddressBytes();
            authPacket.SetAttribute(new RadiusAttribute(RadiusAttributeType.NAS_IP_ADDRESS, bIP));
            var receivedPacket = radiusClient.SendAndReceivePacket(authPacket).Result;

            // Handle no response from RADIUS server.
            if (receivedPacket == null)
            {
                if (this.debugLogging)
                {
                    Logging.LogMessage("No response received from RADIUS server.");
                }
                throw new ExternalAuthenticationException(resMgr.GetString("Error_RADIUS_NULL", new System.Globalization.CultureInfo(context.Lcid)), context);
            }

            // Examine the different RADIUS responses
            switch (receivedPacket.PacketType)
            {
            case RadiusCode.ACCESS_ACCEPT:
                System.Security.Claims.Claim claim = new System.Security.Claims.Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod", "http://schemas.microsoft.com/ws/2012/12/authmethod/otp");
                claims = new System.Security.Claims.Claim[] { claim };
                break;

            case RadiusCode.ACCESS_CHALLENGE:
                // No way to cater for this. Fail.
                result = new AdapterPresentation(resMgr.GetString("Error_RADIUS_ACCESS_CHALLENGE", new System.Globalization.CultureInfo(context.Lcid)), false);
                break;

            case RadiusCode.ACCESS_REJECT:
                result = new AdapterPresentation(resMgr.GetString("Error_InvalidPIN", new System.Globalization.CultureInfo(context.Lcid)), false);
                break;

            default:
                result = new AdapterPresentation(resMgr.GetString("Error_RADIUS_OTHER", new System.Globalization.CultureInfo(context.Lcid)), false);
                break;
            }

            if (this.debugLogging)
            {
                Logging.LogMessage(
                    "Processed authentication response." + Environment.NewLine +
                    "Packet Type: " + receivedPacket.PacketType.ToString() + Environment.NewLine +
                    "User: " + this.identityClaim);
            }

            return(result);
        }
Esempio n. 35
0
        public IAdapterPresentation TryEndAuthentication(IAuthenticationContext context, IProofData proofData, HttpListenerRequest request, out Claim[] outgoingClaims)
        {
            string response = string.Empty;

            outgoingClaims = new Claim[0];

            if (ValidateProofData(proofData, context, out response))
            {
                outgoingClaims = new[]
                {
                    new Claim(
                        "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod",
                        "http://schemas.microsoft.com/ws/2012/12/authmethod/otp"
                        )
                };

                return(null);
            }

            return(new AdapterPresentation(response, false));
        }