Skip to content

Commit

Permalink
Update AuthorizationHttpModule.cs
Browse files Browse the repository at this point in the history
Signed-off-by: Joachim Fosse <56757601+joaf123@users.noreply.github.com>
  • Loading branch information
joaf123 authored Aug 21, 2023
1 parent 4dd31c5 commit 6ddd5bf
Showing 1 changed file with 37 additions and 13 deletions.
50 changes: 37 additions & 13 deletions AuthorizationHttpModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using System.Web.UI;

/// <summary>
/// Verify authorization on requests to AJAX WebServices or Pages.
/// Verify authorization on call to WebMethods or Pages with the attribute: &lt;RequiresAuthentication&gt; (VB) | [RequiresAuthentication] (C#).
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class RequiresAuthenticationAttribute : Attribute { }
Expand All @@ -33,7 +33,7 @@ public void Dispose() {
}

/// <summary>
/// Authorize request.
/// A request has hit IIS. This events handles authorization for the given request.
/// </summary>
/// <param name="sender">Sender Parameter</param>
/// <param name="e">EventArgs Parameter</param>
Expand All @@ -43,8 +43,10 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
var request = context.Request;
var requestUrl = context.Request.Url.ToString();

if (context.Handler is Page page) {
//The request is for a Page Class:
if (context.Handler is Page page) {
var pageType = page.GetType();
//Check if the MasterPage requires authentication:
if (!requestUrl.Contains(".axd?")) {
var masterPagePath = GetMasterPagePathFromMarkup(page.AppRelativeVirtualPath);
if (!string.IsNullOrEmpty(masterPagePath)) {
Expand All @@ -58,13 +60,15 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
}
}

//Check if the Page requires authentication:
if (pageType.GetCustomAttribute<RequiresAuthenticationAttribute>() != null) {
if (!request.IsAuthenticated || request.Cookies?[FormsAuthentication.FormsCookieName] == null) {
DenyAccess(context);
return;
}
}

//The request is for a WebMethod inside a Page Class:
if (request.HttpMethod == "POST") {
var methodName = GetWebMethodNameFromRequest(request);
if (!string.IsNullOrEmpty(methodName)) {
Expand All @@ -76,10 +80,10 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
}
}
}
};

} else if (requestUrl.Contains(".asmx/")) {
//Prøvd å hente Type via Handler._privateSomething

//The request is for a WebService Class:
if (!(context.Handler is Page) & requestUrl.Contains(".asmx/")) {
var segments = requestUrl.Split(new[] { ".asmx/" }, StringSplitOptions.RemoveEmptyEntries);
if (segments.Length > 1) {
string methodName = segments[1]; // Extract the part after .asmx/ as the method name
Expand All @@ -91,15 +95,28 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
dynamic _handler = context.CurrentHandler;
dynamic handlerWrapper = context.Handler;

// Retrieve original handler and its metadata
if (handlerWrapper != null) {
// Retrieve original handler and its metadata
var originalHandlerField = handlerWrapper.GetType().GetField("_originalHandler", BindingFlags.NonPublic | BindingFlags.Instance);
var originalHandler = originalHandlerField?.GetValue(handlerWrapper) as dynamic;

if (originalHandler != null) {
//Session Disabled WebMethod is Called:
var webServiceMethodDataField = originalHandler.GetType().GetField("_webServiceMethodData", BindingFlags.NonPublic | BindingFlags.Instance);
var webServiceMethodData = webServiceMethodDataField?.GetValue(originalHandler) as dynamic;

//If the WebService Method has SessionEnabled=True the RestHandlerWithSession is used, instead of RestHandler class.
//RestHandlerWithSession is an empty class that inherits both the base RestHandler class and IRequireSessionState for session accsess
//Because of this we need to get the class type in a different way, through the BaseType.
//Since System.Web.Script.Services.RestHandlerWithSession is an internal class we also need to retive the type like so:
Type _RestHandlerWithSessionType = Type.GetType("System.Web.Script.Services.RestHandlerWithSession, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");

//Session Enabled WebMethod is Called:
if (_RestHandlerWithSessionType == originalHandler.GetType()) {
webServiceMethodDataField = originalHandler.GetType().BaseType.GetField("_webServiceMethodData", BindingFlags.NonPublic | BindingFlags.Instance);
webServiceMethodData = webServiceMethodDataField?.GetValue(originalHandler) as dynamic;
};

if (webServiceMethodData != null) {
var ownerField = webServiceMethodData.GetType().GetField("_owner", BindingFlags.NonPublic | BindingFlags.Instance);
var owner = ownerField?.GetValue(webServiceMethodData) as dynamic;
Expand All @@ -112,25 +129,25 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
var actualTypeField = typeData.GetType().GetField("_actualType", BindingFlags.NonPublic | BindingFlags.Instance);
var actualType = actualTypeField?.GetValue(typeData) as dynamic;

//The WebMethod's Class Type is retrived, we can now check for Custom Attributes:
var attributes = actualType.GetCustomAttributes(typeof(RequiresAuthenticationAttribute), true);
bool requiresAuthentication = attributes.Length > 0;

// Check if authentication is required for the main class
//Check if authentication is required for the main class
if (requiresAuthentication) {
if (!request.IsAuthenticated || request.Cookies?[FormsAuthentication.FormsCookieName] == null) {
DenyAccess(context);
return;
}
}

// Check for authentication attribute on the requested method
//Check if authentication is required for the requested method
if (!requiresAuthentication) {
var methodInfo = actualType.GetMethod(methodName);
if (methodInfo != null) {
var methodAttributes = methodInfo.GetCustomAttributes(typeof(RequiresAuthenticationAttribute), true);
bool methodRequiresAuthentication = methodAttributes.Length > 0;


if (methodRequiresAuthentication) {
if (!request.IsAuthenticated || request.Cookies?[FormsAuthentication.FormsCookieName] == null) {
DenyAccess(context);
Expand All @@ -140,7 +157,6 @@ private void OnPostAuthorizeRequest(object sender, EventArgs e) {
}
}
}

}
}
}
Expand Down Expand Up @@ -175,13 +191,21 @@ private string GetRelativeVirtualPath(string absolutePath) {
}

private string GetMasterPagePathFromMarkup(string virtualPath) {
string currentFolder = Path.GetDirectoryName(HttpContext.Current.Server.MapPath(virtualPath));

string markup = File.ReadAllText(HttpContext.Current.Server.MapPath(virtualPath));
using (StringReader reader = new StringReader(markup)) {
string line;
while ((line = reader.ReadLine()) != null) {
Match match = Regex.Match(line, "MasterPageFile\\s*=\\s*\"(.+?)\"");
if (match.Success) {
return match.Groups[1].Value;
string masterPagePath = match.Groups[1].Value;

if (!VirtualPathUtility.IsAppRelative(masterPagePath)) {
masterPagePath = VirtualPathUtility.Combine(virtualPath, masterPagePath);
}

return masterPagePath;
}
}
}
Expand All @@ -208,4 +232,4 @@ private static string GetWebMethodNameFromRequest(HttpRequest request) {
var slashIndex = pathInfo.IndexOf('/');
return slashIndex >= 0 ? pathInfo.Substring(0, slashIndex) : pathInfo;
}
}
}

0 comments on commit 6ddd5bf

Please sign in to comment.