I have an ASP.net MVC application where I can't get the MVC Views to render as a PDF after the introduction of the ADFS authentication.
Earlier, the application had Forms authentication and PDF rendering using Rotativa (which uses WkhtmltoPDF library) worked like a charm. After the introduction of the ADFS it just won't work.
What I get is a blank PDF with the title: "Sign In" without any elements on the page/PDF itself.
As it's pretty indicative that it tries to connect somewhere I believe the problem lies somewhere in the authentication parameters of the WkhtmltoPDF i.e. I probably have to add some additional parameters in order to support ADFS, but I'm not sure which ones. I've already tried using --username and --password parameters but they didn't help.
The question is: What to do to make it work (again)?
Try using the [AllowAnonymous] attribute on the action that calls the view you turn into PDF
Example:
For the action that calls rotativa you'd have something like this maybe
return new Rotativa.ViewAsPdf("ViewToPdf", model);
and the action called would look like
[AllowAnonymous]
public ActionResult ViewToPdf(ViewModel model)
{
return View(model);
}
I hope you understand my formatting
I wasn't able to fix the problem the way I wanted it to, but for those interested in the solution the next steps describe what I did.
As the page I was trying to render with Rotativa required authentication I added the logic to create an "one-time access token" which redirects the user to the another application that renders the same page but without any ADFS authentication check. In this case you have to modify Rotativa's logic to return UrlAsPdf instead of ActionAsPdf.
The only authorization thing I did was checking the validity of the token. Since the token has a fast expiration time (it is valid only for the next couple of minutes) I don't think the security of the web app was negatively affected since no one can access the version without authentication without the access token.
Related
Background
I have an ASP.net MVC 4 web application with Forms authentication and a custom AuthorizeAttribute controlling access to all controllers minus the login screen. I am adding to some of the controllers, an action that allows the user to download a server generated PDF whose content and layout is being defined in a Razor View.
To carry out the conversion between Html and PDF, im using a trial version of ABCPdf9 and the bulk of the conversion works perfectly with all CSS, Text, static images, etc being displayed as required.
The problem is that I have images in the HTML that must also be rendered into the PDF file, but these images come from a controller which requires authentication.
Since the Html to PDF conversion takes place in ABCPdf using the Gecko engine, the existing user authentication cookies, etc are not available and as such the GET requests to the Image Controller are not authenticated and will not return anything. (This is the problem).
What I've discovered
From the research I have done, I came across the HttpAdditionalHeaders Property of ABCPdf which (from my understanding) is there to allow you to set header cookies, etc that will be sent with the requests made by the Gecko engine when fetching resources.
I have spent a good few hours trying to set the existing cookies from the originating request and pass them through to ABCPdf but this does not appear to work. Nor does creating a new set of authenticated cookies and pass them either.
So from what I gather, this solution is not possible....
My question
Does anyone know if it is possible to modify the Url.Action helper so it will generate and include a one-time authentication key in the url? Then implement some code in my custom AuthorizeAttribute that strip the key parameter and if valid, provide an alternative method of authentication to access the necessary image controller. This way, I can run the ABCPdf conversion process and it will be able to access the normally restricted resources in the image controller.
For example:
<img src="http://somesite.com/Image/Retrieve/1234?key=WFD6312DFV154WHSF3B1SGB69SB" />
The custom AuthorizeAttribute code should then recognise the key parameter passed in the requests query string and then bypass existing authentication processes.
Any help or even suggestions for where to look would be greatly appreciated!
currently i'm working on ASP .NET MVC 4 application. We are using the provided [ValidateAntiForgeryToken] and the corresponding #Html.AntiForgeryToken() to generate the hidden field in our forms which are submitted using POST.
So far the mechanism seems to be working properly because if I don't provided the token as input hidden field to the target Action annotated with [ValidateAntiForgeryToken] an error is raised as expected.
However i found really strange that if i captured several generated token using Firebug or Chrome inspector, copy them into notepad and then go to a different page which also uses the AntiForgeryToken and basically replace the hidden field with any of the previous token generated, an error is not raised. I was expecting to always have a 1:1 relation (Page Hidden Field - ValidationAtServer], since if someone is able to obtain that value, will be able to forge any request to any form in the application which need the AntiForgeryToken
I was under the impression that once a token was generated it should not be possible to reuse the same token over an over, I see this a security flaw in the Framework itself.
If someone can provide more insight will be greatly appreciate it.
AntiForgeryToken is session base, so that each user has the same token but another user will have a different token. This descussion may be usefull for you: AntiForgeryToken changes per request
It's normal behaviour, because it's supposed that antiforgery token isn't compromised. If an atacker was able to compromise token, that means that atacker already has opportunity to compromise any other tokes, that would be generated. E.g. man in middle attacks.
So basically there is no need to gereate Antiforgery token per each request, and it will allow you to use already generated one for Ajax requests on current page.
I am looking for a bit of a point in the right direction...
We have an MVC site, with a variety of virtual directories that all point at the same code, e.g.
https://www.x.com/dir1
https://www.x.com/dir2
The different virtual directories are used partly for business reasons due to the URL 'content' and partly to control how the site is skinned.
The sites are locked down for access using forms authentication, and I am trying to track down a slightly elusive issue.
A user logs into the site using the url 'dir1', authenticates fine, SetAuthCookie is called.
We have code that runs on OnActionExecuting throughout the site - it takes the logged in user and determines which virtual directory they should be accessing (one per user) and if they are in the wrong URL, will redirect them, e.g. (simplified code):
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Authenticated && UserIsNotInCorrectDirectory())
{
filterContext.Result = new RedirectResult("https://www.x.com/dir2");
}
}
The problem I am having is this - if I start a fresh browser (using firefox at the minute, to view the cookies) and do the following:
Log into the site using the 'dir1' url.
I get authenticated fine - I can see the set-cookie http header containing our auth cookie. This response will also redirect me to 'dir2'.
On the subsequent page, when I view the cookies, the auth cookie is not there - this is the problem.
To add to my confusion, if I then bring up the login page again (same browser, session not closed), and try this again, it works. Anybody got a clue?
My bet is that your OnActionExecuting filter is getting in the way of your login form and your session cookie is getting lost when you overwrite the result. In case this code resides in an attribute, I would try removing the attribute from your Login action and see if that works.
I currently have an intranet site that is accessed by external customers. I therefore set this up using Forms Authentication. However the powers that be (my bosses) want all our domain users to not have to enter their username and password to access the site.
I've done a bit or reading and everything seems to point to setting up a WinLogin.aspx page that you alter to use WindowAuthenthication and then redirect from there.
I have a problem with this as I don't like the idea of putting an aspx form in my mvc application.
Can anyone tell me how to achieve mixed authentication using a strictly MVC Controller/Action setup without a second application?
NOTES: running MVC 3 on an IIS 7 box.
Forms Authentication is not related to the URL or physical structure of your files. What matters is that a URL should ultimately map to a physical (or virtual) resource on the server, and be processed, and be returned back to the user.
Thus, somewhere in between for each incoming call (each HTTP request, even those for CSS and JavaScript files), you have to see if the current user has enough permission to access it or not. If no, then you might redirect him to the login page.
If you want, you can have a URL like /user/windowslogin where user is the name of the controller, and windowslogin is the name of your action method. Then you can create a custom authentication attribute (something like [WindowsAuthentication]) on your windowslogin action, and in that attribute (which is an MVC filter in essence), you can see if the current request comes from within your domain, and if so, talk to Active Directory for authentication or stuff like that, and on case of successful authentication, create an authentication cookie using FormsAuthentication class, and the rest of the story.
However, I don't think this would be an easy task. Others might introduce better solutions.
I have a question about the returnUrl querystring parameter that is appended by ASP.Net when attempted to hit a page that requires authentication. In looking at Microsoft NerdDinner Sample's LogOn action (along with every other 'sample authentication code' I see on the 'net), it just has the ReturnUrl parameter declared in the action's signature and uses it directly in a Redirect() call. However, back in the WebForms days and using Membership Controls, we use to use the FormsAuthentication.GetReturnUrl() call. Besides returning the 'default url' if no url was specified in the querystring, it also does a few security checks (Cross App Redirect and 'IsDangerousUrl()'). Are those no longer a concern or are all the sample 'log on' actions I'm seeing all over the 'net just ignoring those issues?
I'm not sure about the samples that you've looked at, but it's entirely possibly to use Forms Authentication as is in MVC and benefit from the checks performed in The FormsAuthenticationModule processing (or using the FormsAuthentication class directly).
IIRC, the default MVC application in Visual Studio includes an adapter around forms authentication (AuthenticationService) which can be easily adapted to use the ReturnUrl querystring.
I imagine the samples in question have simply overlooked XSR attacks.