protected void LinkButtonNewUser_Click(object sender, EventArgs e) { StartRegistrationAttemptResponse response = null; try { using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); StartNewUserRegistrationAttemptRequest request = new StartNewUserRegistrationAttemptRequest() { // In this example, SuccessUri and FailureUri are set to the same value. The response // to each End<X>Attempt() contains enough information to distinguish // between a success result and a failure result. SignUpNewResult.aspx illustrates // how to do this. SuccessUri = ConfigurationManager.AppSettings["SignUpNewResultUri"], FailureUri = ConfigurationManager.AppSettings["SignUpNewResultUri"], CancelAllowed = true, SignOnAfterSuccess = true, // The user will be signed on following a successful registration, so we need to // specify the application session length. SessionLengthMinutes = HttpContext.Current.Session.Timeout, SessionLengthMinutesSpecified = true, }; response = client.StartNewUserRegistrationAttempt(request); } } catch (Exception ex) { LabelMessage.Text = HttpUtility.HtmlEncode(string.Format("Exception of type {0} raised when calling WebSSOService.StartNewUserRegistrationAttempt(). {1}", ex.GetType().FullName, ex.Message)); } if (response != null) { // The registration attempt ID is placed in the session to act as a "marker" that // a registration attempt is in progress. It's used later to avoid a call to // EndNewUserRegistrationAttempt() if no registration attempt is in progress. Session["NewUserRegistrationAttempt"] = response.RegistrationAttemptId; Response.Redirect(response.RedirectUri); } }
public ActionResult SignOut() { // Always end your local session first. This helps prevent any nasty race // conditions which might occur otherwise if, for example, the user clicks // a protected link before the web service call to SSO is complete. Guid ssoSessionId = Guid.Empty; if (SSOSession.HasSession) { ssoSessionId = SSOSession.Current.SSOSessionId; SSOSession.Current.End(); } Session.Abandon(); if (ssoSessionId != Guid.Empty) { try { // SessionRemoveParticipant() removes this application from the SSO session. If there are other // applications which are participants in the same SSO session, the SSO session will remain // open, otherwise it will be ended. // // SessionRemoveParticpant() is not recommended for applications which are configured to // always automatically sign-on the user if an SSO session already exists. using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); SessionRemoveParticipantRequest request = new SessionRemoveParticipantRequest() { SessionId = ssoSessionId }; SessionRemoveParticipantResponse response = client.SessionRemoveParticipant(request); } } catch (Exception ex) { Session["Message"] = string.Format("Exception of type {0} raised when calling WebSSOService.SessionRemoveParticipant(). {1}", ex.GetType().FullName, ex.Message); } } return SignInPageSessionEndedRedirect; }
public ActionResult RegisterExisting() { StartRegistrationAttemptResponse response = null; try { using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); StartExistingUserRegistrationAttemptRequest request = new StartExistingUserRegistrationAttemptRequest() { // In this example, SuccessUri and FailureUri are set to the same value. The response // to each End<X>Attempt() contains enough information to distinguish // between a success result and a failure result. RegisterExistingResult() illustrates // how to do this. SuccessUri = RegisterExistingResultUri, FailureUri = RegisterExistingResultUri, CancelAllowed = true, // The user will be signed on following a successful registration, so we need to // specify the application session length. SessionLengthMinutes = HttpContext.Session.Timeout, SessionLengthMinutesSpecified = true, }; response = client.StartExistingUserRegistrationAttempt(request); } } catch (Exception ex) { Session["Message"] = HttpUtility.HtmlEncode(string.Format("Exception of type {0} raised when calling WebSSOService.StartExistingUserRegistrationAttempt(). {1}", ex.GetType().FullName, ex.Message)); return SignUpPageRedirect; } // The registration attempt ID is placed in the session to act as a "marker" that // a registration attempt is in progress. It's used later to avoid a call to // EndNewUserRegistrationAttempt() if no registration attempt is in progress. Session["ExistingUserRegistrationAttempt"] = response.RegistrationAttemptId; return Redirect(response.RedirectUri); }
protected void LinkButtonManageAuthorisation_Click(object sender, EventArgs e) { StartManageAuthorisationAttemptResponse response = null; try { using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); StartManageAuthorisationAttemptRequest request = new StartManageAuthorisationAttemptRequest() { // In this example, SuccessUri and FailureUri are set to the same value. The response // to each End<X>Attempt() contains enough information to distinguish // between a success result and a failure result. ManageAuthorisationsResult() illustrates // how to do this. SuccessUri = ConfigurationManager.AppSettings["ManageAuthorisationsResultUri"], FailureUri = ConfigurationManager.AppSettings["ManageAuthorisationsResultUri"], CancelAllowed = true }; response = client.StartManageAuthorisationAttempt(request); } } catch (Exception ex) { LabelMessage.Text = HttpUtility.HtmlEncode(string.Format("Exception of type {0} raised when calling WebSSOService.StartManageAuthorisationAttempt(). {1}", ex.GetType().FullName, ex.Message)); } if (response != null) { // The change password attempt ID is placed in the session to act as a "marker" that // a manage authorisations attempt is in progress. It's used later to avoid a call to // EndManageAuthorisationsAttempt() if no authorisation management attempt is in progress. Session["ManageAuthorisationsAttempt"] = response.ManageAuthorisationAttemptId; Response.Redirect(response.RedirectUri); } }
public ActionResult ManageAuthorisations() { StartManageAuthorisationAttemptResponse response; try { using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); StartManageAuthorisationAttemptRequest request = new StartManageAuthorisationAttemptRequest() { // In this example, SuccessUri and FailureUri are set to the same value. The response // to each End<X>Attempt() contains enough information to distinguish // between a success result and a failure result. ManageAuthorisationsResult() illustrates // how to do this. SuccessUri = ManageAuthorisationsResultUri, FailureUri = ManageAuthorisationsResultUri, CancelAllowed = true }; response = client.StartManageAuthorisationAttempt(request); } } catch (Exception ex) { Session["Message"] = HttpUtility.HtmlEncode(string.Format("Exception of type {0} raised when calling WebSSOService.StartManageAuthorisationAttempt(). {1}", ex.GetType().FullName, ex.Message)); return SignInPageRedirect; } // The change password attempt ID is placed in the session to act as a "marker" that // a manage authorisations attempt is in progress. It's used later to avoid a call to // EndManageAuthorisationsAttempt() if no authorisation management attempt is in progress. Session["ManageAuthorisationsAttempt"] = response.ManageAuthorisationAttemptId; return Redirect(response.RedirectUri); }
public ActionResult SignOnInit() { StartSignOnAttemptResponse response = null; using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); StartSignOnAttemptRequest request = new StartSignOnAttemptRequest() { SuccessUri = SignOnSuccessUri, FailureUri = SignOnFailUri, CancelAllowed = true, SessionLengthMinutes = Session.Timeout, SessionLengthMinutesSpecified = true }; try { response = client.StartSignOnAttempt(request); } catch (Exception ex) { Session["Message"] = HttpUtility.HtmlEncode(string.Format("Exception of type {0} raised when calling WebSSOService.StartSignOnAttempt(). {1}", ex.GetType().FullName, ex.Message)); return SignInPageRedirect; } } // The sign-on attempt ID is placed in the session to act as a "marker" that // a sign-on attempt is in progress. It's used later to avoid a call to // EndSignOnAttempt() if no sign-on attempt is in progress. Session["SignOnAttempt"] = response.SignOnAttemptId; return Redirect(response.RedirectUri); }
protected void LinkButtonSignOutAll_Click(object sender, EventArgs e) { // Always end your local session first. This helps prevent any nasty race // conditions which might occur otherwise if, for example, the user clicks // a protected link before the web service call to SSO is complete. Guid ssoSessionId = Guid.Empty; if (SSOSession.HasSession) { ssoSessionId = SSOSession.Current.SSOSessionId; SSOSession.Current.End(); } HttpContext.Current.Session.Abandon(); if (ssoSessionId != Guid.Empty) { try { // SessionSignOff() ends the SSO session for all participants. A Session.Ended notification // is sent out to all participants (including this one). It is recommended that all // SSO-enabled applications offer a way for the user to end their SSO session. using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); SessionSignOffRequest request = new SessionSignOffRequest() { SessionId = ssoSessionId }; SessionSignOffResponse response = client.SessionSignOff(request); } } catch (Exception ex) { Session["Message"] = string.Format("Exception of type {0} raised when calling WebSSOService.SessionSignOff(). {1}", ex.GetType().FullName, ex.Message); } } Response.Redirect("~/SignIn.aspx"); }
protected void Page_Load(object sender, EventArgs e) { try { if (Request.HttpMethod == "POST") { byte[] buffer = new byte[Request.InputStream.Length]; Request.InputStream.Read(buffer, 0, buffer.Length); // Notification data is supplied in Base64 format, to avoid digital signature encoding issues string data = Encoding.UTF8.GetString(Convert.FromBase64String(Encoding.ASCII.GetString(buffer))); // Load the notification data into an XmlDocument XmlDocument notification = new XmlDocument(); notification.LoadXml(data); // Items in the notification XML are in the Sage SSO namespace, so we need to add an // XmlNamespaceManager here. See the schema documentation for Notification for more details on // the notification XML format. XmlNamespaceManager nsmgr = new XmlNamespaceManager(notification.NameTable); nsmgr.AddNamespace("sso", "http://sso.sage.com"); CheckNotificationValidSignature(notification); CheckNotificationNotExpired(notification, nsmgr); CheckNotificationNotReplayed(notification, nsmgr); // This XPath expression will only return an XmlNode if the notification type node contains "Session.Ended" and there // is a parameter with the name "SessionId". XmlNode sessionIdNode = notification.SelectSingleNode("/sso:Notification[sso:Type=\"Session.Ended\"]/sso:Parameters/sso:Parameter[sso:Name=\"SessionId\"]/sso:Value", nsmgr); if (sessionIdNode != null) { // Remove the SSO session from the session map. The next time a page is loaded for that SSO session ID, // the map is checked and, if the session is not found the application session is ended. SSOSessionMap.EndSSOSession(new Guid(sessionIdNode.InnerText)); } // This XPath expression will only return an XmlNode if the notification type node contains "Session.ExpiryDue" and there // is a parameter with the name "SessionId". sessionIdNode = notification.SelectSingleNode("/sso:Notification[sso:Type=\"Session.ExpiryDue\"]/sso:Parameters/sso:Parameter[sso:Name=\"SessionId\"]/sso:Value", nsmgr); if (sessionIdNode != null) { // The session will expire shortly. We need to determine whether we need to // extend the session in Sage SSO and act accordingly. Guid ssoSessionId = new Guid(sessionIdNode.InnerText); if (SSOSessionMap.HasSSOSession(ssoSessionId)) { // This XPath expression returns the Timestamp parameter value in the notification. XmlNode ssoSessionExpiryDueNode = notification.SelectSingleNode("/sso:Notification/sso:Parameters/sso:Parameter[sso:Name=\"Timestamp\"]/sso:Value", nsmgr); // The timestamp, like all Sage SSO timestamps, is in XSD schema format and is UTC. DateTime ssoSessionExpiryDue = XmlConvert.ToDateTime(ssoSessionExpiryDueNode.InnerText, XmlDateTimeSerializationMode.RoundtripKind); DateTime newSSOSessionExpiry = DateTime.MinValue; // If there has been some user activity on this session we'll call Sage SSO to extend the // SSO session to match the application session expiry time based on the last activity // and the application session timeout setting. if (SSOSessionMap.ShouldExtendSSOSession(ssoSessionId, ssoSessionExpiryDue, out newSSOSessionExpiry)) { using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); SessionExtendRequest request = new SessionExtendRequest() { SessionId = ssoSessionId, SessionExpiry = newSSOSessionExpiry, SessionExpirySpecified = true }; try { // Call Sage SSO to extend the SSO session to match our application session SessionExtendResponse response = client.SessionExtend(request); // Extend the SSO session in the session map to synchronise with what Sage SSO // tells us. It's important to observe the session expiry that's returned // because the Sage SSO session may be nearing its hard timeout and we // don't want to extend the application session beyond that. SSOSessionMap.ExtendSSOSession(ssoSessionId, response.SessionExpiry); // The ExpiryDue flag tells us whether this session is in its expiry period. If // ExpiryDue returns true at this point either we haven't extended the session far enough // past the expiry due threshold to cause Sage SSO to unmark the session (perhaps // because there was some activity right at the start of the application session but // nothing since) or the SSO session is approaching its hard timeout. // // If the flag is false then we'll receive another notification before the session expires, // if it's true then we WON'T receive another notification before the session expires and // we must call Sage SSO to extend the session if there's any activity. SSOSessionMap.SetShouldExtendSSOSessionOnUserActivity(ssoSessionId, response.ExpiryDue); } catch (Exception) { // There was a problem extending the session on Sage SSO, or some other local problem // with the SSO session map or application session state. The safest thing to do // at this point is to end the application session. SSOSessionMap.EndSSOSession(ssoSessionId); } } } else { // We're not extending the SSO session right now but we mark the mapped SSO session // as requiring extension on user activity. If the user makes a call into the // application while the session is marked, we call Sage SSO to extend the session and un-mark // the application session. You can see this code in PageBase.cs in the OnLoad() method. // The application will receive another notification when the Sage SSO session is next due to expire. SSOSessionMap.SetShouldExtendSSOSessionOnUserActivity(ssoSessionId, true); } } } } } catch (Exception) { // We catch all exceptions here so we don't return a 500 Internal Server Error to Sage SSO. // In a production system, it would be a good idea to log these. } }
protected void LinkButtonSignIn_Click(object sender, EventArgs e) { StartSignOnAttemptResponse response = null; try { using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); StartSignOnAttemptRequest request = new StartSignOnAttemptRequest() { // SuccessUri is the URI to which you want the user to be redirected after a successful sign-on. SuccessUri = ConfigurationManager.AppSettings["SignInSuccessUri"], // FailureUri is the URI to which you want the user to be redirected after an unsuccessful sign-on. Note // that SuccessUri and FailureUri can be the same if you prefer. The response from the call to EndSignOnAttempt // provides enough information to distinguish between success and failure. FailureUri = ConfigurationManager.AppSettings["SignInFailUri"], // CancelAllowed lets you specify whether or not the cancel button is displayed. If the user cancels the sign-on by // clicking the cancel button, EndSignOnAttempt gives a specific failure code. CancelAllowed = true, // Set SessionLengthMinutes to the length of your application session. SessionLengthMinutes = HttpContext.Current.Session.Timeout, SessionLengthMinutesSpecified = true, // You may pass a small amount of arbitrary state data to StartSignOnAttempt, which will be returned // unmodified to your application when EndSignOnAttempt is called. This is optional and the // facility is provided to support web frameworks which do not automatically establish application // sessions. Most of the WebSSOService APIs support the State parameter. // State = "this is arbitary state", // Optionally set culture for this attempt // Culture = "fr-fr", // Optionally set TemplateName and CaptchaTheme. // TemplateName = "other", // CaptchaTheme = CaptchaTheme.White }; response = client.StartSignOnAttempt(request); } } catch (Exception ex) { LabelMessage.Text = HttpUtility.HtmlEncode(string.Format("Exception of type {0} raised when calling WebSSOService.StartSignOnAttempt(). {1}", ex.GetType().FullName, ex.Message)); } if (response != null) { // The sign-on attempt ID is placed in the session to act as a "marker" that // a sign-on attempt is in progress. It's used later to avoid a call to // EndSignOnAttempt() if no sign-on attempt is in progress. Session["SignOnAttempt"] = response.SignOnAttemptId; Response.Redirect(response.RedirectUri); } }
// Check for the existence of an SSO session, record the activity and extend it by calling SSO, if needed. Refresh // should be called each time a page is loaded (or if any Ajax service is called). Returns true if the SSO // session was successfully refreshed. public static bool Refresh() { bool refreshed = false; if (HasSession) { Guid ssoSessionId = Current.SSOSessionId; if (SSOSessionMap.ShouldExtendSSOSessionOnUserActivity(ssoSessionId)) { // The Sage SSO session associated with this application session has been marked expiry due since // the last time there was activity. Call Sage SSO to extend the session and then clear the // mark so that we don't call SessionExtend again until we receive another Session.ExpiryDue // notification. using (WebSSOServiceSoapClient client = new WebSSOServiceSoapClient("WebSSOServiceSoapClient")) { client.Open(); SessionExtendRequest request = new SessionExtendRequest() { SessionId = ssoSessionId, SessionExpiry = DateTime.UtcNow + TimeSpan.FromMinutes(HttpContext.Current.Session.Timeout), SessionExpirySpecified = true }; try { // Call Sage SSO to extend the session to match our application session. SessionExtendResponse response = client.SessionExtend(request); Current.AuthenticationToken = response.UserAuthenticationToken; // Extend the SSO session in the session map to synchronise with what Sage SSO // tells us. It's important to observe the session expiry that's returned // because the Sage SSO session may be nearing its hard timeout and we // don't want to extend the application session beyond that. SSOSessionMap.ExtendSSOSession(ssoSessionId, response.SessionExpiry); // Unlike when we handle the Session.ExpiryDue notification, we always clear // the expiry due flag here to avoid making continual calls to Sage SSO // if the SSO session is nearing the hard timeout. SSOSessionMap.SetShouldExtendSSOSessionOnUserActivity(ssoSessionId, false); refreshed = true; } catch (Exception) { // There was a problem extending the session on Sage SSO, or some other local problem // with the SSO session map or application session state. The safest thing to do // at this point is to end the application session. Current.End(); } } } else { try { // Record the activity in the SSO session map. SSOSessionMap.RefreshSSOSession(ssoSessionId); refreshed = true; } catch (Exception) { // There was a problem refreshing the SSO session in the SSO session map. The safest thing // to do at this point is to end the application session. Current.End(); } } } return refreshed; }