MVC site simple question



  • Where do I put a bit of code I want to run on user's first login? (And only the user's first login.)

    Can I do this by implementing a filter? Is there a "CompleteFirstLogin" IFilter, or a way to write one?

    The authentication process is invisible to the MVC app-- all I have in the code is an [Authorize] attribute that uses a custom provider (implemented in another DLL entirely) to do an OAuth authentication redirect thingy.

    What we're doing here is splitting an application used by one company into two (virtual) companies-- both companies are on the same AD, use the same OAuth provider, but need to be distinct otherwise. As part of this implementation, we need to ensure that users who belong to company B are correctly redirected to the company B instance of the application after login.

    The OAuth provider has no way of communicating this ("this" meaning that a redirect is needed) to the application, BTW. However the application can look up in the user database which company the user belongs to and decide to redirect as a result.

    Site is implemented in MVC5.


  • And then the murders began.

    @blakeyrat You can add code to your AuthorizeAttribute to redirect if they should go to the other instance:

            protected override bool AuthorizeCore(HttpContextBase httpContext)
            {
                // Follow standard authorize logic.
                var result = base.AuthorizeCore(httpContext);
    
                // If authorized, check the company.
                if (result && IsOtherInstance())
                {
                    result = false;
                }
    
                return result;
            }
    
            protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
            {
                ActionResult result = null;
                if (IsOtherInstance())
                {
                    result = new RedirectResult("url of other instance");
                }
    
                if (result != null)
                {
                    filterContext.Result = result;
                }
                else
                {
                    base.HandleUnauthorizedRequest(filterContext);
                }
            }
    


  • @unperverted-vixen Ok; but the AuthorizeAttribute is defined in another DLL I don't really want to touch if I don't have to.

    I guess what I could do is subclass it, then call it as the base and do my stuff after it returns?

    The attribute is defined like this:

        [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
        public class ApiCustomAuthorizeAttribute : AuthorizeAttribute
        {
            protected override bool AuthorizeCore(HttpContextBase httpContext)
            {
    

    I should mention that all users of the two companies are in the same AD, and thus will correctly be authorized even if they initially visit the URL for the other company. That quirk is exactly why we want to do this redirect.


  • And then the murders began.

    @blakeyrat said in MVC site simple question:

    I guess what I could do is subclass it, then call it as the base and do my stuff after it returns?

    That seems like a reasonable approach to me.



  • @unperverted-vixen Thanks, makes sense to me too. The attribute being in a different DLL was throwing me but in retrospect, that doesn't really even matter does it.



  • @blakeyrat said in MVC site simple question:

    The attribute being in a different DLL was throwing me but in retrospect, that doesn't really even matter does it.

    As long as it is public, it does not matter.... Obviously if it was internal, then it would ;)



  • How do you debug into an AuthorizeAttribute hosted in another DLL that was included in the project using Nuget? Turns out it's not a simple reference, it's some stupid Nuget hackery putting the DLL there, and I have no idea where or how I can put a breakpoint into it.

    The people who originally wrote this seemed intent to make actually debugging the fucking code as difficult as possible...



  • @blakeyrat said in MVC site simple question:

    How do you debug into an AuthorizeAttribute hosted in another DLL that was included in the project using Nuget? Turns out it's not a simple reference, it's some stupid Nuget hackery putting the DLL there, and I have no idea where or how I can put a breakpoint into it.

    The people who originally wrote this seemed intent to make actually debugging the fucking code as difficult as possible...

    Does your NuGet server implement a symbol server Visual Studio can talk to? [Shameless plug] Here's how you'd do it with ProGet: https://inedo.com/support/documentation/proget/feed-types/nuget/symbol-and-source-server


  • Impossible Mission - B

    @blakeyrat said in MVC site simple question:

    How do you debug into an AuthorizeAttribute hosted in another DLL that was included in the project using Nuget?

    Do you have source and a PDB for the other DLL?

    If not, I'd suggest JetBrains dotPeek. It can run a symbol server on localhost that will generate debug data and decompiled source on demand. It's not perfect, but it works pretty well.



  • @masonwheeler said in MVC site simple question:

    Do you have source and a PDB for the other DLL?

    Yes; I just don't know how to place a breakpoint there. You can't put a breakpoint on the [Authorize] line, and breakpoints placed at the beginning of the controller method only trip after the authorization is finished.


  • Impossible Mission - B

    @blakeyrat Yeah, you can't breakpoint the [Authorize] tag because it isn't an executable line of code; it's technically a description of a constructor call, that can be used to create the attribute when something needs it.

    But somewhere there's an AuthorizeAttribute class that takes care of the authorization. You should be able to find it, if you have source, by clicking on the attribute tag and hitting F12. Then find whatever method on the class handles authorization, and place your breakpoint there.



  • @masonwheeler said in MVC site simple question:

    But somewhere there's an AuthorizeAttribute class that takes care of the authorization. You should be able to find it, if you have source, by clicking on the attribute tag and hitting F12. Then find whatever method on the class handles authorization, and place your breakpoint there.

    I've done that natch, but that doesn't work because of the way the DLL is pulled in as a Nuget reference. (At least I assume that's why it doesn't work.)

    I have all this black box "magic" code. If there's a line of code executing, goddamnedit, show it in the goddamned IDE. Grump.

    EDIT: except now I'm digging into it, this particular controller seems to be using the MVC default [Authorize] and not the override that's present in the DLL... now I'm even more confused, but it at least explains why my breakpoint wasn't hit.

    But how is the OAuth getting done?

    Ugh. I hate having to learn a gigantic complicated scary-action-at-a-distance framework just to put in a tiny feature change...


  • Impossible Mission - B

    @blakeyrat It being a Nuget reference should be 100% irrelevant to how the debugger operates.

    OK, hmm... how to deal with this?

    At some point after the authorizing has been done (just to gather information), break into the debugger. Find the Modules list and look for the DLL containing AuthorizeAttribute. Scroll over and see if it has symbols loaded. If you set a breakpoint on it and it's not firing, that's your most likely culprit. Either that, or the symbols are pointing to a different location than where you have your source code.



  • @masonwheeler Yeah actually see my edit above, digging into this project a bit more it seems to be using the default MVC [Authorize], but now I'm confused as to how it's working at all of course. So I need to keep do more digging.

    The "good" news is I can technically complete this current work item with just a database change and an Entity Framework update (both things I know how to do and nothing's stopping me from doing them), but I'm still stymied on the next steps here.

    Oh well. If all else fails I do have a line to the guy who originally wrote it, but since he's no longer with the company we only have limited hours with him and of course we need to take this knowledge in-house since he didn't write any goddamned documentation anywhere ever, not even in the code.


  • Impossible Mission - B

    @blakeyrat Oy, sounds like a mess and a half. I wish you luck!



  • @masonwheeler Yeah, so the site consists of an index page, and a bunch of "applications". The guy who designed this thought it'd be a good idea to put each "application" and the library they powers them are different solutions, even though I can even slightly imagine why they aren't all projects in a single solution. (Each "application", BTW, literally one project. The library code, to be fair, is about 8 projects, but-- guess what? Solutions can contain folders, so this organization still makes no sense and breaks debugging for no good reason.)

    So the first thing I did it make a "roll-up" solution containing all these projects, and now I'm finding out they still dive into Nuget to grab DLLs instead of just using the normal project references, and it's kind of pissing me off.

    Anyway I also just noticed that each "application" runs independently, so it's not enough to do the redirect on the index page, I have to do the redirect where ever an authorized user enters the site, which is like potentially 20 different places. Sigh.


  • Impossible Mission - B


  • 🚽 Regular

    @blakeyrat said in MVC site simple question:

    @masonwheeler Yeah, so the site consists of an index page, and a bunch of "applications". The guy who designed this thought it'd be a good idea to put each "application" and the library they powers them are different solutions, even though I can even slightly imagine why they aren't all projects in a single solution. (Each "application", BTW, literally one project. The library code, to be fair, is about 8 projects, but-- guess what? Solutions can contain folders, so this organization still makes no sense and breaks debugging for no good reason.)

    So the first thing I did it make a "roll-up" solution containing all these projects, and now I'm finding out they still dive into Nuget to grab DLLs instead of just using the normal project references, and it's kind of pissing me off.

    Anyway I also just noticed that each "application" runs independently, so it's not enough to do the redirect on the index page, I have to do the redirect where ever an authorized user enters the site, which is like potentially 20 different places. Sigh.

    It's so nice to return to the roots of what this site is all about. This kind of anti-pattern is on the same level as Merge Day or the episodes with Gary.


Log in to reply