Using Orchard 1.9 from GitHub, if I attempt to force a page validation exception by navigating to
~/Users/Account/LogOn?ReturnUrl=<script%20src%3Dhttp%3A%2F%2Flocalhost%2Fj%20
the end result is a yellow-screen-of-death rather than the Orchard custom exception message.
What is the recommended Orchard way to handle this? Ideally I would like to show the Orchard error page.
FYI I notice that the GET LogOn action (AccountController) does not have a ValidateInput attribute but the POST action does.
Potential Solution:
I set the customErrors element in the web.config to have the attribute defaultRedirect="Error.html" where Error.html is a new file. This of course does not meet my original goal of displaying the Orchard error page.
This does not seem right as modifying the Orchard core (even though it's just the web.config) does not feel right, especially when thinking ahead to updating the Orchard version by pulling the latest Orchard code from the GitHub repository.
The ReturnUrl property does looks a bit strange, this might cause an exception regarding request validation.
If you are in a controller just return a new HttpUnauthorizedResult if authorization fails.
Related
We work on a product that is a series of components that could be installed on different CMSs and provide different services. We take a CMS agnostic approach and try to use the same code in all the CMSs as much as possible (we try to avoid using CMS API as much as we can).
Some part of the code needs to work with the current URL for some redirections so we use Request.Url.ToString() that is something that has worked fine in other environments but in Kentico instead of returning the current page we always get a reference to CMSPages/PortalTemplate.aspx with a querystring parameter aliasPath that holds the real URL. In addition to that, requesting the Template page using a browser gives you a 404 error.
Example:
Real URL (this works fine on a browser):
(1) https://www.customer.com/Membership/Questionnaire?Id=7207f9f9-7354-df11-88d9-005056837252
Request.Url.ToString() (this gives you a 404 error on a browser):
(2) https://www.customer.com/CMSPages/PortalTemplate.aspx?Id=7207f9f9-7354-df11-88d9-005056837252&aliaspath=/Membership/Questionnaire
I've noticed that the 404 error is thrown explicitly by the template code when invoked directly. Please see below code from Page_Init method of PortalTemplate.aspx.cs:
var resolvedTemplatePage = URLHelper.ResolveUrl(URLHelper.PortalTemplatePage);
if (RequestContext.RawURL.StartsWithCSafe(resolvedTemplatePage, true))
{
// Deny direct access to this page
RequestHelper.Respond404();
}
base.OnInit(e);
So, if I comment the above code out my redirection works fine ((2) resolves to (1)). I know it is not an elegant solution but since I cannot / don't want to use Kentico API is the only workaround I could find.
Note that I know that using Kentico API will solve the issue since I'm sure I will find an API method that will return the actual page. I'm trying to avoid that as much as possible.
Questions: Am I breaking something? Is there a better way of achieving what I trying to accomplish? Can you think on any good reason I shouldn't do what I'm doing (security, usability, etc)?
This is kind of a very broad question so I was not able to find any useful information on Kentico docs.
I'm testing all this on Kentico v8.2.50 which is the version one of my customers currently have.
Thanks in advance.
It's not really recommended to edit the source files of Kentico, as you may start to run into issues with future upgrades and also start to see some unexpected behaviour.
If you want to get the original URL sent to the server before Kentico's routing has done its work, you can use Page.Request.RawUrl. Using your above example, RawUrl would return a value of /Membership/Questionnaire?Id=7207f9f9-7354-df11-88d9-005056837252, whereas Url will return a Uri with a value of https://www.customer.com/CMSPages/PortalTemplate.aspx?Id=7207f9f9-7354-df11-88d9-005056837252&aliaspath=/Membership/Questionnaire (as you stated).
This should avoid needing to use the Kentico API and also avoid having to change a file that pretty much every request goes through when using the portal engine.
If you need to get the full URL to redirect to, you can use something like this:
var redirectUrl = Request.Url.GetLeftPart(UriPartial.Authority) + Request.RawUrl;
We are experiencing some odd behaviour when attempting to POST to the Lost Password action on the Account Controller in Orchard.Users.
The important details
We are not directly using Orchard source code, we are using a compiled re-distributable and building modules that are deployed to the redist host, so direct debugging is a challenge.
We have tried this with the vanilla Orchard 1.8.1 (the version of our redist) so we can all but eliminate any of our module's code.
When POSTing the form we get back a 302 Moved response with the Location Header set to /. This then does end up to root rather than to the Success page or back to the Enter New Details password. The user's password is not successfully changed.
Looking at the Account Controller in source shows that the only result that expressly returns the root is when the the call IUserService.ValidateLostPassword(nonce) fails and the return Redirect("~/"); is called.
Seeing as direct debugging is a little complex, we acquired a copy of the Controller from source and moved the action code and all related service call logic into an Orchard command for testing. This has succeeded in changing a user's password. and returning without error, using the NOnce captured from the reset email.
So we suspect this may be a bug with Orchard itself though more likely to be with our instance and it's configuration seeing as "Cannot change password" is a pretty expansive issue.
Anyone have any advice to offer? Known bugs that may apply?
Update 1:
Thank you Bertrand. We have not tried it with Orchard 1.9 yet but did manage to get a completely clean 1.8 (as this is the version we are currently running out in the wild from with one of our repos. P.S. Are you aware that your GitHub repo braches go 1.4.x, 1.5.x, 1.9.x? No 1.8.x available. Anyway.) and this worked. The short version: we played around with what could be different and we got it down to it works when our theme is off and doesn't when it on.
A little digging showed that our FE guys has overwritten the Lost Password view to match our business look. Here is what I found:
In the default Orchard view the form is started using:
#using (Html.BeginFormAntiForgeryPost()) {
and ends up looking like
<form action="/OrchardLocal/Users/Account/LostPassword?nonce=Vc7ABvKcwfMO0jrRkJFxiBWoJzbdGAqQ7bbEgGySqlyAAKnHPTIkyhzG8nn%2FXJsqKkh6e9sreTnHx223BKFOs17gY%2FDWMggtCZw%2BSfz194Mviua5smhl5d%2FnACXCI%2BrdQaGcJj%2BjvoFE7m2OIiaX8w%3D%3D" method="post">
all fine and dandy. I presume that because the nonce came in as a query param on the get, it is persisted to the post through inference in calling the default Begin Form without any additional settings.
However, our override currently uses:
#using (Html.BeginFormAntiForgeryPost(Url.Action("LostPassword"), FormMethod.Post, new{ #class="form-lost-password"} ) ) {
Here we specify some additional class for the needs of our theme and on the page we get:
<form action="/Users/Account/LostPassword" class="form-lost-password" method="post">
The nonce has disappered (or rather has not been added at all since we are specifying an particular route). So the ready solution is the add the nonce on using the
Action(String, String, Object)
form of Url.Action() to specify it as a route value.
However, the nonce is not passed through as either a member on the Model nor through the ViewBag (like the minimum password length is).
I found this this previous question from the time of Orchard 1.6/1.7 which suggests updating the controller to add the nonce to the Viewbag but we are using a pre-compiled re-dist of Orchard so this is less than ideal for our needs.
I will be other ways of writing that form using what we have available to us without updating the Controller but is there any plan to make the nonce available to this view for use?
I have a MVC5 app that is using layout page to control the header and footer ect. The layout page has some sections that are database driven such as the nav bar. I am not sure of the best practice for where to make these calls is. I can think of 2 ways but neither are perfect
Method 1: Pass in data with the pages view model. Don't like this approach has my homepage controller should only be concerned with homepage content, not the layout. This would have to be repeated for each and every view.
Method 2: Ajax to WebAPI controller. Kinda leaning towards this, although I think this means losing stuff like #URL and #HTML which are being used to create links and render custom content.
EDIT: Though of another method
Method 3: Load info into cache on Start. Since this is not info that changes often after initial setup and this code is displayed on every page, caching would be needed anyways.
You should call a controller method from within the view. On your view:
#Html.Action("MyAction", "MyController")
Make sure this action can find everything it needs without having to have values passed in, and you're set. We do this in several projects via service location and/or dependency injection.
I am having trouble with script link custom actions. I am building a SharePoint app, and I successfully added a site-scope custom action pointing to a script file in the Style Library, as I want this particular script to be injected to all the pages of my SharePoint site.
While it works in certain situations, the script link injection breaks without apparent reason under certain conditions. For example, when I arrive on my root web, the script will be injected. But, if I go to a certain link within this web (for example Home or Site Contents), the file that is supposed to be injected will simply not be fetched from the Style Library and therefore never be injected, resulting in an uncaught ReferenceError when I try to call one of the script's function. The weirdest part is that a page refresh through Ctrl+F5 will fetch the script file without any problem, regardless of the page's ability to originally fetch the script file when first accessed. It will keep the script until it is accessed through a link again.
I've read up on Sharepoint caching, thinking it may be the cause of my problem, but the trouble is that these articles mostly talk about cache-induced errors when updating a file, while I am only trying to access it.
One thing to note is that, due to limitations, I am adding the script link custom action through code. Here's an example of what this kind of call currently looks like in my app:
context.Load(context.Site.UserCustomActions);
context.ExecuteQuery();
customAction.Name = "MyScriptLink";
customAction.Location = "ScriptLink";
customAction.Sequence = 100;
customAction.ScriptSrc = "~SiteCollection/Style Library/MySite/MyScript.js";
customAction.Update();
context.ExecuteQuery();
So, what's going on here ? Why is my script no injected on certain pages ? Why does a refresh on these exact same pages manage to fetch the file without any problem ?
Found it ! Three words: Minimum Download Strategy. Disable it, it messes with you page redirect behavior within a SharePoint site (either through code or through site settings)
Edit: If you still want MDS enabled on your site, there is a solution
We have a legacy JSF application running on jetty. It has pages like /foo/bar/mypage.xhtml with outputLink tags like: <h:outputLink value="?param1=value1">Click</h:outputLink>. These links are being generated without any context, and so when clicked, the browser correctly links to the current page with the specified parameters.
We recently installed Xebia's XForwardedFilter to fix issues with running the app behind a proxy. With it enabled, though, the link is getting generated by jsf with the context (which from my understanding is the correct behavior). Unfortunately, the context doesn't include anything after the last /, so the current page is not included in the link. For the example above, the link becomes /foo/bar/?param1=value1 instead of the desired /foo/bar/mypage.jsf?param1=value1
The workaround is to include the current page for the link value: <h:outputLink value="mypage.jsf?param1=value1">Click</h:outputLink>. The problem is that there are a lot of these links in the application and some of them are in includes which will require passing an additional parameter to indicate the page that should be referenced.
Is there a way to get the outputLink to generate the full context? Alternatively, if we could disable the context generation altogether so that the prior behavior occurs, that would work as well.