From 7f42c50d9807272b8e503d75e112d5f516a35b05 Mon Sep 17 00:00:00 2001 From: Jason Kanaris Date: Tue, 16 Apr 2019 23:12:02 -0400 Subject: [PATCH 1/5] Closes #9 --- .../Validation/CasSaml11Response.cs | 29 +++++-------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/DotNetCasClient/Validation/CasSaml11Response.cs b/DotNetCasClient/Validation/CasSaml11Response.cs index 5cff83e..a49b216 100644 --- a/DotNetCasClient/Validation/CasSaml11Response.cs +++ b/DotNetCasClient/Validation/CasSaml11Response.cs @@ -6,9 +6,9 @@ * Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a * copy of the License at: - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -36,7 +36,7 @@ class CasSaml11Response // The SAML 1.1 Assertion namespace const string SAML11_ASSERTION_NAMESPACE = "urn:oasis:names:tc:SAML:1.0:assertion"; - private static readonly Logger protoLogger = new Logger(Category.Protocol); + private static readonly Logger protoLogger = new Logger(Category.Protocol); // Tolerance ticks for checking the current time against the SAML // Assertion valid times. @@ -99,7 +99,7 @@ private void ProcessValidAssertion() protoLogger.Debug("Unmarshalling SAML response"); XmlDocument document = new XmlDocument(); document.Load(new StringReader(_CasResponse)); - + XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable); nsmgr.AddNamespace("assertion", SAML11_ASSERTION_NAMESPACE); @@ -112,12 +112,6 @@ private void ProcessValidAssertion() throw new TicketValidationException("No assertions found."); } - XmlReaderSettings xmlReaderSettings = new XmlReaderSettings(); - xmlReaderSettings.ConformanceLevel = ConformanceLevel.Auto; - xmlReaderSettings.IgnoreWhitespace = true; - xmlReaderSettings.IgnoreComments = true; - xmlReaderSettings.CloseInput = true; - foreach (XmlNode assertionNode in assertions) { XmlNode conditionsNode = assertionNode.SelectSingleNode("descendant::assertion:Conditions", nsmgr); @@ -148,23 +142,16 @@ private void ProcessValidAssertion() protoLogger.Debug("No AuthenticationStatement found in SAML response."); throw new TicketValidationException("No AuthenticationStatement found in the CAS response."); } - - string authMethod = SamlUtils.GetAttributeValue(authenticationStmtNode.Attributes, "AuthenticationMethod"); - + XmlNode nameIdentifierNode = assertionNode.SelectSingleNode("child::assertion:AuthenticationStatement/child::assertion:Subject/child::assertion:NameIdentifier", nsmgr); if (nameIdentifierNode == null) { protoLogger.Debug("No NameIdentifier found in SAML response."); throw new TicketValidationException("No NameIdentifier found in AuthenticationStatement of the CAS response."); } - + string subject = nameIdentifierNode.FirstChild.Value; - IList authValues = new List(); - IDictionary> authenticationAttributes = new Dictionary>(); - authValues.Add(authMethod); - authenticationAttributes.Add("samlAuthenticationStatement::authMethod", authValues); - IAssertion casAssertion; XmlNode attributeStmtNode = assertionNode.SelectSingleNode("descendant::assertion:AttributeStatement", nsmgr); @@ -177,9 +164,9 @@ private void ProcessValidAssertion() { casAssertion = new Assertion(subject, notBefore, notOnOrAfter); } - + CasPrincipal = new CasPrincipal(casAssertion, null, null); - + return; } } From e27ef4521897eab61b38ea09ec4cb8bb87b76bc0 Mon Sep 17 00:00:00 2001 From: Blair Allen Date: Wed, 17 Apr 2019 16:21:09 -0400 Subject: [PATCH 2/5] Fixed the IsUserInRole() method per issue 75 --- .../Security/AssertionRoleProvider.cs | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/DotNetCasClient/Security/AssertionRoleProvider.cs b/DotNetCasClient/Security/AssertionRoleProvider.cs index e8978d1..bc5aba0 100644 --- a/DotNetCasClient/Security/AssertionRoleProvider.cs +++ b/DotNetCasClient/Security/AssertionRoleProvider.cs @@ -123,13 +123,36 @@ public override string[] GetUsersInRole(string roleName) throw new NotImplementedException(); } + /// + /// Determines whether or not the specified user is a member of the specified role. + /// + /// The identity of the current user + /// The role to check for membership + /// A Boolean indicating whether or not the user is a member of the role public override bool IsUserInRole(string username, string roleName) { if (CasAuthentication.CurrentPrincipal.Identity.Name != username) { + // Role membership is provided by the CAS server, not this client, so it is + // impossible to determine the role membership for other identities throw new ProviderException("Cannot fetch roles for user other than that of current context."); } - return GetCurrentUserRoles().Count > 0; + + // Get the list of roles the current user has + IList roles = GetCurrentUserRoles(); + + // Determine if any of the current user roles match the specified role name + foreach (string role in roles) + { + if (string.Compare(role, roleName, true) == 0) + { + // Role names match, so the current user is in the specified role + return true; + } + } + + // Current user is not in any roles that match the specified role + return false; } public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) @@ -142,12 +165,12 @@ public override bool RoleExists(string roleName) throw new NotImplementedException(); } - private IList GetCurrentUserRoles() + private IList GetCurrentUserRoles() { - ICasPrincipal principal = CasAuthentication.CurrentPrincipal; + ICasPrincipal principal = CasAuthentication.CurrentPrincipal; if (principal == null) { - return EMPTY_LIST; + return EMPTY_LIST; } IList roles = principal.Assertion.Attributes[roleAttribute]; if (roles == null) From f72506443e0e4a6916202815cd4bc61ebe22258f Mon Sep 17 00:00:00 2001 From: Blair Allen Date: Wed, 17 Apr 2019 16:33:45 -0400 Subject: [PATCH 3/5] Fixed the GetCurrentUserRoles() method per issue 75 --- .../Security/AssertionRoleProvider.cs | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/DotNetCasClient/Security/AssertionRoleProvider.cs b/DotNetCasClient/Security/AssertionRoleProvider.cs index e8978d1..bc24a8f 100644 --- a/DotNetCasClient/Security/AssertionRoleProvider.cs +++ b/DotNetCasClient/Security/AssertionRoleProvider.cs @@ -142,22 +142,44 @@ public override bool RoleExists(string roleName) throw new NotImplementedException(); } - private IList GetCurrentUserRoles() - { - ICasPrincipal principal = CasAuthentication.CurrentPrincipal; - if (principal == null) - { - return EMPTY_LIST; - } - IList roles = principal.Assertion.Attributes[roleAttribute]; - if (roles == null) - { - roles = EMPTY_LIST; - } - return roles; - } - - } + /// + /// Gets all the roles of which the current user is a member. + /// + /// A list of role names + private IList GetCurrentUserRoles() + { + // Attempt to get the identity of the current user + ICasPrincipal principal = CasAuthentication.CurrentPrincipal; + if (principal == null) + { + // No identity is set in the current CAS context, so there cannot be any role + // membership + return EMPTY_LIST; + } + + // Assert the configured role attribute name exists in the list of CAS assertion + // attributes + if (principal.Assertion.Attributes.ContainsKey(roleAttribute)) + { + // Obtain the attribute in the CAS assertion that contains the list of role for the + // current user + IList roles = principal.Assertion.Attributes[roleAttribute]; + if (roles == null) + { + // The current user is not a member of any roles + return EMPTY_LIST; + } + + return roles; + } + else + { + // The CAS assertion does not contain the attribute configured for role membership, + // so assume the user is not a member of any roles + return EMPTY_LIST; + } + } + } } #pragma warning restore 1591 \ No newline at end of file From 09de0ecf1439bee033d4609bb64881ea585a5b69 Mon Sep 17 00:00:00 2001 From: Blair Allen Date: Wed, 17 Apr 2019 17:02:53 -0400 Subject: [PATCH 4/5] Fixed the GetAllRoles() and GetRolesForUser() methods per issue 75 --- .../Security/AssertionRoleProvider.cs | 76 +++++++++++-------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/DotNetCasClient/Security/AssertionRoleProvider.cs b/DotNetCasClient/Security/AssertionRoleProvider.cs index e8978d1..6f3b27e 100644 --- a/DotNetCasClient/Security/AssertionRoleProvider.cs +++ b/DotNetCasClient/Security/AssertionRoleProvider.cs @@ -89,36 +89,52 @@ public override string[] FindUsersInRole(string roleName, string usernameToMatch throw new NotImplementedException(); } - /// - /// Get all the roles we know about from the current user's CAS assertion. - /// This operation is synonymous with . - /// - /// List of all roles belonging to current user. - public override string[] GetAllRoles() - { - IList roles = GetCurrentUserRoles(); - if (roles is Array) - { - return (string[])roles; - } - string[] roleArray = new string[roles.Count]; - for (int i = 0; i < roles.Count; i++) - { - roleArray[i] = roles[i]; - } - return roleArray; - } - - public override string[] GetRolesForUser(string username) - { - if (CasAuthentication.CurrentPrincipal.Identity.Name != username) - { - throw new ProviderException("Cannot fetch roles for user other than that of current context."); - } - return GetAllRoles(); - } - - public override string[] GetUsersInRole(string roleName) + /// + /// Gets a list of all the roles for the configured applicationName. + /// + /// A string array containing the names of all the roles stored in the data + /// source for the configured applicationName. + /// This method will always throw a as the + /// CAS client is not able to retrieve a list of all roles from the CAS server. + public override string[] GetAllRoles() + { + throw new NotImplementedException(); + } + + /// + /// Gets a list of role names of which the specified user is a member. + /// + /// The user to get roles for + /// A string array containing the names of all the roles + public override string[] GetRolesForUser(string username) + { + if (CasAuthentication.CurrentPrincipal.Identity.Name != username) + { + // Role membership is provided by the CAS server, not this client, so it is + // impossible to determine the role membership for other identities + throw new ProviderException("Cannot fetch roles for user other than that of current context."); + } + + // Call the private method to get all roles for the specified (current) user + IList roles = GetCurrentUserRoles(); + + if (roles is Array) + { + // The roles list can be directly cast to a string array and returned to the caller + return (string[])roles; + } + + // The elements of the roles list must be manually copied into a new string array + // that can be returned to the caller + string[] roleArray = new string[roles.Count]; + for (int i = 0; i < roles.Count; i++) + { + roleArray[i] = roles[i]; + } + return roleArray; + } + + public override string[] GetUsersInRole(string roleName) { throw new NotImplementedException(); } From 64595a4317e92da2578e4bcd3e73081c401cdf2e Mon Sep 17 00:00:00 2001 From: Jason Kanaris Date: Thu, 18 Apr 2019 23:51:27 -0400 Subject: [PATCH 5/5] Update AssertionRoleProvider.cs --- DotNetCasClient/Security/AssertionRoleProvider.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DotNetCasClient/Security/AssertionRoleProvider.cs b/DotNetCasClient/Security/AssertionRoleProvider.cs index bc5aba0..23b5432 100644 --- a/DotNetCasClient/Security/AssertionRoleProvider.cs +++ b/DotNetCasClient/Security/AssertionRoleProvider.cs @@ -165,12 +165,12 @@ public override bool RoleExists(string roleName) throw new NotImplementedException(); } - private IList GetCurrentUserRoles() + private IList GetCurrentUserRoles() { - ICasPrincipal principal = CasAuthentication.CurrentPrincipal; + ICasPrincipal principal = CasAuthentication.CurrentPrincipal; if (principal == null) { - return EMPTY_LIST; + return EMPTY_LIST; } IList roles = principal.Assertion.Attributes[roleAttribute]; if (roles == null) @@ -183,4 +183,4 @@ private IList GetCurrentUserRoles() } } -#pragma warning restore 1591 \ No newline at end of file +#pragma warning restore 1591