Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closes #15 #17 #97

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 74 additions & 36 deletions DotNetCasClient/CasAuthentication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
using DotNetCasClient.State;
using DotNetCasClient.Utils;
using DotNetCasClient.Validation;
using DotNetCasClient.Validation.Schema.Cas20;
using DotNetCasClient.Validation.TicketValidator;
using System.Collections.Generic;

namespace DotNetCasClient
{
Expand Down Expand Up @@ -249,20 +247,22 @@ public static void Initialize()

if (!String.IsNullOrEmpty(ticketValidatorName))
{
if (String.Compare(CasClientConfiguration.CAS10_TICKET_VALIDATOR_NAME,ticketValidatorName) == 0)
if (String.Compare(CasClientConfiguration.CAS10_TICKET_VALIDATOR_NAME, ticketValidatorName) == 0)
ticketValidator = new Cas10TicketValidator();
else if (String.Compare(CasClientConfiguration.CAS20_TICKET_VALIDATOR_NAME, ticketValidatorName) == 0)
ticketValidator = new Cas20ServiceTicketValidator();
else if (String.Compare(CasClientConfiguration.CAS30_TICKET_VALIDATOR_NAME, ticketValidatorName) == 0)
ticketValidator = new Cas30ServiceTicketValidator();
else if (String.Compare(CasClientConfiguration.SAML11_TICKET_VALIDATOR_NAME, ticketValidatorName) == 0)
ticketValidator = new Saml11TicketValidator();
ticketValidator = new Saml11TicketValidator();
else
{
// the ticket validator name is not recognized, let's try to get it using Reflection then
Type ticketValidatorType = Type.GetType(ticketValidatorName, false, true);
if (ticketValidatorType != null)
{
if (typeof(ITicketValidator).IsAssignableFrom(ticketValidatorType))
ticketValidator = (ITicketValidator)Activator.CreateInstance(ticketValidatorType);
if (typeof(ITicketValidator).IsAssignableFrom(ticketValidatorType))
ticketValidator = (ITicketValidator)Activator.CreateInstance(ticketValidatorType);
else
LogAndThrowConfigurationException("Ticket validator type is not correct " + ticketValidatorName);
}
Expand Down Expand Up @@ -525,36 +525,75 @@ public static string GetProxyTicketIdFor(string targetServiceUrl)
string proxyTicket = null;
try
{
ServiceResponse serviceResponse = ServiceResponse.ParseResponse(proxyTicketResponse);
if (serviceResponse.IsProxySuccess)
if (String.Compare(CasClientConfiguration.CAS20_TICKET_VALIDATOR_NAME, ticketValidatorName) == 0)
{
ProxySuccess success = (ProxySuccess)serviceResponse.Item;
if (!String.IsNullOrEmpty(success.ProxyTicket))
var serviceResponse = Validation.Schema.Cas20.ServiceResponse.ParseResponse(proxyTicketResponse);
if (serviceResponse.IsProxySuccess)
{
protoLogger.Info(String.Format("Proxy success: {0}", success.ProxyTicket));
var success = (Validation.Schema.Cas20.ProxySuccess)serviceResponse.Item;
if (!String.IsNullOrEmpty(success.ProxyTicket))
{
protoLogger.Info(String.Format("Proxy success: {0}", success.ProxyTicket));
}
proxyTicket = success.ProxyTicket;
}
proxyTicket = success.ProxyTicket;
}
else
{
ProxyFailure failure = (ProxyFailure)serviceResponse.Item;
if (!String.IsNullOrEmpty(failure.Message) && !String.IsNullOrEmpty(failure.Code))
else
{
protoLogger.Info(String.Format("Proxy failure: {0} ({1})", failure.Message, failure.Code));
var failure = (Validation.Schema.Cas20.ProxyFailure)serviceResponse.Item;
if (!String.IsNullOrEmpty(failure.Message) && !String.IsNullOrEmpty(failure.Code))
{
protoLogger.Info(String.Format("Proxy failure: {0} ({1})", failure.Message, failure.Code));
}
else if (!String.IsNullOrEmpty(failure.Message))
{
protoLogger.Info(String.Format("Proxy failure: {0}", failure.Message));
}
else if (!String.IsNullOrEmpty(failure.Code))
{
protoLogger.Info(String.Format("Proxy failure: Code {0}", failure.Code));
}
}
else if (!String.IsNullOrEmpty(failure.Message))
}
else if (String.Compare(CasClientConfiguration.CAS30_TICKET_VALIDATOR_NAME, ticketValidatorName) == 0)
{
var serviceResponse = Validation.Schema.Cas30.ServiceResponse.ParseResponse(proxyTicketResponse);
if (serviceResponse.IsProxySuccess)
{
protoLogger.Info(String.Format("Proxy failure: {0}", failure.Message));
var success = (Validation.Schema.Cas30.ProxySuccess)serviceResponse.Item;
if (!String.IsNullOrEmpty(success.ProxyTicket))
{
protoLogger.Info(String.Format("Proxy success: {0}", success.ProxyTicket));
}
proxyTicket = success.ProxyTicket;
}
else if (!String.IsNullOrEmpty(failure.Code))
else
{
protoLogger.Info(String.Format("Proxy failure: Code {0}", failure.Code));
var failure = (Validation.Schema.Cas30.ProxyFailure)serviceResponse.Item;
if (!String.IsNullOrEmpty(failure.Message) && !String.IsNullOrEmpty(failure.Code))
{
protoLogger.Info(String.Format("Proxy failure: {0} ({1})", failure.Message, failure.Code));
}
else if (!String.IsNullOrEmpty(failure.Message))
{
protoLogger.Info(String.Format("Proxy failure: {0}", failure.Message));
}
else if (!String.IsNullOrEmpty(failure.Code))
{
protoLogger.Info(String.Format("Proxy failure: Code {0}", failure.Code));
}
}
}
}
catch (InvalidOperationException)
{
LogAndThrowOperationException("CAS Server response does not conform to CAS 2.0 schema");
if (String.Compare(CasClientConfiguration.CAS20_TICKET_VALIDATOR_NAME, ticketValidatorName) == 0)
{
LogAndThrowOperationException("CAS Server response does not conform to CAS 2.0 schema");
}
else if (String.Compare(CasClientConfiguration.CAS30_TICKET_VALIDATOR_NAME, ticketValidatorName) == 0)
{
LogAndThrowOperationException("CAS Server response does not conform to CAS 3.0 schema");
}
}
return proxyTicket;
}
Expand Down Expand Up @@ -798,7 +837,7 @@ internal static bool ProcessProxyCallbackRequest()

ProxyTicketManager.InsertProxyGrantingTicketMapping(proxyGrantingTicketIou, proxyGrantingTicket);

// TODO: Consider creating a DotNetCasClient.Validation.Schema.Cas20.ProxySuccess object and serializing it.
// TODO: Consider creating a DotNetCasClient.Validation.Schema.CasXX.ProxySuccess object and serializing it.

response.Write("<?xml version=\"1.0\"?>");
response.Write("<casClient:proxySuccess xmlns:casClient=\"http://www.yale.edu/tp/casClient\" />");
Expand All @@ -809,14 +848,15 @@ internal static bool ProcessProxyCallbackRequest()

/// <summary>
/// Validates a ticket contained in the URL, presumably generated by
/// the CAS server after a successful authentication. The actual ticket
/// the CAS server after a successful authentication. The actual ticket
/// validation is performed by the configured TicketValidator
/// (i.e., CAS 1.0, CAS 2.0, SAML 1.0). If the validation succeeds, the
/// request is authenticated and a FormsAuthenticationCookie and
/// corresponding CasAuthenticationTicket are created for the purpose of
/// authenticating subsequent requests (see ProcessTicketValidation
/// method). If the validation fails, the authentication status remains
/// unchanged (generally the user is and remains anonymous).
/// (i.e., CAS 1.0, CAS 2.0, CAS 3.0, SAML 1.0). If the validation
/// succeeds, the request is authenticated and a
/// FormsAuthenticationCookie and corresponding CasAuthenticationTicket
/// are created for the purpose of authenticating subsequent requests
/// (see ProcessTicketValidation method). If the validation fails, the
/// authentication status remains unchanged (generally the user is and
/// remains anonymous).
/// </summary>
internal static void ProcessTicketValidation()
{
Expand Down Expand Up @@ -1279,7 +1319,7 @@ private static void LogAndThrowOperationException(string message)
#region Properties
/// <summary>
/// Name of ticket validator that validates CAS tickets using a
/// particular protocol. Valid values are Cas10, Cas20, and Saml11.
/// particular protocol.
/// </summary>
public static string TicketValidatorName
{
Expand All @@ -1292,9 +1332,7 @@ public static string TicketValidatorName

/// <summary>
/// An instance of the TicketValidator specified in the
/// TicketValidatorName property. This will either be an instance of
/// a Cas10TicketValidator, Cas20TicketValidator, or
/// Saml11TicketValidator.
/// TicketValidatorName property.
/// </summary>
internal static ITicketValidator TicketValidator
{
Expand Down Expand Up @@ -1629,4 +1667,4 @@ public static string[] BypassCasForHandlers

#endregion
}
}
}
5 changes: 3 additions & 2 deletions DotNetCasClient/Configuration/CasClientConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public class CasClientConfiguration : ConfigurationSection
// Names for the supported ticket validators
public const string CAS10_TICKET_VALIDATOR_NAME = "Cas10";
public const string CAS20_TICKET_VALIDATOR_NAME = "Cas20";
public const string CAS30_TICKET_VALIDATOR_NAME = "Cas30";
public const string SAML11_TICKET_VALIDATOR_NAME = "Saml11";

// Names for the supported Service Ticket state provider
Expand Down Expand Up @@ -127,7 +128,7 @@ public string CasServerUrlPrefix
/// <summary>
/// The ticket validator to use to validate tickets returned by the CAS server.
/// <remarks>
/// Currently supported values: Cas10 / Cas20 / Saml11 or any fully qualified type which extends AbstractCasProtocolTicketValidator
/// Currently supported values: Cas10 / Cas20 / Cas30 / Saml11 or any fully qualified type which extends AbstractCasProtocolTicketValidator
/// </remarks>
/// </summary>
[ConfigurationProperty(TICKET_VALIDATOR_NAME, IsRequired = true)]
Expand Down Expand Up @@ -461,4 +462,4 @@ public string AuthenticationType
}
}

#pragma warning restore 1591
#pragma warning restore 1591
90 changes: 90 additions & 0 deletions DotNetCasClient/Validation/Schema/Cas30/AuthenticationFailure.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Licensed to Apereo under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Apereo licenses this file to you under the Apache License,
* 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
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#pragma warning disable 1591

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Xml.Serialization;

namespace DotNetCasClient.Validation.Schema.Cas30
{
[Serializable]
[DebuggerStepThrough]
[DesignerCategory("code")]
[XmlType(Namespace = "http://www.yale.edu/tp/cas")]
public class AuthenticationFailure
{
internal AuthenticationFailure() { }

[XmlAttribute("code")]
public string Code
{
get;
set;
}

[XmlText]
public string Message
{
get;
set;
}

[XmlIgnore]
public bool IsInvalidRequester
{
get
{
return String.Compare(Code, "INVALID_REQUEST", true, CultureInfo.InvariantCulture) == 0;
}
}

[XmlIgnore]
public bool IsInvalidTicket
{
get
{
return String.Compare(Code, "INVALID_TICKET", true, CultureInfo.InvariantCulture) == 0;
}
}

[XmlIgnore]
public bool IsInvalidService
{
get
{
return String.Compare(Code, "INVALID_SERVICE", true, CultureInfo.InvariantCulture) == 0;
}
}

[XmlIgnore]
public bool IsInternalError
{
get
{
return String.Compare(Code, "INTERNAL_ERROR", true, CultureInfo.InvariantCulture) == 0;
}
}
}
}

#pragma warning restore 1591
Loading