protected void Btn_Logoff_Click(object sender, EventArgs e)
 {
     // Example of logging required by the requirements SLO1 ("Id of internal account that is matched to SAML Assertion")
     // Since FormsAuthentication is used in this sample, the user name to log can be found in context.User.Identity.Name
     AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "ServiceProvider logoff requested, local user id: " + HttpContext.Current.User.Identity.Name);
     Response.Redirect("logout.ashx");
 }
Exemplo n.º 2
0
        /// <summary>
        /// Deserializes an assertion, verifies its signature and logs in the user if the assertion is valid.
        /// </summary>
        private void HandleAssertion(HttpContext context, XmlElement elem)
        {
            Trace.TraceMethodCalled(GetType(), "HandleAssertion");

            string issuer = GetIssuer(elem);

            IDPEndPoint endp = RetrieveIDPConfiguration(issuer);

            AuditLogging.IdpId = endp.Id;

            PreHandleAssertion(context, elem, endp);

            bool quirksMode = false;

            if (endp != null)
            {
                quirksMode = endp.QuirksMode;
            }

            //VALTECH: 2011-05-19: Changed constructor to one using default assertion profile
            //ORIGINAL: Saml20Assertion assertion = new Saml20Assertion(elem, null, quirksMode);
            Saml20Assertion assertion = new Saml20Assertion(elem, null, AssertionProfile.Core, quirksMode);

            if (endp == null || endp.metadata == null)
            {
                AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                      "Unknown login IDP, assertion: " + elem);

                HandleError(context, Resources.UnknownLoginIDP);
                return;
            }

            if (!endp.OmitAssertionSignatureCheck)
            {
                if (!assertion.CheckSignature(GetTrustedSigners(endp.metadata.GetKeys(KeyTypes.signing), endp)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                          "Invalid signature, assertion: " + elem);

                    HandleError(context, Resources.SignatureInvalid);
                    return;
                }
            }

            if (assertion.IsExpired())
            {
                AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                      "Assertion expired, assertion: " + elem);

                HandleError(context, Resources.AssertionExpired);
                return;
            }

            CheckConditions(context, assertion);
            AuditLogging.AssertionId = assertion.Id;
            AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                  "Assertion validated succesfully");

            DoLogin(context, assertion);
        }
 public void AuditLoggerConfigurationTest()
 {
     AuditLoggerMock.LogEntryCalledCount = 0;
     Assert.IsTrue(AuditLoggerMock.LogEntryCalledCount == 0);
     AuditLogging.logEntry(Direction.IN, Operation.LOGIN, "Testing");
     Assert.IsTrue(AuditLoggerMock.LogEntryCalledCount > 0);
 }
Exemplo n.º 4
0
        public async Task <IActionResult> Index(string yearOrDistrict)
        {
            JObject      clientInfo = getClientInformation();
            AuditLogging audit      = new AuditLogging();

            audit.IPAddress    = (string)clientInfo["IPv4"];
            audit.Location     = (string)clientInfo["latitude"] + "," + (string)clientInfo["longitude"] + "," + (string)clientInfo["city"];
            audit.TimeOfAction = DateTime.Now;
            _context.Add(audit);
            await _context.SaveChangesAsync();

            if (yearOrDistrict == null)
            {
                return(NotFound());
            }

            // If yearOrDistrict is a int, assume this is a year; else a district
            if (Regex.IsMatch(yearOrDistrict, @"^\d+$"))
            {
                ViewBag.message      = "Index1";
                ViewBag.electionYear = yearOrDistrict;
                return(View(await _context.Elections.Where(m => m.Year == yearOrDistrict).ToListAsync()));
            }
            else
            {
                ViewBag.message       = "Index2";
                ViewBag.districtValue = yearOrDistrict;
                return(View(await _context.Elections.Where(m => m.District == yearOrDistrict).ToListAsync()));
            }
        }
Exemplo n.º 5
0
        private void DoLogin(HttpContext context, Saml20Assertion assertion)
        {
            SessionStore.AssociateUserIdWithCurrentSession(assertion.Subject.Value);

            // The assertion is what keeps the session alive. If it is ever removed ... the session will appear as removed in the SessionStoreProvider because Saml20AssertionLite is the only thing kept in session store when login flow is completed..
            SessionStore.CurrentSession[SessionConstants.Saml20AssertionLite] = Saml20AssertionLite.ToLite(assertion);

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.Login, assertion.Subject.Value, assertion.SessionIndex, assertion.Subject.Format));
            }

            string assuranceLevel = GetAssuranceLevel(assertion) ?? "(Unknown)";

            AuditLogging.logEntry(Direction.IN, Operation.LOGIN, string.Format("Subject: {0} NameIDFormat: {1}  Level of authentication: {2}  Session timeout in minutes: {3}", assertion.Subject.Value, assertion.Subject.Format, assuranceLevel, FederationConfig.GetConfig().SessionTimeout));


            foreach (IAction action in Actions.Actions.GetActions())
            {
                Trace.TraceMethodCalled(action.GetType(), "LoginAction()");

                action.LoginAction(this, context, assertion);

                Trace.TraceMethodDone(action.GetType(), "LoginAction()");
            }
        }
Exemplo n.º 6
0
        public async Task <IActionResult> Post(IFormFile files)
        {
            JObject      clientInfo = getClientInformation();
            AuditLogging audit      = new AuditLogging();

            audit.IPAddress    = (string)clientInfo["IPv4"];
            audit.Location     = (string)clientInfo["latitude"] + "," + (string)clientInfo["longitude"] + "," + (string)clientInfo["city"];
            audit.TimeOfAction = DateTime.Now;
            _context.Add(audit);

            HashSet <Election> electionSet = new HashSet <Election>();

            using (var memoryStream = new MemoryStream())
            {
                await files.CopyToAsync(memoryStream).ConfigureAwait(false);

                using (var package = new ExcelPackage(memoryStream))
                {
                    var workSheet = package.Workbook.Worksheets.First();
                    var rowCount  = workSheet.Dimension?.Rows;
                    var colCount  = workSheet.Dimension?.Columns;


                    for (int row = 2; row <= rowCount.Value; row++)
                    {
                        electionSet.Add(new Election
                        {
                            Year = workSheet.Cells[row, 1].Text,
                            Constituency_Number      = workSheet.Cells[row, 2].Text,
                            District                 = workSheet.Cells[row, 3].Text,
                            Constituency             = workSheet.Cells[row, 4].Text,
                            Latitude                 = float.Parse(workSheet.Cells[row, 5].Text),
                            Longitude                = float.Parse(workSheet.Cells[row, 6].Text),
                            Registered_Voters        = int.Parse(workSheet.Cells[row, 7].Text),
                            ValidVotes               = int.Parse(workSheet.Cells[row, 8].Text),
                            Voter_TurnOut_Percentage = float.Parse(workSheet.Cells[row, 9].Text),
                            Winner           = workSheet.Cells[row, 10].Text,
                            RunnerUp         = workSheet.Cells[row, 11].Text,
                            WinnerVotes      = int.Parse(workSheet.Cells[row, 12].Text),
                            RunnerUpVotes    = int.Parse(workSheet.Cells[row, 13].Text),
                            MarginVotes      = int.Parse(workSheet.Cells[row, 14].Text),
                            MarginPercentage = float.Parse(workSheet.Cells[row, 15].Text),
                            Magnitude        = int.Parse(workSheet.Cells[row, 16].Text)
                        });
                    }
                }
            }

            foreach (var item in electionSet)
            {
                if (_context.Elections.Where(m => m.Year == item.Year && m.Constituency == item.Constituency).Count() == 0)
                {
                    _context.Add(item);
                }
            }
            await _context.SaveChangesAsync();

            return(RedirectToAction(nameof(Index)));
        }
 public void LogoutAction(dk.nita.saml20.protocol.AbstractEndpointHandler handler, HttpContext context, bool IdPInitiated)
 {
     // Example of logging required by the requirements SLO1 ("Id of internal user account")
     // Since FormsAuthentication is used in this sample, the user name to log can be found in context.User.Identity.Name
     // The login will be not be cleared until next redirect due to the way FormsAuthentication works, so we will have to check Saml20Identity.IsInitialized() too
     AuditLogging.logEntry(Direction.IN, Operation.LOGOUT, "ServiceProvider logout",
                           "SP local user id: " + (context.User.Identity.IsAuthenticated ? context.User.Identity.Name : "none") + " login status: " + Saml20Identity.IsInitialized());
 }
Exemplo n.º 8
0
        /// <summary>
        /// Invoked when a LoA validation has failed. Adds a log entry to the audit log and displays an error page.
        /// </summary>
        protected void HandleLoaValidationError(string errorMessageTemplate, string sourceLoa, string requiredMinLoa,
                                                HttpContext context, XmlElement assertionXml)
        {
            var loaErrorMessage = string.Format(errorMessageTemplate, sourceLoa, requiredMinLoa);

            AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                  loaErrorMessage + " Assertion: " + assertionXml.OuterXml);

            HandleError(context, loaErrorMessage, (m) => new Saml20NsisLoaException(m));
        }
 protected void Page_Load(object sender, EventArgs e)
 {
     Title = "My page on SP " + SAML20FederationConfig.GetConfig().ServiceProvider.ID;
     if (Request.QueryString["action"] == "sso")
     {
         // Example of logging required by the requirements BSA6/SSO6 ("Id of internal account that is matched to SAML Assertion")
         // Since FormsAuthentication is used in this sample, the user name to log can be found in context.User.Identity.Name.
         // This user will not be set until after a new redirect, so unfortunately we cannot just log it in our LogAction.LoginAction
         AuditLogging.logEntry(Direction.IN, Operation.LOGIN, "ServiceProvider login",
                               "SP internal user id: " +
                               (Context.User.Identity.IsAuthenticated ? Context.User.Identity.Name : "(not logged in)"));
     }
 }
Exemplo n.º 10
0
        public async Task <IActionResult> Index()
        {
            JObject      clientInfo = getClientInformation();
            AuditLogging audit      = new AuditLogging();

            audit.IPAddress    = (string)clientInfo["IPv4"];
            audit.Location     = (string)clientInfo["latitude"] + "," + (string)clientInfo["longitude"] + "," + (string)clientInfo["city"];
            audit.TimeOfAction = DateTime.Now;
            _context.Add(audit);
            await _context.SaveChangesAsync();

            // Return a message "Index0", To load _LoadChartIndex0 in /Elections
            ViewBag.message = "Index0";
            return(View(await _context.Elections.ToListAsync()));
        }
Exemplo n.º 11
0
        /// <summary>
        /// Enables processing of HTTP Web requests by a custom HttpHandler that implements the <see cref="T:System.Web.IHttpHandler"/> interface.
        /// </summary>
        /// <param name="context">An <see cref="T:System.Web.SamlContext"/> object that provides references to the intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
        public override void ProcessRequest(SamlHttpContext context)
        {
            try
            {
                Trace.TraceMethodCalled(GetType(), "ProcessRequest()");
                SAML20FederationConfig config = SAML20FederationConfig.GetConfig();

                if (config == null)
                {
                    throw new Saml20Exception("Missing SAML20Federation config section in web.config.");
                }

                Saml20ServiceEndpoint endp
                    = config.ServiceProvider.serviceEndpoints.Find(delegate(Saml20ServiceEndpoint ep) { return(ep.endpointType == EndpointType.SIGNON); });

                if (endp == null)
                {
                    throw new Saml20Exception("Signon endpoint not found in configuration");
                }

                string returnUrl = config.ServiceProvider.Server + endp.localPath + "?r=1";

                SamlHttpCookie samlIdp = context.Request.Cookies[CommonDomainCookie.COMMON_DOMAIN_COOKIE_NAME];

                if (samlIdp != null)
                {
                    returnUrl += "&_saml_idp=" + HttpUtility.UrlEncode(samlIdp.Value);

                    if (Trace.ShouldTrace(TraceEventType.Information))
                    {
                        Trace.TraceData(TraceEventType.Information, string.Format(Tracing.CDC, samlIdp.Value));
                    }

                    AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_REDIRECT,
                                          "Redirection to Signon endpoint found in Common Domain Cookie: " + samlIdp.Value);
                }
                else
                {
                    AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_REDIRECT,
                                          "Redirection to Signon endpoint, no Common Domain Cookie found: " + returnUrl);
                }
                context.Response.Redirect(returnUrl);
            }
            catch (Exception ex)
            {
                HandleError(context, ex);
            }
        }
Exemplo n.º 12
0
        public async Task <JsonResult> Audit(AuditLogging jObject)
        {
            if (jObject != null)
            {
                _context.Add(jObject);
                await _context.SaveChangesAsync();
            }
            var audit = _context.Set <AuditLogging>().Select(x => new
            {
                x.Country,
                x.CountryCode,
                x.TimeOfAction
            });

            return(Json(audit));
        }
Exemplo n.º 13
0
        /// <summary>
        /// Handles a request.
        /// </summary>
        /// <param name="context">The context.</param>
        protected override void Handle(HttpContext context)
        {
            Trace.TraceMethodCalled(GetType(), "Handle()");

            //Some IdP's are known to fail to set an actual value in the SOAPAction header
            //so we just check for the existence of the header field.
            if (Array.Exists(context.Request.Headers.AllKeys, delegate(string s) { return(s == SOAPConstants.SOAPAction); }))
            {
                SessionStore.AssertSessionExists();

                HandleSOAP(context, context.Request.InputStream);
                return;
            }

            if (!string.IsNullOrEmpty(context.Request.Params["SAMLart"]))
            {
                SessionStore.AssertSessionExists();

                HandleArtifact(context);
            }

            if (!string.IsNullOrEmpty(context.Request.Params["SamlResponse"]))
            {
                SessionStore.AssertSessionExists();

                HandleResponse(context);
            }
            else
            {
                if (SAML20FederationConfig.GetConfig().CommonDomain.Enabled&& context.Request.QueryString["r"] == null &&
                    context.Request.Params["cidp"] == null)
                {
                    AuditLogging.logEntry(Direction.OUT, Operation.DISCOVER, "Redirecting to Common Domain for IDP discovery");
                    context.Response.Redirect(SAML20FederationConfig.GetConfig().CommonDomain.LocalReaderEndpoint);
                }
                else
                {
                    AuditLogging.logEntry(Direction.IN, Operation.ACCESS,
                                          "User accessing resource: " + context.Request.RawUrl +
                                          " without authentication.");

                    SessionStore.CreateSessionIfNotExists();

                    SendRequest(context);
                }
            }
        }
        private void DoLogin(HttpContext context, Saml20Assertion assertion)
        {
            //User is now logged in at IDP specified in tmp
            context.Session[IDPLoginSessionKey] = context.Session[IDPTempSessionKey];
            context.Session[IDPSessionIdKey]    = assertion.SessionIndex;
            context.Session[IDPNameIdFormat]    = assertion.Subject.Format;
            context.Session[IDPNameId]          = assertion.Subject.Value;

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.Login, assertion.Subject.Value, assertion.SessionIndex, assertion.Subject.Format));
            }

            string inResponseTo = "(unknown)";

            if (assertion.GetSubjectConfirmationData() != null && assertion.GetSubjectConfirmationData().InResponseTo != null)
            {
                inResponseTo = assertion.GetSubjectConfirmationData().InResponseTo;
            }

            string assuranceLevel = "(unknown)";

            foreach (var attribute in assertion.Attributes)
            {
                if (attribute.Name == "dk:gov:saml:attribute:AssuranceLevel" &&
                    attribute.AttributeValue != null &&
                    attribute.AttributeValue.Length > 0)
                {
                    assuranceLevel = attribute.AttributeValue[0];
                }
            }

            AuditLogging.logEntry(Direction.IN, Operation.LOGIN, string.Format("Subject: {0} NameIDFormat: {1}  Level of authentication: {2}  Session timeout in minutes: {3}", assertion.Subject.Value, assertion.Subject.Format, assuranceLevel, HttpContext.Current.Session.Timeout));


            foreach (IAction action in Actions.Actions.GetActions())
            {
                Trace.TraceMethodCalled(action.GetType(), "LoginAction()");

                action.LoginAction(this, context, assertion);

                Trace.TraceMethodDone(action.GetType(), "LoginAction()");
            }
        }
Exemplo n.º 15
0
        private static void CheckReplayAttack(HttpContext context, string inResponseTo)
        {
            var expectedInResponseToSessionState = SessionStore.CurrentSession[SessionConstants.ExpectedInResponseTo];

            SessionStore.CurrentSession[SessionConstants.ExpectedInResponseTo] = null; // Ensure that no more responses can be received.

            string expectedInResponseTo = expectedInResponseToSessionState.ToString();

            if (string.IsNullOrEmpty(expectedInResponseTo) || string.IsNullOrEmpty(inResponseTo))
            {
                throw new Saml20Exception("Empty protocol message id is not allowed.");
            }

            if (inResponseTo != expectedInResponseTo)
            {
                AuditLogging.logEntry(Direction.IN, Operation.LOGIN, string.Format("Unexpected value {0} for InResponseTo, expected {1}, possible replay attack!", inResponseTo, expectedInResponseTo));
                throw new Saml20Exception("Replay attack.");
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Validates that the <see cref="LogoutRequest"/> has not expired, by checking that NotOnOrAfter + allowedTimeSkew is greater than current time.
        /// Only validated if <see cref="LogoutRequest.NotOnOrAfter"/> is not null.
        /// </summary>
        /// <param name="context">The requests <see cref="HttpContext"/></param>
        /// <param name="logoutRequest">The LogoutRequest to validate</param>
        /// <exception cref="T:System.Threading.ThreadAbortException">Throws ThreadAbortException if validation fails, and config is set to show an error page.</exception>
        /// <exception cref="Saml20Exception">Throws Saml20Exception if validation fails, and config is set to throw exception.</exception>
        private void ValidateNotOnOrAfter(HttpContext context, LogoutRequest logoutRequest)
        {
            if (!logoutRequest.NotOnOrAfter.HasValue)
            {
                return;
            }

            var notOnOrAfter         = logoutRequest.NotOnOrAfter.Value;
            var allowedClockSkewTime = FederationConfig.GetConfig().AllowedClockSkewMinutes;
            var now = DateTime.UtcNow;

            if (notOnOrAfter.AddMinutes(allowedClockSkewTime) > now)
            {
                return;
            }

            var errormessage = $"Logout request expired. NotOnOrAfter={notOnOrAfter}, RequestReceived={now}";

            AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, errormessage);
            HandleError(context, errormessage);
        }
        private static void CheckReplayAttack(HttpContext context, string inResponseTo)
        {
            var expectedInResponseToSessionState = SessionFactory.SessionContext.Current[SessionConstants.ExpectedInResponseTo];

            if (expectedInResponseToSessionState == null)
            {
                throw new Saml20Exception("Your session has been disconnected, please logon again");
            }

            string expectedInResponseTo = expectedInResponseToSessionState.ToString();

            if (string.IsNullOrEmpty(expectedInResponseTo) || string.IsNullOrEmpty(inResponseTo))
            {
                throw new Saml20Exception("Empty protocol message id is not allowed.");
            }

            if (inResponseTo != expectedInResponseTo)
            {
                AuditLogging.logEntry(Direction.IN, Operation.LOGIN, string.Format("Unexpected value {0} for InResponseTo, expected {1}, possible replay attack!", inResponseTo, expectedInResponseTo));
                throw new Saml20Exception("Replay attack.");
            }
        }
Exemplo n.º 18
0
        private void DoLogin(HttpContext context, Saml20Assertion assertion)
        {
            //User is now logged in at IDP specified in tmp
            context.Session[IDPLoginSessionKey] = context.Session[IDPTempSessionKey];
            context.Session[IDPSessionIdKey]    = assertion.SessionIndex;
            context.Session[IDPNameIdFormat]    = assertion.Subject.Format;

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.Login, assertion.Subject.Value, assertion.SessionIndex, assertion.Subject.Format));
            }
            AuditLogging.logEntry(Direction.IN, Operation.LOGIN, "Subject: " + assertion.Subject.Value + " NameIDFormat: " + assertion.Subject.Format);


            foreach (IAction action in Actions.Actions.GetActions())
            {
                Trace.TraceMethodCalled(action.GetType(), "LoginAction()");

                action.LoginAction(this, context, assertion);

                Trace.TraceMethodDone(action.GetType(), "LoginAction()");
            }
        }
Exemplo n.º 19
0
        /// <summary>
        /// Validates the LoA of the session to determine if it adheres to the configured requirements of the service provider.
        /// If validation fails, response is modified to display an error page.
        /// </summary>
        /// <returns>True if valid, otherwise false.</returns>
        private bool ValidateLoA(HttpContext context, Saml20Assertion assertion, XmlElement assertionXml)
        {
            // If AssuranceLevel is allowed, and it's present in assertion, validate.
            var allowAL     = SAML20FederationConfig.GetConfig().AllowAssuranceLevel;
            var assertionAL = GetAssuranceLevel(assertion);

            if (allowAL && assertionAL != null)
            {
                return(ValidateAssuranceLevel(assertionAL, context, assertionXml));
            }

            // If NSIS LoA is missing, invalidate.
            var assertionNsisLoa = GetNsisLoa(assertion);

            if (assertionNsisLoa == null)
            {
                AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST, Resources.NsisLoaMissing + " Assertion: " + assertionXml.OuterXml);
                HandleError(context, Resources.NsisLoaMissing);
                return(false);
            }

            return(ValidateNsisLoa(assertionNsisLoa, context, assertionXml));
        }
Exemplo n.º 20
0
 public ActionResult Edit(PayrollPeriod obj)
 {
     if (obj.PeriodStageID == "C" || obj.PeriodStageID == "O")
     {
     }
     else
     {
         ModelState.AddModelError("PeriodStageID", "Stage should be O or C.");
     }
     if (ModelState.IsValid)
     {
         if (obj.PeriodStageID == "C")
         {
             VMLoggedUser LoggedInUser = Session["LoggedInUser"] as VMLoggedUser;
             AuditLogging.SaveAuditLog(obj, LoggedInUser.PUserID, EnumControllerNames.Payroll, EnumActionNames.Edit);
             DDService.ProcessMonthlyERPAttendance(obj.PRStartDate.Value, LoggedInUser.UserEmpID.Value);
         }
         PayrollPeriodService.PostEdit(obj);
         return(Json("OK", JsonRequestBehavior.AllowGet));
     }
     HelperMethod(obj);
     return(PartialView("Edit", obj));
 }
Exemplo n.º 21
0
        private void DoLogin(HttpContext context, Saml20Assertion assertion)
        {
            SessionFactory.SessionContext.AssociateUserIdWithCurrentSession(assertion.Subject.Value);
            SessionFactory.SessionContext.Current[SessionConstants.Saml20AssertionLite] = Saml20AssertionLite.ToLite(assertion);

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.Login, assertion.Subject.Value, assertion.SessionIndex, assertion.Subject.Format));
            }

            string assuranceLevel = GetAssuranceLevel(assertion) ?? "(Unknown)";

            AuditLogging.logEntry(Direction.IN, Operation.LOGIN, string.Format("Subject: {0} NameIDFormat: {1}  Level of authentication: {2}  Session timeout in minutes: {3}", assertion.Subject.Value, assertion.Subject.Format, assuranceLevel, FederationConfig.GetConfig().SessionTimeout));


            foreach (IAction action in Actions.Actions.GetActions())
            {
                Trace.TraceMethodCalled(action.GetType(), "LoginAction()");

                action.LoginAction(this, context, assertion);

                Trace.TraceMethodDone(action.GetType(), "LoginAction()");
            }
        }
Exemplo n.º 22
0
        private void HandleRequest(HttpContext context)
        {
            Trace.TraceMethodCalled(GetType(), "HandleRequest()");

            //Fetch config object
            SAML20FederationConfig config = SAML20FederationConfig.GetConfig();

            LogoutRequest logoutRequest = null;
            IDPEndPoint endpoint = null;
            string message = string.Empty;

            //Build the response object
            var response = new Saml20LogoutResponse();
            response.Issuer = config.ServiceProvider.ID;
            response.StatusCode = Saml20Constants.StatusCodes.Success; // Default success. Is overwritten if something fails.
            
            if(context.Request.RequestType == "GET") // HTTP Redirect binding
            {
                HttpRedirectBindingParser parser = new HttpRedirectBindingParser(context.Request.Url);
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST,
                                      string.Format("Binding: redirect, Signature algorithm: {0}  Signature:  {1}, Message: {2}", parser.SignatureAlgorithm, parser.Signature, parser.Message));

                if (!parser.IsSigned)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                logoutRequest = parser.LogoutRequest;
                endpoint = config.FindEndPoint(logoutRequest.Issuer.Value);

                if (endpoint.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP: " + logoutRequest.Issuer.Value);
                    // Not able to return a response as we do not know the IdP.
                    HandleError(context, "Cannot find metadata for IdP " + logoutRequest.Issuer.Value);
                    return;
                }

                Saml20MetadataDocument metadata = endpoint.metadata;

                if (!parser.VerifySignature(metadata.GetKeys(KeyTypes.signing)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. Invalid signature redirect-binding, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                message = parser.Message;
            }
            else if (context.Request.RequestType == "POST") // HTTP Post binding
            {
                HttpPostBindingParser parser = new HttpPostBindingParser(context);
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST,
                                      "Binding: POST, Message: " + parser.Message);

                if (!parser.IsSigned())
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                logoutRequest = parser.LogoutRequest;
                endpoint = config.FindEndPoint(logoutRequest.Issuer.Value);
                if (endpoint.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP");
                    // Not able to return a response as we do not know the IdP.
                    HandleError(context, "Cannot find metadata for IdP " + logoutRequest.Issuer.Value);
                    return;
                }

                Saml20MetadataDocument metadata = endpoint.metadata;

                // handle a logout-request
                if (!parser.CheckSignature(metadata.GetKeys(KeyTypes.signing)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. Invalid signature post-binding, msg: " + parser.Message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                message = parser.Message;
            }else
            {
                //Error: We don't support HEAD, PUT, CONNECT, TRACE, DELETE and OPTIONS
                // Not able to return a response as we do not understand the request.
                HandleError(context, Resources.UnsupportedRequestTypeFormat(context.Request.RequestType));
            }

            AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, message);
            
            // Check that idp in session and request matches.
            string idpRequest = logoutRequest.Issuer.Value;
            if (!context.Session.IsNewSession)
            {
                object idpSession = context.Session[IDPLoginSessionKey];
            
                if (idpSession != null && idpSession.ToString() != idpRequest)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, Resources.IdPMismatchBetweenRequestAndSessionFormat(idpSession, idpRequest), message);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }
            }
            else
            {
                // All other status codes than Success results in the IdP throwing an error page. Therefore we return default Success even if we do not have a session.
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Session does not exist. Continues the redirect logout procedure with status code success." + idpRequest, message);
            }

            //  Only logout if request is valid and we are working on an existing Session.
            if (Saml20Constants.StatusCodes.Success == response.StatusCode && !context.Session.IsNewSession)
            {
                // Execute all actions that the service provider has configured
                DoLogout(context, true);
            }

            // Update the response object with informations that first is available when request has been parsed.
            IDPEndPointElement destination = DetermineEndpointConfiguration(SAMLBinding.REDIRECT, endpoint.SLOEndpoint, endpoint.metadata.SLOEndpoints());
            response.Destination = destination.Url;
            response.InResponseTo = logoutRequest.ID;

            //Respond using redirect binding
            if(destination.Binding == SAMLBinding.REDIRECT)
            {
                HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder();
                builder.RelayState = context.Request.Params["RelayState"];
                builder.Response = response.GetXml().OuterXml;
                builder.signingKey = FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey;
                string s = destination.Url + "?" + builder.ToQuery();
                context.Response.Redirect(s, true);
                return;
            }

            //Respond using post binding
            if (destination.Binding == SAMLBinding.POST)
            {
                HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination);
                builder.Action = SAMLAction.SAMLResponse;                                
                XmlDocument responseDocument = response.GetXml();
                XmlSignatureUtils.SignDocument(responseDocument, response.ID);
                builder.Response = responseDocument.OuterXml;
                builder.RelayState = context.Request.Params["RelayState"];
                builder.GetPage().ProcessRequest(context);
                return;
            }
        }
Exemplo n.º 23
0
        private void HandleResponse(HttpContext context)
        {
            Trace.TraceMethodCalled(GetType(), "HandleResponse()");


            string message = string.Empty;

            if(context.Request.RequestType == "GET")
            {
                HttpRedirectBindingParser parser = new HttpRedirectBindingParser(context.Request.Url);
                LogoutResponse response = Serialization.DeserializeFromXmlString<LogoutResponse>(parser.Message);

                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Binding: redirect, Signature algorithm: {0}  Signature:  {1}, Message: {2}", parser.SignatureAlgorithm, parser.Signature, parser.Message));

                IDPEndPoint idp = RetrieveIDPConfiguration(response.Issuer.Value);
                
                AuditLogging.IdpId = idp.Id;
                AuditLogging.AssertionId = response.ID;
                
                if (idp.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("No IDP metadata, unknown IDP, response: {0}", parser.Message));
                    HandleError(context, Resources.UnknownIDP);
                    return;
                }

                if (!parser.VerifySignature(idp.metadata.Keys))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Invalid signature in redirect-binding, response: {0}", parser.Message));
                    HandleError(context, Resources.SignatureInvalid);
                    return;
                }

                message = parser.Message;
            }else if(context.Request.RequestType == "POST")
            {
                HttpPostBindingParser parser = new HttpPostBindingParser(context);
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      "Binding: POST, Message: " + parser.Message);


                LogoutResponse response = Serialization.DeserializeFromXmlString<LogoutResponse>(parser.Message);

                IDPEndPoint idp = RetrieveIDPConfiguration(response.Issuer.Value);

                if (idp.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("No IDP metadata, unknown IDP, response: {0}", parser.Message));
                    HandleError(context, Resources.UnknownIDP);
                    return;
                }

                if (!parser.IsSigned())
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Signature not present, response: {0}", parser.Message));
                    HandleError(context, Resources.SignatureNotPresent);
                }

                // signature on final message in logout
                if (!parser.CheckSignature(idp.metadata.Keys))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Invalid signature in post-binding, response: {0}", parser.Message));
                    HandleError(context, Resources.SignatureInvalid);
                }

                message = parser.Message;
            }else
            {
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Unsupported request type format, type: {0}", context.Request.RequestType));
                HandleError(context, Resources.UnsupportedRequestTypeFormat(context.Request.RequestType));
            }

            XmlDocument doc = new XmlDocument();
            doc.PreserveWhitespace = true;
            doc.LoadXml(message);

            XmlElement statElem =
                (XmlElement)doc.GetElementsByTagName(Status.ELEMENT_NAME, Saml20Constants.PROTOCOL)[0];

            Status status = Serialization.DeserializeFromXmlString<Status>(statElem.OuterXml);

            if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
            {
                AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                                      string.Format("Unexpected status code: {0}, msg: {1}", status.StatusCode.Value, message));
                HandleError(context, status);
                return;
            }

            AuditLogging.logEntry(Direction.IN, Operation.LOGOUTRESPONSE,
                     "Assertion validated succesfully");

            //Log the user out locally
            DoLogout(context);
        }
Exemplo n.º 24
0
        private void TransferClient(IDPEndPoint endpoint, HttpContext context)
        {
            Trace.TraceMethodCalled(GetType(), "TransferClient()");
            
            Saml20LogoutRequest request = Saml20LogoutRequest.GetDefault();
            
            AuditLogging.AssertionId = request.ID;
            AuditLogging.IdpId = endpoint.Id;
            
            // Determine which endpoint to use from the configuration file or the endpoint metadata.
            IDPEndPointElement destination =
                DetermineEndpointConfiguration(SAMLBinding.REDIRECT, endpoint.SLOEndpoint, endpoint.metadata.SLOEndpoints());
            
            request.Destination = destination.Url;

            string nameIdFormat = context.Session[IDPNameIdFormat].ToString();
            request.SubjectToLogOut.Format = nameIdFormat;
            
            if (destination.Binding == SAMLBinding.POST)
            {
                HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination);
                request.Destination = destination.Url;
                request.Reason = Saml20Constants.Reasons.User;
                request.SubjectToLogOut.Value = context.Session[IDPNameId].ToString();
                 request.SessionIndex = context.Session[IDPSessionIdKey].ToString();
                XmlDocument requestDocument = request.GetXml();
                XmlSignatureUtils.SignDocument(requestDocument, request.ID);
                builder.Request = requestDocument.OuterXml;

                if(Trace.ShouldTrace(TraceEventType.Information))
                    Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendLogoutRequest, "POST", endpoint.Id, requestDocument.OuterXml));

                AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "Binding: POST");
                builder.GetPage().ProcessRequest(context);
                context.Response.End();
                return;
            }

            if(destination.Binding == SAMLBinding.REDIRECT)
            {
                HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder();
                builder.signingKey = FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey;
                request.Destination = destination.Url;
                request.Reason = Saml20Constants.Reasons.User;
                request.SubjectToLogOut.Value = context.Session[IDPNameId].ToString();
                request.SessionIndex = context.Session[IDPSessionIdKey].ToString();
                builder.Request = request.GetXml().OuterXml;
                
                string redirectUrl = destination.Url + "?" + builder.ToQuery();

                if (Trace.ShouldTrace(TraceEventType.Information))
                    Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendLogoutRequest, "REDIRECT", endpoint.Id, redirectUrl));

                AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "Binding: Redirect");
                context.Response.Redirect(redirectUrl, true);
                return;
            }

            if(destination.Binding == SAMLBinding.ARTIFACT)
            {
                if (Trace.ShouldTrace(TraceEventType.Information))
                    Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendLogoutRequest, "ARTIFACT", endpoint.Id, string.Empty));

                request.Destination = destination.Url;
                request.Reason = Saml20Constants.Reasons.User;
                request.SubjectToLogOut.Value = context.Session[IDPNameId].ToString();
                request.SessionIndex = context.Session[IDPSessionIdKey].ToString();

                HttpArtifactBindingBuilder builder = new HttpArtifactBindingBuilder(context);
                AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "Method: Artifact");
                builder.RedirectFromLogout(destination, request, Guid.NewGuid().ToString("N"));
            }

            HandleError(context, Resources.BindingError);
        }
Exemplo n.º 25
0
        private void HandleSOAP(HttpContext context, Stream inputStream)
        {
            Trace.TraceMethodCalled(GetType(), "HandleSOAP");

            HttpArtifactBindingParser parser = new HttpArtifactBindingParser(inputStream);
            HttpArtifactBindingBuilder builder = new HttpArtifactBindingBuilder(context);
            SAML20FederationConfig config = SAML20FederationConfig.GetConfig();

            IDPEndPoint idp = RetrieveIDPConfiguration(parser.Issuer);
            AuditLogging.IdpId = idp.Id;

            
            if (parser.IsArtifactResolve())
            {
                Trace.TraceData(TraceEventType.Information, Tracing.ArtifactResolveIn);

                if (!parser.CheckSamlMessageSignature(idp.metadata.Keys))
                {
                    HandleError(context, "Invalid Saml message signature");
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, "Signature could not be verified", parser.SamlMessage);
                }
                AuditLogging.AssertionId = parser.ArtifactResolve.ID;
                AuditLogging.logEntry(Direction.IN, Operation.ARTIFACTRESOLVE, "", parser.SamlMessage);
                builder.RespondToArtifactResolve(parser.ArtifactResolve);
            }
            else if (parser.IsArtifactResponse())
            {
                Trace.TraceData(TraceEventType.Information, Tracing.ArtifactResponseIn);

                Status status = parser.ArtifactResponse.Status;
                if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
                {
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, string.Format("Unexpected status code for artifact response: {0}, expected 'Success', msg: {1}", status.StatusCode.Value, parser.SamlMessage));
                    HandleError(context, status);
                    return;
                }

                if (parser.ArtifactResponse.Any.LocalName == LogoutRequest.ELEMENT_NAME)
                {
                    if(Trace.ShouldTrace(TraceEventType.Information))
                        Trace.TraceData(TraceEventType.Information, string.Format(Tracing.LogoutRequest, parser.ArtifactResponse.Any.OuterXml));

                    //Send logoutresponse via artifact
                    Saml20LogoutResponse response = new Saml20LogoutResponse();
                    response.Issuer = config.ServiceProvider.ID;
                    LogoutRequest req = Serialization.DeserializeFromXmlString<LogoutRequest>(parser.ArtifactResponse.Any.OuterXml);
                    response.StatusCode = Saml20Constants.StatusCodes.Success;
                    response.InResponseTo = req.ID;
                    IDPEndPoint endpoint = RetrieveIDPConfiguration(context.Session[IDPLoginSessionKey].ToString());
                    IDPEndPointElement destination =
                        DetermineEndpointConfiguration(SAMLBinding.REDIRECT, endpoint.SLOEndpoint, endpoint.metadata.SLOEndpoints());

                    builder.RedirectFromLogout(destination, response);
                }else if(parser.ArtifactResponse.Any.LocalName == LogoutResponse.ELEMENT_NAME)
                {
                    DoLogout(context);
                }
                else
                {
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, string.Format("Unsupported payload message in ArtifactResponse: {0}, msg: {1}", parser.ArtifactResponse.Any.LocalName, parser.SamlMessage));
                    HandleError(context,
                                string.Format("Unsupported payload message in ArtifactResponse: {0}",
                                              parser.ArtifactResponse.Any.LocalName));
                }
            }
            else if(parser.IsLogoutReqest())
            {
                if (Trace.ShouldTrace(TraceEventType.Information))
                    Trace.TraceData(TraceEventType.Information, string.Format(Tracing.LogoutRequest, parser.SamlMessage.OuterXml));

                LogoutRequest req = parser.LogoutRequest;
                
                //Build the response object
                Saml20LogoutResponse response = new Saml20LogoutResponse();
                response.Issuer = config.ServiceProvider.ID;
                //response.Destination = destination.Url;
                response.StatusCode = Saml20Constants.StatusCodes.Success;
                response.InResponseTo = req.ID;
                XmlDocument doc = response.GetXml();
                XmlSignatureUtils.SignDocument(doc, response.ID);
                if (doc.FirstChild is XmlDeclaration)
                    doc.RemoveChild(doc.FirstChild);
                
                builder.SendResponseMessage(doc.OuterXml);
                
            }
            else
            {
                Status s = parser.GetStatus();
                if (s != null)
                {
                    HandleError(context, s);
                }
                else
                {
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, string.Format("Unsupported SamlMessage element: {0}, msg: {1}", parser.SamlMessageName, parser.SamlMessage));
                    HandleError(context, string.Format("Unsupported SamlMessage element: {0}", parser.SamlMessageName));
                }
            }
        }
 /// <summary>
 /// <see cref="IAction.SoapLogoutAction"/>
 /// </summary>
 public void SoapLogoutAction(AbstractEndpointHandler handler, HttpContext context, string userId)
 {
     AuditLogging.logEntry(Direction.IN, Operation.LOGOUT, "ServiceProvider SOAP logout",
                           "IdP user id: " + userId + " login status: " + Saml20Identity.IsInitialized());
 }
Exemplo n.º 27
0
        private void HandleSOAP(HttpContext context, Stream inputStream)
        {
            Trace.TraceMethodCalled(GetType(), "HandleSOAP");
            HttpArtifactBindingParser  parser  = new HttpArtifactBindingParser(inputStream);
            HttpArtifactBindingBuilder builder = new HttpArtifactBindingBuilder(context);

            if (parser.IsArtifactResolve())
            {
                Trace.TraceData(TraceEventType.Information, Tracing.ArtifactResolveIn);

                IDPEndPoint idp = RetrieveIDPConfiguration(parser.Issuer);
                AuditLogging.IdpId       = idp.Id;
                AuditLogging.AssertionId = parser.ArtifactResolve.ID;
                if (!parser.CheckSamlMessageSignature(idp.metadata.Keys))
                {
                    HandleError(context, "Invalid Saml message signature");
                    AuditLogging.logEntry(Direction.IN, Operation.ARTIFACTRESOLVE, "Could not verify signature", parser.SamlMessage);
                }
                builder.RespondToArtifactResolve(idp, parser.ArtifactResolve);
            }
            else if (parser.IsArtifactResponse())
            {
                Trace.TraceData(TraceEventType.Information, Tracing.ArtifactResponseIn);

                Status status = parser.ArtifactResponse.Status;
                if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
                {
                    HandleError(context, status);
                    AuditLogging.logEntry(Direction.IN, Operation.ARTIFACTRESOLVE, string.Format("Illegal status for ArtifactResponse {0} expected 'Success', msg: {1}", status.StatusCode.Value, parser.SamlMessage));
                    return;
                }
                if (parser.ArtifactResponse.Any.LocalName == Response.ELEMENT_NAME)
                {
                    bool       isEncrypted;
                    XmlElement assertion = GetAssertion(parser.ArtifactResponse.Any, out isEncrypted);
                    if (assertion == null)
                    {
                        HandleError(context, "Missing assertion");
                    }
                    if (isEncrypted)
                    {
                        HandleEncryptedAssertion(context, assertion);
                    }
                    else
                    {
                        HandleAssertion(context, assertion);
                    }
                }
                else
                {
                    AuditLogging.logEntry(Direction.IN, Operation.ARTIFACTRESOLVE, string.Format("Unsupported payload message in ArtifactResponse: {0}, msg: {1}", parser.ArtifactResponse.Any.LocalName, parser.SamlMessage));
                    HandleError(context,
                                string.Format("Unsupported payload message in ArtifactResponse: {0}",
                                              parser.ArtifactResponse.Any.LocalName));
                }
            }
            else
            {
                Status s = parser.GetStatus();
                if (s != null)
                {
                    HandleError(context, s);
                }
                else
                {
                    AuditLogging.logEntry(Direction.IN, Operation.ARTIFACTRESOLVE, string.Format("Unsupported SamlMessage element: {0}, msg: {1}", parser.SamlMessageName, parser.SamlMessage));
                    HandleError(context, string.Format("Unsupported SamlMessage element: {0}", parser.SamlMessageName));
                }
            }
        }
Exemplo n.º 28
0
        private void TransferClient(IDPEndPoint idpEndpoint, Saml20AuthnRequest request, HttpContext context)
        {
            AuditLogging.AssertionId = request.ID;
            AuditLogging.IdpId       = idpEndpoint.Id;

            // Determine which endpoint to use from the configuration file or the endpoint metadata.
            IDPEndPointElement destination =
                DetermineEndpointConfiguration(SAMLBinding.REDIRECT, idpEndpoint.SSOEndpoint, idpEndpoint.metadata.SSOEndpoints());



            request.Destination = destination.Url;

            bool   isPassive;
            string isPassiveAsString = context.Request.Params[IDPIsPassive];

            if (bool.TryParse(isPassiveAsString, out isPassive))
            {
                request.IsPassive = isPassive;
            }

            if (idpEndpoint.IsPassive)
            {
                request.IsPassive = true;
            }

            bool   forceAuthn;
            string forceAuthnAsString = context.Request.Params[IDPForceAuthn];

            if (bool.TryParse(forceAuthnAsString, out forceAuthn))
            {
                request.ForceAuthn = forceAuthn;
            }

            if (idpEndpoint.ForceAuthn)
            {
                request.ForceAuthn = true;
            }

            if (idpEndpoint.SSOEndpoint != null)
            {
                if (!string.IsNullOrEmpty(idpEndpoint.SSOEndpoint.ForceProtocolBinding))
                {
                    request.ProtocolBinding = idpEndpoint.SSOEndpoint.ForceProtocolBinding;
                }
            }

            //Save request message id to session
            SessionStore.CurrentSession[SessionConstants.ExpectedInResponseTo] = request.ID;

            var shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(idpEndpoint.ShaHashingAlgorithm);

            if (destination.Binding == SAMLBinding.REDIRECT)
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAuthnRequest, Saml20Constants.ProtocolBindings.HTTP_Redirect, idpEndpoint.Id));

                HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder();
                builder.signingKey          = _certificate.PrivateKey;
                builder.Request             = request.GetXml().OuterXml;
                builder.ShaHashingAlgorithm = shaHashingAlgorithm;
                string s = request.Destination + "?" + builder.ToQuery();

                AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_REDIRECT, "Redirecting user to IdP for authentication", builder.Request);

                context.Response.Redirect(s, true);
                return;
            }

            if (destination.Binding == SAMLBinding.POST)
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAuthnRequest, Saml20Constants.ProtocolBindings.HTTP_Post, idpEndpoint.Id));

                HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination);
                //Honor the ForceProtocolBinding and only set this if it's not already set
                if (string.IsNullOrEmpty(request.ProtocolBinding))
                {
                    request.ProtocolBinding = Saml20Constants.ProtocolBindings.HTTP_Post;
                }
                XmlDocument req = request.GetXml();
                var         signingCertificate = FederationConfig.GetConfig().SigningCertificate.GetCertificate();
                var         signatureProvider  = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm);
                signatureProvider.SignAssertion(req, request.ID, signingCertificate);
                builder.Request = req.OuterXml;
                AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_POST);

                builder.GetPage().ProcessRequest(context);
                return;
            }

            if (destination.Binding == SAMLBinding.ARTIFACT)
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAuthnRequest, Saml20Constants.ProtocolBindings.HTTP_Artifact, idpEndpoint.Id));

                HttpArtifactBindingBuilder builder = new HttpArtifactBindingBuilder(context);

                //Honor the ForceProtocolBinding and only set this if it's not already set
                if (string.IsNullOrEmpty(request.ProtocolBinding))
                {
                    request.ProtocolBinding = Saml20Constants.ProtocolBindings.HTTP_Artifact;
                }
                AuditLogging.logEntry(Direction.OUT, Operation.AUTHNREQUEST_REDIRECT_ARTIFACT);

                builder.RedirectFromLogin(idpEndpoint, destination, request);
            }

            HandleError(context, Resources.BindingError);
        }
Exemplo n.º 29
0
        /// <summary>
        /// Deserializes an assertion, verifies its signature and logs in the user if the assertion is valid.
        /// </summary>
        private void HandleAssertion(HttpContext context, XmlElement elem)
        {
            Trace.TraceMethodCalled(GetType(), "HandleAssertion");

            string issuer = GetIssuer(elem);

            IDPEndPoint endp = RetrieveIDPConfiguration(issuer);

            AuditLogging.IdpId = endp.Id;

            PreHandleAssertion(context, elem, endp);

            bool quirksMode = false;

            if (endp != null)
            {
                quirksMode = endp.QuirksMode;
            }

            Saml20Assertion assertion = new Saml20Assertion(elem, null, quirksMode);

            if (endp == null || endp.metadata == null)
            {
                AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                      "Unknown login IDP, assertion: " + elem);

                HandleError(context, Resources.UnknownLoginIDP);
                return;
            }

            if (!endp.OmitAssertionSignatureCheck)
            {
                IEnumerable <string> validationFailures;
                if (!assertion.CheckSignature(GetTrustedSigners(endp.metadata.GetKeys(KeyTypes.signing), endp, out validationFailures)))
                {
                    AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                          "Invalid signature, assertion: " + elem);

                    string errorMessage = Resources.SignatureInvalid;

                    validationFailures = validationFailures.ToArray();
                    if (validationFailures.Any())
                    {
                        errorMessage += $"\nVerification of IDP certificate used for signature failed from the following certificate checks:\n{string.Join("\n", validationFailures)}";
                    }

                    HandleError(context, errorMessage);
                    return;
                }
            }

            if (assertion.IsExpired())
            {
                AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                      "Assertion expired, assertion: " + elem.OuterXml);

                HandleError(context, Resources.AssertionExpired);
                return;
            }

            // Only check if assertion has the required assurancelevel if it is present.
            string assuranceLevel        = GetAssuranceLevel(assertion);
            string minimumAssuranceLevel = SAML20FederationConfig.GetConfig().MinimumAssuranceLevel;

            if (assuranceLevel != null)
            {
                // Assurance level is ok if the string matches the configured minimum assurance level. This is in order to support the value "Test". However, normally the value will be an integer
                if (assuranceLevel != minimumAssuranceLevel)
                {
                    // If strings are different it is still ok if the assertion has stronger assurance level than the minimum required.
                    int assuranceLevelAsInt;
                    int minimumAssuranceLevelAsInt;
                    if (!int.TryParse(assuranceLevel, out assuranceLevelAsInt) ||
                        !int.TryParse(minimumAssuranceLevel, out minimumAssuranceLevelAsInt) ||
                        assuranceLevelAsInt < minimumAssuranceLevelAsInt)
                    {
                        string errorMessage = string.Format(Resources.AssuranceLevelTooLow, assuranceLevel,
                                                            minimumAssuranceLevel);
                        AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                              errorMessage + " Assertion: " + elem.OuterXml);

                        HandleError(context,
                                    string.Format(Resources.AssuranceLevelTooLow, assuranceLevel, minimumAssuranceLevel));
                        return;
                    }
                }
            }

            CheckConditions(context, assertion);
            AuditLogging.AssertionId = assertion.Id;
            AuditLogging.logEntry(Direction.IN, Operation.AUTHNREQUEST_POST,
                                  "Assertion validated succesfully");

            DoLogin(context, assertion);
        }
Exemplo n.º 30
0
        /// <summary>
        /// Handle the authentication response from the IDP.
        /// </summary>
        private void HandleResponse(HttpContext context)
        {
            Encoding    defaultEncoding = Encoding.UTF8;
            XmlDocument doc             = GetDecodedSamlResponse(context, defaultEncoding);

            AuditLogging.logEntry(Direction.IN, Operation.LOGIN, "Received SAMLResponse: " + doc.OuterXml);

            try
            {
                XmlAttribute inResponseToAttribute =
                    doc.DocumentElement.Attributes["InResponseTo"];

                if (inResponseToAttribute == null)
                {
                    throw new Saml20Exception("Received a response message that did not contain an InResponseTo attribute");
                }

                string inResponseTo = inResponseToAttribute.Value;

                CheckReplayAttack(context, inResponseTo);

                Status status = GetStatusElement(doc);

                if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
                {
                    if (status.StatusCode.Value == Saml20Constants.StatusCodes.Responder && status.StatusCode.SubStatusCode != null && Saml20Constants.StatusCodes.NoPassive == status.StatusCode.SubStatusCode.Value)
                    {
                        HandleError(context, "IdP responded with statuscode NoPassive. A user cannot be signed in with the IsPassiveFlag set when the user does not have a session with the IdP.");
                    }

                    HandleError(context, status);
                    return;
                }

                // Determine whether the assertion should be decrypted before being validated.

                bool       isEncrypted;
                XmlElement assertion = GetAssertion(doc.DocumentElement, out isEncrypted);
                if (isEncrypted)
                {
                    assertion = GetDecryptedAssertion(assertion).Assertion.DocumentElement;
                }

                // Check if an encoding-override exists for the IdP endpoint in question
                string      issuer   = GetIssuer(assertion);
                IDPEndPoint endpoint = RetrieveIDPConfiguration(issuer);
                if (!string.IsNullOrEmpty(endpoint.ResponseEncoding))
                {
                    Encoding encodingOverride = null;
                    try
                    {
                        encodingOverride = System.Text.Encoding.GetEncoding(endpoint.ResponseEncoding);
                    }
                    catch (ArgumentException ex)
                    {
                        HandleError(context, ex);
                        return;
                    }

                    if (encodingOverride.CodePage != defaultEncoding.CodePage)
                    {
                        XmlDocument doc1 = GetDecodedSamlResponse(context, encodingOverride);
                        assertion = GetAssertion(doc1.DocumentElement, out isEncrypted);
                    }
                }

                HandleAssertion(context, assertion);
                return;
            }
            catch (Exception e)
            {
                HandleError(context, e);
                return;
            }
        }