I'm trying to lock down the CM (master) site. The users are going to have to login in order to view the site.
The config below gets added to sitecore.config. Unfortunately, the implementation below only works fro the homepage (e.g. /).
When an anonymous user goes to /hello-world, they'll see a "white" page that doesn't have any content. It doesn't direct them to the login page.
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<sites>
<site name="website"
set:requireLogin="true"
set:domain="sitecore"
set:loginPage="/sitecore/login"
set:targetHostName="master.website.com"
set:scheme="http" />
</sites>
</sitecore>
</configuration>
Visiting homepage takes me to
login page
But, if i manually enter an interior page URL, i get the following:
white page
To make it work, only 2 settings should be changed for the "website" configuration node - requireLogin and loginPage. So you definitely set it correctly.
I met similar "blank page" issue in the past, it was related to some misconfiguration of the ItemNotFoundUrl setting. It could be your case as well, if the "hello-world" page doesn't exist.
Can you please try this:
<site name="website" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/hello-world" database="master" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize="10MB" registryCacheSize="0" viewStateCacheSize="0" xslCacheSize="5MB" filteredItemsCacheSize="2MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" requireLogin="true" loginPage="/sitecore/login/Default.aspx" />
Highlights:
startItem : set to hello-world page (assuming this is the home item)
database : set to master (depends on your test case(s), you can use web db, as well)
loginPage : redirect to Sitecore login page
requireLogin : enforce login, set to TRUE
After further investigation, and contacting the sitecore community, I found out that there is a bug in sitecore 8 update 5 (mvc). The security check doesn't work properly.
Here is the FIX:
1. Add a pipeline that inherits from SecurityCheck.
public class SecurityCheck : Sitecore.Pipelines.RenderLayout.SecurityCheck
{
private RequestBeginArgs originalArgs;
public virtual void Process(RequestBeginArgs args)
{
originalArgs = args;
Process(new RenderLayoutArgs((System.Web.UI.Page)new Sitecore.Web.UI.HtmlControls.Page(), (Item)null));
}
protected override bool HasAccess()
{
SiteContext site = Context.Site;
if (site != null && site.RequireLogin && (!Context.User.IsAuthenticated && !this.IsLoginPageRequest()))
{
originalArgs.AbortPipeline();
return false;
}
if (site == null || site.DisplayMode == DisplayMode.Normal || (Context.User.IsAuthenticated || !(PreviewManager.GetShellUser() == string.Empty)) || this.IsLoginPageRequest())
return true;
originalArgs.AbortPipeline();
return false;
}
}
2. Add this processor as a first processor in the
<mvc.requestBegin>
<!-- security check for site -->
<processor type="Namespace.SecurityCheck, Assembly"/>
</mvc.requestBegin>
Related
I have a website that runs HTTPS correctly in my local environment. When I upload it to AWS it just times out or redirects forever.
My setup in AWS is an Elastic Beanstalk application, an RDS database running MS SQL, I added a Load Balancer to forward the HTTPS requests, and I have a SSL certificate properly assigned to the Load Balancer. From all I can tell my app is running, in fact, Entity Framework fired off and correctly built my database in my RDS instance. I just can't reach the website through the internet.
I've tried setting the Listeners different ways. If I set them like this, it just redirects forever:
If I set them like this, it just times out:
I have the default HTTP/HTTPS port forwarding code in my Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// Sets all calls to require HTTPS: https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new RequireHttpsAttribute());
});
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Force all HTTP requests to redirect to HTTPS: https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl
var options = new RewriteOptions().AddRedirectToHttps();
app.UseRewriter(options);
...
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto
});
...
}
I've spent days on this and I can't get it to work. I've tried taking all of my HTTPS code out and that doesn't work. I've tried code solutions from blogs like this and this and that doesn't work either. From what I've read, the Load Balancer ends up handling the HTTPS request and then forwards an HTTP request to my app. But I don't know how to properly handle that, still enforce HTTPS, and redirect HTTP to HTTPS.
This seems like it would be something that would just work out of the box without a bunch of setup from me. If it's not, I would think a lot of other people would have run into this problem by now and there'd be info about it on the internet. Am I missing something small? Because I'm totally at my wit's end about it.
If you can answer this, you'll be my new hero.
So I finally got this fixed. First, the Load Balancer has to be set to forward HTTPS 443 to HTTP 80 like this:
Then, ALL the code I've outlined in my question needs to be deleted (or not run in the AWS environment). I forgot to remove the services.Configure<MvcOptions>(options){} lines of code initially and I believe that was what was causing the error.
Then I followed this blog to handle the X-Forwarded-Proto header. I put all the code in one extension file:
public static class RedirectToProxiedHttpsExtensions
{
public static RewriteOptions AddRedirectToProxiedHttps(this RewriteOptions options)
{
options.Rules.Add(new RedirectToProxiedHttpsRule());
return options;
}
}
public class RedirectToProxiedHttpsRule : IRule
{
public virtual void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// #1) Did this request start off as HTTP?
string reqProtocol;
if (request.Headers.ContainsKey("X-Forwarded-Proto"))
{
reqProtocol = request.Headers["X-Forwarded-Proto"][0];
}
else
{
reqProtocol = (request.IsHttps ? "https" : "http");
}
// #2) If so, redirect to HTTPS equivalent
if (reqProtocol != "https")
{
var newUrl = new StringBuilder()
.Append("https://").Append(request.Host)
.Append(request.PathBase).Append(request.Path)
.Append(request.QueryString);
context.HttpContext.Response.Redirect(newUrl.ToString(), true);
}
}
}
Finally, I call this code in Startup.cs:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
var options = new RewriteOptions()
.AddRedirectToProxiedHttps()
.AddRedirect("(.*)/$", "$1"); // remove trailing slash
app.UseRewriter(options);
...
}
After all that it finally worked!
According to this AWS docs you must analyze X-Forwarded-Proto header and response with redirects only when it is http (not https).
Current RedirectToHttpsRule from Microsoft.AspNetCore.Rewrite package does not analyze this. You need to implement your own IRule.
app.UseForwardedHeaders() seems to have issues with AWS Load Balancers unless you clear the known networks and proxies first.
Don't forget to install the Microsoft.AspNetCore.HttpOverrides NuGet package first otherwise it will fail silently.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.UseForwardedHeaders(GetForwardedHeadersOptions());
...
}
private static ForwardedHeadersOptions GetForwardedHeadersOptions()
{
ForwardedHeadersOptions forwardedHeadersOptions = new ForwardedHeadersOptions()
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
};
forwardedHeadersOptions.KnownNetworks.Clear();
forwardedHeadersOptions.KnownProxies.Clear();
return forwardedHeadersOptions;
}
You need to accept the XForwardedProto
In Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedProto;
});
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseForwardedHeaders();
...
}
I was facing same issue.I finally got this fixed by changing web.config file.
Below Exact code Works for me. I follow this link. If URL rewrite module is not install then you will have to install this on your instance otherwise only this web.config file change will works.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="HTTPS rewrite behind AWS ELB rule" enabled="true" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions>
<add input="{HTTP_X_FORWARDED_PROTO}" pattern="^http$" ignoreCase="false" />
</conditions>
<action type="Redirect" url="https://{SERVER_NAME}{URL}" redirectType="Found" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I have local website with subdomains like:
localhost:55307
aaa.localhost:55307
bbb.localhost:55307
It works perfectly except authorization - if I log in in localhost:55307 I'm not logged in aaa.localhost:55307 because my subdomains are treated as separate domain. I looking for solution but I can't find any for Asp Identity (Form authentication in MVC 4 it's useless).
Based on some questions and answers in SO I did:
Edit CookieAuthenticationOptions class in Startup.Auth.cs as below:
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
CookieDomain = ".localhost",
ExpireTimeSpan = new TimeSpan(0,12,0,0,0),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
Get MachineKey from IIS Manager and add to web.config:
<system.web>
<authentication mode="None" />
<machineKey validationKey="61D42DE996486DEA64CEA26C0373C547E0D07108789662C2D2E15210A65C475925055009D962FEB3D5D93E9BEA3E3717187F1BCBF63E386EB198F641E6157044" decryptionKey="06CF7C1C31BDBD4E7056D0F3531BE253E98A658B50974155" validation="SHA1" decryption="Auto"/>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" maxRequestLength="1073741824" />
</system.web>
Now i can login but cookies aren't shared - I still logged in one subdomain.
PS. I now that there is a lot of similar questions in StackOberflow but no one of them is about MVC 5 and ASP Identity and no of them got solutions.
I would like to build a Sitecore pipeline processor that would grab the ID of a media item when it is uploaded and save that ID to an existing custom database that is used by a third-party application.
I have been unable to locate any How-to or examples on how to do this?
I am using Sitecore 8.0 Update 5 and an MVC structure for my code.
You can check in the uiUpload pipeline, but that will not fire for programatically created items, i.e. it will only fire when a user uploads an item via the CMS interface.
Create a new processor class:
public class ExternalSystemProcessor
{
public void Process(UploadArgs args)
{
foreach (Item file in args.UploadedItems.Where(file => file.Paths.IsMediaItem))
{
// Custom code here
SaveToExternalSystem(file.ID);
}
}
}
And then patch the in after the default save processor:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<processors>
<uiUpload>
<processor type="MyProject.Custom.Pipelines.ExternalSystemProcessor, MyProject.Custom" mode="on"
patch:after="*[#type='Sitecore.Pipelines.Upload.Save, Sitecore.Kernel']" />
</uiUpload>
</processors>
</sitecore>
</configuration>
I don't remember any pipeline that would be executed when a new item is uploaded to media library, but you should be able to use item:created event.
Just check if the item from the args (ItemCreatedEventArgs) is media item and execute your code.
public void OnItemCreated(object sender, EventArgs args)
{
var createdArgs = Event.ExtractParameter(args, 0) as ItemCreatedEventArgs;
if (createdArgs != null)
{
if (createdArgs.Item != null)
{
...
}
}
}
Sitecore ItemWebApi Gurus,
Why am I getting a response of "Access to site is not granted" every time I attempt to make a Sitecore ItemWebApi request?
Here are the security settings in my Sitecore.ItemWebApi.config
<site name="website">
<patch:attribute name="itemwebapi.mode">StandardSecurity</patch:attribute>
<patch:attribute name="itemwebapi.access">ReadOnly</patch:attribute>
<patch:attribute name="itemwebapi.allowanonymousaccess">false</patch:attribute>
</site>
</sites>
Here's how I'm setting up my ItemWebApi request (please note that I have used a fake username, password, and GUID for the purpose of stack overflow):
var client = new WebClient();
var n = new NameValueCollection();
n["X-Scitemwebapi-Username"] = "extranet\\Sample_Username";
n["X-Scitemwebapi-Password"] = "SamplePassword";
client.Headers.Add(n);
var result = client.DownloadString(
"http://localhost:11111/-/item/v1/?sc_itemid={11111111-1111-1111-1111-111111111111}&scope=c");
The response I get back from my request is always:
Access to site is not granted
I'm using sitecore 7.1.
Turns out I was using the wrong password for the user. The code above in my question is perfectly valid and will return a json response containing the desired information about a sitecore item.
I'd like to also add that you need to verify that the sitecore user which you are trying to authenticate with has been "enabled" in sitecore. I had added a user for my Item Web Api through a sitecore package and wasn't aware that when you do that, sitecore by default disables the user. You actually have to manually "enable" the user before it is active.
I'm having serious problems with creating a Web service in Visual Studio 2010 (Framework 4).
Anyway, I have to use a Oracle membership provider (I have installed "Oracle Providers for ASP.NET 4 11.2.0.2.0', which modifies the framework's machine.config), but I can not connect to the membership.
My code in web.config is as follows:
<configuration>
<connectionStrings>
<remove name="OraAspNetConString"></remove>
<add name="OraAspNetConString" connectionString="User Id=USUARIO;Password=PASSWORD;Data Source=DATABASENAME;" providerName="Oracle.DataAcces.Client"/>
</connectionStrings>
<system.web>
<membership defaultProvider="OracleMembershipProvider" userIsOnlineTimeWindow="30"/>
<roleManager defaultProvider="OracleRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName=".ASPROLES" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All"/>
<authentication mode="None"/>
<authorization>
<allow users="*"/>
</authorization>
I also added the reference 'System.Web.ApplicationServices' to my project.
To test the connection to the membership of Oracle I have put this code in one of the OperationContract that has my web service:
MembershipUserCollection userC = Membership.GetAllUsers();
sample.StringValue += " - " + userC.Count;
bool resp = Membership.ValidateUser(id, id2);
The obtained MembershipUserCollection always appears without users. UserC.Count always equals zero.
The parameters 'id' and 'id2', username and password respectively, are used to validate (that is a poor use, I know) but always returns false.
Anybody can help me with this?
Thanks a lot.
PD: Authentication mode is 'None', I've tried with 'Forms' and still not working.
Problem solved.
I needed to put the name of the application (applicationName) on the label of the membership and role manager providers (in the file machine.config).
:-)