/// <summary> /// Method to construct the SAML AuthN response using a template, replacing /// certain string placeholders with appropriate values. /// </summary> /// <param name="responseTo"></param> /// <param name="samlArtifactCacheEntry"></param> /// <returns>Artifact Resolution Response XML</returns> String BuildResponse(String responseTo, SamlArtifactCacheEntry samlArtifactCacheEntry, String audienceRestriction) { String recipientGsa = samlArtifactCacheEntry.SamlAssertionConsumerURL; if (!recipientGsa.StartsWith("http")) { recipientGsa = "http://" + Request.Headers["Host"] + recipientGsa; } Common.debug("inside BuildResponse"); String req = Common.AuthNResponseTemplate; req = req.Replace("%REQID", responseTo); DateTime currentTimeStamp = DateTime.Now; req = req.Replace("%INSTANT", Common.FormatInvariantTime(currentTimeStamp.AddMinutes(-1))); req = req.Replace("%NOT_ON_OR_AFTER", Common.FormatInvariantTime(currentTimeStamp.AddSeconds(Common.iTrustDuration))); String idpEntityId; if (Common.IDPEntityId.Length > 0) { idpEntityId = Common.IDPEntityId; } else { Common.debug("IDP Entity ID is not set in config. Using machine name as default"); idpEntityId = SecurityElement.Escape(Server.MachineName.Trim()); } Common.debug("IDP Entity ID used as Issuer is: " + idpEntityId); req = req.Replace("%ISSUER", idpEntityId); req = req.Replace("%MESSAGE_ID", Common.GenerateRandomString()); req = req.Replace("%ASSERTION_ID", Common.GenerateRandomString()); req = req.Replace("%SESSION_INDEX", Common.GenerateRandomString()); req = req.Replace("%STATUS", "Success"); req = req.Replace("%CLASS", "InternetProtocol"); req = req.Replace("%SUBJECT", SecurityElement.Escape(samlArtifactCacheEntry.Subject)); req = req.Replace("%AUTHN_REQUEST_ID", SecurityElement.Escape(samlArtifactCacheEntry.AuthNRequestId)); req = req.Replace("%RECIPIENT", recipientGsa); req = req.Replace("%AUDIENCE_RESTRICTION", audienceRestriction); XmlDocument doc = new XmlDocument(); doc.InnerXml = req; Common.debug("exit BuildResponse"); return(doc.InnerXml); }
/// <summary> /// Method to obtain cached user ID and AuthN request ID from the given artifact /// </summary> /// <param name="artifact"></param> /// <returns>SamlArtifactCacheEntry</returns> SamlArtifactCacheEntry GetSamlArtifactCacheEntry(String artifact) { Common.debug("inside GetSubject"); // User ID is stored in an application variable (e.g. Artifact_someLongString = username@domain) String artifactKey = Common.ARTIFACT + "_" + artifact; // Get the user ID from the application space. If it doesn't exist, // this might be a spoof attempt with an invalid artifact SamlArtifactCacheEntry samlArtifactCacheEntry = (SamlArtifactCacheEntry)Application.Get(artifactKey); //Artifact can be used only once as per SAML standard. if (samlArtifactCacheEntry != null) { Application.Remove(artifactKey); return(samlArtifactCacheEntry); } else { Common.error("Artifact ID not found!"); return(null); } }
private void Page_Load(object sender, System.EventArgs e) { Common.debug("inside ResolveArt::Page_Load"); // Get the artifact and SAML request ID String [] info = ExtractInfo(); if (info == null) { Common.error("Handshake error: Resolve Message is wrong"); return; } // Using the artifact, get the user ID SamlArtifactCacheEntry samlArtifactCacheEntry = GetSamlArtifactCacheEntry(info[0]); if (samlArtifactCacheEntry == null || samlArtifactCacheEntry.Subject == null || samlArtifactCacheEntry.Subject.Trim().Length == 0) { Common.error("Handshake error: valid user identity not found!"); return; } // Construct the SAML response to the GSA String res = BuildResponse(info[1], samlArtifactCacheEntry, info[2]); Common.debug("Authentication response=" + res); Response.Write(res); }
private void Page_Load(object sender, System.EventArgs e) { Common.debug("Login Request is: " + Request.RawUrl); Common.debug("before Login::entering pageload"); // create an IAutn instance IAuthn authn = AAFactory.getAuthn(this); String samlRequest = Request.Params["SAMLRequest"]; if (samlRequest == null || "".Equals(samlRequest)) { Diagnose(); return; } //Decode request and extract the AuthNRequestId AuthNRequest authNRequest = ExtractAuthNRequest(samlRequest); if (authNRequest.Id == null || authNRequest.Id.Equals("")) { Common.error("Couldn't extract AuthN Request Id from SAMLRequest"); throw new Exception("Failed to extract AuthN Request Id from SAML Request"); } Common.debug("Extracted AuthNRequestId is :" + authNRequest.Id); String subject = authn.GetUserIdentity(); // Get the user's identity (silently, if properly configured). if (subject == null || subject.Equals("")) { Common.error("Couldn't get user name, check your system setup"); throw new Exception("Failed to get user name"); } Common.debug("The user is: " + subject); // Generate a random string (artifact) that the GSA // will use later to confirm the user's identity String artifactId = Common.GenerateRandomString(); // Set an application level name/value pair for storing the user ID // and the AuthN request Id with the artifact string. // This is used later when the GSA asks to verify the artifact and obtain the // user ID (in ResolveArt.aspx.cs). SamlArtifactCacheEntry samlArtifactCacheEntry = new SamlArtifactCacheEntry(subject, authNRequest.Id); Application[Common.ARTIFACT + "_" + artifactId] = samlArtifactCacheEntry; // Get the relay state, which is the search URL to which the user // is redirected following authentication and verification String relayState = Request.Params["RelayState"]; // Look up the GSA host name (stored in Web.config) String gsa; // Encode the relay state for building the redirection URL (back to the GSA) relayState = HttpUtility.UrlEncode(relayState); gsa = Common.GSAAssertionConsumer + "?SAMLart=" + artifactId + "&RelayState=" + relayState; if (!gsa.StartsWith("http")) { gsa = "http://" + Request.Headers["Host"] + gsa; } Common.debug("before Login::redirect"); Common.debug(" to: " + gsa); // Redirect back to the GSA, which will theb contact the Artifact verifier service // with the artifact, to ensure its validity and obtain the user's ID Response.Redirect(gsa); }