apereo / dotnet-cas-client

Apereo .NET CAS Client

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How can I call the CAS login directly?

alexhaberer opened this issue · comments

I have an app that also has an API that serves images. As the images are used in other locations access is anonymous. Within the application though I have some admin pages that a user would need to be logged into see.

How can I call the CAS authentication process directly?

Thanks,

@alexhaberer ASP.NET already has a framework for handling the scenario you are describing. In other words, you shouldn't have to initiate the CAS authentication process manually. In your web.config file you can set your default authorization rules using the system.web/authorization section and corresponding allow and deny rules. Then, for specific areas or pages of your application, you can use location sections to change those authorization rules. My personal recommendation is that you set the default rules to whatever is most common in your application, and then use the location sections to override as necessary. Since adding a location section for each exception is tedious, this is why I recommend setting the most common authorization scenario as your default rules. The following resource seems to have a good explanation of the authorization mechanism I am describing: Authorization and Protecting Web Resources in ASP.NET

As an example, if your images directory is the only area of your application where anonymous access is allowed, then I would set your default rule to deny unauthenticated users.

<system.web>
    <authorization>
        <deny users="?" />
    </authorization>
</system.web>

Then add a location section to allow all users (authenticated or not) for the /images directory

<location path="/images">
    <system.web>
        <authorization>
            <allow users="*" />
        </authorization>
    </system.web>
</location>

If most of your application allows anonymous and you just have a few admin pages that need to be authenticated, then you would flip the above rules. Take note of how you have to re-enumerate the hierarchy of config sections when you define each location section, hence why it can become tedious.

NOTE: In my experience the path attribute of the location section is pretty particular about slashes, and off the top of my head I couldn't remember if a directory needs a leading or trailing slash. So if you find it doesn't work as expected, try different combinations or search the web for the exact requirements. Hope this helps, and please let us know if this resolves your issue!

Can't be sure, in IIS I've set Allow Anonymous Enabled, and within my Controllers I have [Authorize] attributes of different kinds.

Depending on the image type you may be able to view it and some not. Essentially everyone needs access to /Assets/Images/{user}/

Then I have the image types which limits access.

So when an application (External) requests images there is a check that pulls users/app details and allows/stops the image return.

Is there a way to just call the process to go through Auth? When a user hits a page?

I've tried [AllowAnonymous] but that doesn't seem to work as I get directed to the CAS login.

@alexhaberer Before I further try to diagnose your situation, can you further explain how your users/apps are consuming the images? For example, are you embedding them elsewhere using <img> tags? Or are they for download only? How they are being consumed will have a significant impact on whether you will be able to accomplish what you want. In general, static resources like images typically are either left open to the world (anonymous) or for authenticated users only (with no specific authorization).

The images are on the same server within the project, I'm using routes.MapRoute to catch the URL. Then above the controller functions have multiple [Authorize] attributes which then get user information and determine if the file should be served or denied.

I had this working with a direct saml2 ADFS connector, but for setup, CAS was much quicker in .Net as well our CAS environment directs the user to ADFS, so we are converting it to CAS.

Overall everything is working, but when a user attempts to access an admin page, I need to redirect them to the CAS login so I can them get their information to then validate their AD groups for authorization.

ROUTE:
// Redirect for requests to Blackboard image files.
routes.MapRoute(
name: "SecureImage",
url: "Assets/Images/{user}/Blackboard.jpg",
defaults: new { controller = "Serve", action = "serveSecureImage" }
);

CONTROLLER:
[Route("Assets/Images/{user}/Blackboard.jpg")]
[AuthController.AdminAuth]
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public ActionResult serveSecureImage() {

    Logic to get image info and return.

    }

AUTH:
public class AdminAuthAttribute : AuthorizeAttribute {

    Logic to get session info from CAS.

    }

Within the Auth I previously had CAS info as it was obtained on Session_OnStart, but as the images needed API access without Auth I had to enable anonymous access. With that, CAS login is never hit now. So when I want to access an admin page I need to kick off the CAS login process.

Thanks,

Ahh, I finally understand what you are trying to do. Thanks for the explanation. You do not need to call anything in DotNetCasClient directly to kick off the authentication (that was the part that was confusing me). I see that you are wanting to create custom logic within your override of AuthorizeAttribute. What you need to do here is simply implement your authorization logic based on the already known state of authentication for the user. So when your AuthController.AdminAuth attribute is executed, you will know the user is either not authenticated, or they are authenticated (and if so, who the user is).

See the following StackOverflow question/answer for a good start for how you would do this: Overriding AuthorizeAttribute in MVC 4

Each state has its own method that is executed. If the user is not authenticated, you can redirect them to your CAS login URL. If they are already authenticated, you can either allow access to the resource or deny them access. The core concept at this point is that DotNetCasClient has already executed in the pipeline at this point, so there is nothing to call (except for perhaps the helper methods to generate the full URL to your CAS server's login endpoint.

So that is the issue, my applicaiton hasn't authenticated the user. Thus i need to redirect them or call a CasAuthentication login method.

I have started searching and can complete a CasAuthentication.REdirectToLoginPage(); which directs me to the CAS url, but after signing in I'm directed to the NotAuthorized.aspx and not the page I was originally requesting.

Any ideas?

I'm already overriding the authorize functionality, buy stating if a user isn't authenticated send them to a not authorized page.

But at this point I need to get them to login. Which with my above comment I can direct them to the login, but post login I get the NotAuthorized.aspx and not the page I was requesting.

Thanks,

By changing my IIS setting to Anonymous the CAS url login is never requested. This allows my images to be severed without logging in. Thus outside applications can use my API to pull images for users. When I change this and require a login, the API call then requires a login to view the images. In applications where the images are being used it just then give a broken link as the image requires authentication/authorization before serving the image.

That is why I need a way to authenticate the user once they have logged into the main application where some admin features exist, so I can authenticate whom is logged in and where they are trying to access.

Thanks,

So is there some documentation on how I could go about starting the CAS login process manually when a request is made to a page where a certain access is needed?

Like I said earlier I was able to redirect to the Login page using CasAuthentication.RedirectToLoginPage(); but after logging in I didn't get directed to the original request page or anything, it directed me to the NotAuthorized.aspx I'm assuming I may need to re-initialize it or set the redirect after login using a method prior to the redirect to login?

Thanks,

I was able to kick off the CAS auth later upon page request.

        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
            if (filterContext.HttpContext.Request.IsAuthenticated == false) {
                CasAuthentication.RedirectToLoginPage(true);
            }

            if (filterContext.HttpContext.Request.IsAuthenticated == true) {
                filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary {
                    { "action", "Index" },
                    { "controller", "Auth" }
                });
            }
        }

I used the HandleUnauthorizedRequest override to call the CAS login page redirect (true). The within the AuthorizeAttribute class I completed some logic to get everything setup.

So essentially now my public images are accessible via API routing and secured images require a redirect/login to view/pull.