Products

Solutions

Resources

Partners

Community

About

New Community Website

Ordinarily, you'd be at the right spot, but we've recently launched a brand new community website... For the community, by the community.

Yay... Take Me to the Community!

Services Framework Security - ASP.NET MVC

Return to previous page

  • 4/7/2015
  • 13107 Views

Comments

13107 Views

Services Framework Security - ASP.NET MVC

Last updated 9 years ago

Comments

Common

(Enter the content of this article below)

Advanced

 

Note: this wiki page refers to the initial implementation of the services framework (released in DotNetNuke 6.2.0) that used asp.net MVC. This has now been superceded by a WebAPI implementation in DotNetNuke 7.0.0

BackgroundThe Service frameworks in DotNetNuke has a number of benefits

  • Built in authentication
  • Built in Authorization – including an understanding of DotNetNuke concepts
  • Loads DotNetNuke Context
  • Builds on ASP.NET MVC 2 – and likely will build upon WebAPI in a future release.
  • active module
  • Portal settings
  • DnnAuthorizeAttribute

    MVC is “open” by default – DotNetNuke’s implementation is locked down to “superuser” (host) access and the developer chooses the scope of access (secure by default). If you want to open an area to non-superuser's you'll make use of DnnAuthorizeAttribute.

    This is very similar to the ASP.Net MVC AuthorizeAttribute, but with a couple extra properties and it works with DotNetNuke users. This attribute can be used at class or method level to determine the type of access required. It supports

    • AllowAnonymous
    • RequiresHost
    • StaticRoles - The same as MVC's AuthorizeAttribute.Roles. That name was changed in anticipation of providing a more dynamic form of Role authorization that better fits the dyanmic nature of DotNetNuke roles.

    Verbs

    When developing services, its important to consider the verb used on methods. GET requests are simply requests for resources, so it's very easy to execute these e.g. setting the SRC attribute of an image to the service endpoint. As such GET is only ever used for services that read data -if a GET request makes a change to data then it is likely vulnerable to Cross-site request forgery

    In the DotNetNuke Services Framework (and MVC) the default is GET, so if your service/method changes data you will need to use an alternative verb - typically POST is the correct behaviour except where implementing a full REST architecture where other verbs such as PUT/DELETE may be used. To set the verb, add an attribute like so:

    [AcceptVerbs(HttpVerbs.Post)]

    To ease the amount of typing required, if you are just accepting one verb you can use the shortened syntax:
    [HttpPost]


    Note: whilst it may be temping to use JsonRequestBehavior to control this (e.g.JsonRequestBehavior.DenyGet), it's not advised as using this approach will mean a portion of your method will execute before failing with an exception. When you use AcceptVerbs it will not accept requests without the correct verb so a 404 is returned where the verb for the method/class is wrong.

    Integrate with modules

    In many cases a services developer will add a service that is intended only to work for a particular module. If this is the case then services developers need to add code to their service to state that only certain module(s) can use them. In addition the code that executes the service request will need to add some code to allow DotNetNuke to detect and mark the request as initiating from that module.

    If you need to restrict service requests to certain module(s), the SupportedModules attribute is provided by the services framework e.g.

    [SupportedModules("MyModule")]


    In this case the request is restricted to "MyModule" -this is the module name used in the dnn manifest (and stored in the ModuleName column of DesktopModules). it is a best practice to not "overshare" your service.

    Typically the call to the service request is coming from a jQuery/Ajax request. This needs to use the services framework also, but as client code it can't use attributes so instead uses services framework javascript (this can be seen in js\dnn.servicesframework.js). To use the serviceframework javascript you need to add code to your calling page codebehind (e.g. the view.ascx.cs) to both reference the namespace and call a method to insert the script reference.

    using DotNetNuke.Framework;
    <br /><br />override protected void OnInit(EventArgs e)
    <br />{
    <br />    ServicesFramework.Instance.RequestAjaxScriptSupport();
    <br />}

    To restrict request to a module, you will need to add
    beforeSend: serviceFramework.setModuleHeaders,


    To see this implemented into a jQuery ajax request, see the "Example of a well-secured request" below.

    Note: if your code is intended to run when the page loads, rather than based around some event (such as clicking a button), you need to ensure that the document is reading before executing the call. Please see here for an example

    Anti-forgery token

    To protect against Cross-site request forgery, methods need to implement an anti-forgery token. This generates a hidden form field (anti-forgery token) that is validated when the form is submitted. Similarly to module integration it requires changes both to the service and the request.

    On the service request(s) you will add the ValidateAntiForgeryToken attribute.

            [ValidateAntiForgeryToken]
    <br />        [AcceptVerbs(HttpVerbs.Post)]
    <br />        public ActionResult Create(string subject, string body, string roleIds, string userIds, string fileIds)
    <br />...

    In addition you will need to add code in your view.ascx.cs codebehind to both register the service framework and send the forgery token
    using DotNetNuke.Framework;
    <br /><br />override protected void OnInit(EventArgs e)
    <br />{
    <br />    ServicesFramework.Instance.RequestAjaxScriptSupport();
    <br />    ServicesFramework.Instance.RequestAjaxAntiForgerySupport();
    <br />}

    On the request, you will need to wrap the JSON data sent to the POST request
     data: serviceFramework.getAntiForgeryProperty({ NotificationId: action.NotificationId })

    Request validation

    By default, the ASP.NET MVC framework (and hence the DotNetNuke Services Framework) prevents you from submitting form data that contains potentially malicious content. This feature is called request validation, and is a useful protection against inadvertantly allowing html/script to be passed to your services. However in some cases you may wish to disable this e.g. a service method that supports html as content - if you do not you will receive a "a potentially dangerous request.form value..." exception. To do so, you can disable it at the class or method level via the ValidateInput attribute e.g.

    <br />[ValidateInput(false)]
    <br />[AcceptVerbs(HttpVerbs.Post)]
    <br />       public ActionResult Create(string subject, string body, string roleIds, string userIds, string fileIds)
    <br />...

    Example of a well-secured request

    Example of a request, that is a POST, can only be executed by certain module(s) and also implements an antiforgery token.
     //Actions
    <br />        self.acceptFriend = function () {
    <br />            $.ajax({
    <br />                type: "POST",
    <br />                cache: false,
    <br />                url: baseServicepath + 'AcceptFriend',
    <br />                beforeSend: serviceFramework.setModuleHeaders,
    <br />                data: serviceFramework.getAntiForgeryProperty({ friendId: self.UserId })
    <br />            }).done(function (data) {
    <br />                if (data.Result === "success") {
    <br />                    self.FriendStatus(2);
    <br />                } else {
    <br />                    displayMessage(settings.serverErrorText, "dnnFormWarning");
    <br />                }
    <br />            }).fail(function (xhr, status) {
    <br />                displayMessage(settings.serverErrorWithDescriptionText + status, "dnnFormWarning");
    <br />            });
    <br />        };
    Contents
    No sections defined
    What is Liquid Content?
    Find Out
    What is Liquid Content?
    Find Out
    What is Liquid Content?
    Find Out