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()"); } }
/// <summary> /// Handles a request. /// </summary> /// <param name="context">The context.</param> protected override void Handle(HttpContext context) { Trace.TraceMethodCalled(GetType(), "Handle()"); try { //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); })) { HandleSOAP(context, context.Request.InputStream); return; } if (!string.IsNullOrEmpty(context.Request.Params["SAMLart"])) { HandleArtifact(context); return; } if (!string.IsNullOrEmpty(context.Request.Params["SAMLResponse"])) { HandleResponse(context); } else if (!string.IsNullOrEmpty(context.Request.Params["SAMLRequest"])) { HandleRequest(context); } else { IDPEndPoint idpEndpoint = null; Saml20AssertionLite saml20AssertionLite = Saml20PrincipalCache.GetSaml20AssertionLite(); if (saml20AssertionLite != null) { idpEndpoint = RetrieveIDPConfiguration(saml20AssertionLite.Issuer); } if (idpEndpoint == null) { context.User = null; FormsAuthentication.SignOut(); HandleError(context, Resources.UnknownLoginIDP); } TransferClient(idpEndpoint, context); } } catch (Exception e) { //ThreadAbortException is thrown by response.Redirect so don't worry about it if (e is ThreadAbortException) { throw; } HandleError(context, e.Message); } }
/// <summary> /// This method converts the received Saml assertion into a .Net principal. /// </summary> internal static IPrincipal InitSaml20Identity(Saml20AssertionLite assertion) { string subjectIdentifier = assertion.Subject.Value; // Create identity var identity = new Saml20Identity(subjectIdentifier, assertion.Attributes); return(new GenericPrincipal(identity, new string[] { })); }
/// <summary> /// This method converts the received Saml assertion into a .Net principal. /// </summary> internal static IPrincipal InitSaml20Identity(Saml20AssertionLite assertion) { // Find IDPEndPoint IDPEndPoint point = SAML20FederationConfig.GetConfig().FindEndPoint(assertion.Issuer); bool isPersistentPseudonym = assertion.Subject.Format == Saml20Constants.NameIdentifierFormats.Persistent; // Protocol-level support for persistent pseudonyms: If a mapper has been configured, use it here before constructing the principal. string subjectIdentifier = assertion.Subject.Value; if (isPersistentPseudonym && point.PersistentPseudonym != null) { subjectIdentifier = point.PersistentPseudonym.GetMapper().MapIdentity(assertion.Subject); } // Create identity var identity = new Saml20Identity(subjectIdentifier, assertion.Attributes, isPersistentPseudonym ? assertion.Subject.Value : null); return(new GenericPrincipal(identity, new string[] { })); }
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; Saml20AssertionLite saml20AssertionLite = Saml20PrincipalCache.GetSaml20AssertionLite(); IDPEndPoint endpoint = RetrieveIDPConfiguration(saml20AssertionLite.Issuer); 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)); } Saml20LogoutResponse response = new Saml20LogoutResponse(); if (!parser.IsSigned()) { AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present in SOAP logout request, msg: " + parser.SamlMessage.OuterXml); response.StatusCode = Saml20Constants.StatusCodes.RequestDenied; } if (idp.metadata == null) { AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP: " + parser.Issuer); // Not able to process the request as we do not know the IdP. response.StatusCode = Saml20Constants.StatusCodes.NoAvailableIDP; } else { Saml20MetadataDocument metadata = idp.metadata; if (!parser.CheckSignature(metadata.GetKeys(KeyTypes.signing))) { AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. Invalid signature SOAP logout, msg: " + parser.SamlMessage.OuterXml); response.StatusCode = Saml20Constants.StatusCodes.RequestDenied; } } if (parser.GetNameID() != null && !string.IsNullOrEmpty(parser.GetNameID().Value)) { DoSoapLogout(context, parser.GetNameID().Value); } else { AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. No user ID was supplied in SOAP logout request, msg: " + parser.SamlMessage.OuterXml); response.StatusCode = Saml20Constants.StatusCodes.NoAuthnContext; } LogoutRequest req = parser.LogoutRequest; //Build the response object response.Issuer = config.ServiceProvider.ID; 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)); } } }
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 = "(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()"); } }
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()"); } }