7

I'm trying to use this attribute on methods in the web API for a custom module:

[DnnModuleAuthorize(AccessLevel = DotNetNuke.Security.SecurityAccessLevel.Edit)]

but no matter what SecurityAccessLevel I set, I always get a 401 unauthorized response.

I was able to make the code work by adding:

[AllowAnonymous]

on the method, and adding:

if (!ModulePermissionController.CanEditModuleContent(this.ActiveModule))
                return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "You do not have permission to access this content.");

to the beginning of my method, but it seems like this is a workaround that I really shouldn't need because it's exactly what that attribute is there for. I'm running DNN 7.2.1.

Anyone have any idea where I'm going wrong with the attribute?

Chris Searles
  • 2,322
  • 17
  • 32

3 Answers3

8

Turns out it was actually related to the anti-forgery token. I'm using Angular so I'm setting my headers manually in my Angular service rather than using the built-in ServicesFramework setModuleHeaders method and was only setting the TabId and ModuleId. I didn't think the [AllowAnonymous] attribute would override the anti-forgery stuff but it looks like it definitely does (which is good to know).

Full solution for those doing the same:

var baseUrl = sf.getServiceRoot('[yourmodulename]') + '[controller]';
    var config = {
        headers: {
            'ModuleId': sf.getModuleId(),
            'TabId': sf.getTabId(),
            'RequestVerificationToken': sf.getAntiForgeryValue()
        }
    };
Chris Searles
  • 2,322
  • 17
  • 32
  • Yeah, the `AllowAnonymous` attribute is... not so good. It completely ignores the rest the auth pipeline. – bdukes Mar 07 '14 at 18:36
  • 1
    hey chris, how did you get the AntiForgeryValue. I did not think you could get it from JS. did you use a http get to get it? – J King Oct 16 '14 at 19:14
  • 1
    @JKing You have to initialize the Services Framework on the client. Check this out for a good detailed example: http://www.dnnsoftware.com/community-blog/cid/145174/services-framework-with-meat – Chris Searles Oct 20 '14 at 15:23
  • thanks for following up Chris. Exactly what I was looking for and it was the final piece I needed to get my services' security working. – J King Oct 20 '14 at 20:24
2

Do you have the SupportedModules attribute applied to your controller (or action method)? If so, I'd guess there's a mismatch between the name you're passing in there and the real name in DNN (you should be passing in the desktop module name). Try removing that attribute and seeing if it helps.

The same process that sets ActiveModule and the current user (and would thus make your check in the action method work) should be responsible for implementing the DnnModuleAuthorize attribute's check. So, that's definitely perplexing. Maybe that changed, and if you just pass ModuleId but not TabId in the headers, then it sets ActiveModule, but won't authenticate?

Have you looked at the traffic in Fiddler and made sure that the ModuleId and TabId headers are being sent correctly? Does being logged in as a super-user (i.e. host-level user) affect any of the auth checks (if so, perhaps the URL isn't being constructed properly, and DNN is identifying the wrong portal)?

bdukes
  • 152,002
  • 23
  • 148
  • 175
  • Hey Brian. SupportedModules has been applied to the controller (but not DnnSupportedModules, assuming that's just a typo though?), also tried moving it to the method but that didn't help; headers are being passed in and parsed properly and all other functionality related to those ID's works as expected; and being logged in as super-user doesn't have any affect. – Chris Searles Mar 07 '14 at 14:40
  • @ChrisSearles Yeah, that was a typo. Try removing the `SupportedModules` attribute and seeing if it helps (I updated my answer with details/suggestions). – bdukes Mar 07 '14 at 14:52
  • Tried that, no luck. Also just double-checked in Fiddler and headers are definitely being sent properly (both Tab and Module ID's). – Chris Searles Mar 07 '14 at 16:19
  • I am struggling with this as well. Logged in as "host" it works nice. Logging in as a "registered user" or a "subscriber" I get the 401 Unauthorized. – Asle G May 11 '16 at 18:47
  • Found the solution to be that I was missing the [SupportedModules] attribute. Adding [SupportedModules("myModuleNameAsInManifest")] gave different error, which turned out to be an undefined knockout-variable given the "value" ´undefined´ with only varchar(6) allocation in the db, thus returning an truncate error as described here: http://stackoverflow.com/questions/5591473/error-string-or-binary-data-would-be-truncated-when-trying-to-insert – Asle G May 11 '16 at 19:34
0

When you initialize the ServicesFramework, make sure you do it inside a document.ready function.

    var self = {};
    jQuery(document).ready(function ($) {
        self.sf = $.ServicesFramework(<%=ModuleID %>);
    });

More info: www.dnnsoftware.com/forums/threadid/507753/scope/posts/services-framework-problems

EfficionDave
  • 2,736
  • 3
  • 31
  • 38