Developer forum

Forum » Development » Custom authorization

Custom authorization

Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Hi guys,

I am trying to protect a page using some custom code. We have a third party that submits a custom header. When the header is missing or invalid, I like to set a 401. I have something like this:

[Subscribe(Standard.Application.AfterBeginRequest)]
public class BlockAccess : NotificationSubscriber
{
  public override void OnNotify(string notification, NotificationArgs args)
  {
    if (MyCustomLogic())
    {
      HttpContext.Current.Response.StatusCode = 401;
      HttpContext.Current.Response.StatusDescription = "Unauthorized";
      HttpContext.Current.Response.End();
    }
  }
}

This works well and correctly blocks the access. However, in order to see which page to run this on, I need to access the Request.QueryString["ID"]:

    int currentPageId = Convert.ToInt32(HttpContext.Current.Request.QueryString["ID"]);

That's available for Default.aspx?ID=123 but not for a friendly URL. I guess AfterBeginRequest kicks in before URLs are resolved. I looked at HttpContext.Current.Request but none of its properties contain a reference to the ID.

If I choose a later notification, like DeviceDetected, the same code returns a 200 OK with HTML saying "Response status code does not indicate success: 401 (Unauthorized)".

Is there a notification between these two that let me set the status code and have access to the page ID?

Thanks!

Imar


Replies

 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Bump. Any ideas?

 
Morten Bengtson Dynamicweb Employee
Morten Bengtson
Reply
This post has been marked as an answer

Hi Imar,

Here are some options you can try...

Option 1) Check for a matching page id

[Subscribe(Standard.Application.BeforePreRequestHandlerExecute)]
public class BlockAccess : NotificationSubscriber
{
    public override void OnNotify(string notification, NotificationArgs args)
    {
        var currentPageId = Context.Current.Request.GetInt32("ID");
 
        // TODO: Add your own logic to determine if the page is protected
        var isCurrentPageProtected = (currentPageId == 1);
 
        if (isCurrentPageProtected)
        {
            // TODO: Add your own authentication / authorization logic
            var isAuthorized = false;
 
            if (!isAuthorized)
            {
                Context.Current.Response.StatusCode = 401;
                Context.Current.Response.StatusDescription = "Unauthorized";
                Context.Current.Response.End();
            }
        }
    }
}

Option 2) Check for a matching page path

[Subscribe(Standard.Application.AuthenticateRequest)]
public class BlockAccess : NotificationSubscriber
{
    public override void OnNotify(string notification, NotificationArgs args)
    {
        var protectedPageId = 1; // TODO: Get the id from a database query, config or somewhere else, e.g. SystemConfiguration.Instance.GetInt32("/GlobalSettings/Custom/ProtectedPageId");
        var protectedPagePath = SearchEngineFriendlyURLs.GetFriendlyUrl(protectedPageId); 
        var isCurrentRequestPathProtected = string.Equals(protectedPagePath, Context.Current.Request.Path);
 
        if (isCurrentRequestPathProtected)
        {
            // If you don't want Dynamicweb to handle this as a normal page request then mark the request as handled.
            var authenticateRequestArgs = args as Standard.Application.AuthenticateRequestArgs;
            authenticateRequestArgs.Handled = true;
 
            // TODO: Add your own authentication / authorization logic
            var isAuthorized = false; 
 
            if (!isAuthorized)
            {
                Context.Current.Response.StatusCode = 401;
                Context.Current.Response.StatusDescription = "Unauthorized";
                Context.Current.Response.End();
            }
        }
    }
}

Best regards,
Morten

Votes for this answer: 1
 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Wonderful! Thanks for the detailed response, Morten. I'll give that a try. We did implement a similar approach to your second solution but it felt a bit fragile because of potential name changes. Sounds like BeforePreRequestHandlerExecute is the way to go.

Imar

 

You must be logged in to post in the forum