<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fredrik Haglund's blog &#187; Security</title>
	<atom:link href="http://blog.fredrikhaglund.se/blog/tag/security/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.fredrikhaglund.se</link>
	<description>Chatter about EPiServer, ASP.NET, CSS and Web Development.</description>
	<lastBuildDate>Tue, 28 Jun 2011 13:37:32 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>EPiServer &#8211; Security and Access Control (1/2)</title>
		<link>http://blog.fredrikhaglund.se/blog/2010/03/08/episerver-security-and-access-control-12/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2010/03/08/episerver-security-and-access-control-12/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 07:15:00 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[EPiServer CMS]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2010/03/08/episerver-security-and-access-control-12/</guid>
		<description><![CDATA[EPiServer CMS is using the standard methods in ASP.NET to handle authentication and authorization. On top of this they have added a few providers to handle authentication and access control to EPiServer assets like pages and files uploaded by editors. Make sure that you read up on how the authentication, location and authorization-tags works in [...]]]></description>
			<content:encoded><![CDATA[<p>EPiServer CMS is using the standard methods in ASP.NET to handle authentication and authorization. On top of this they have added a few providers to handle authentication and access control to EPiServer assets like pages and files uploaded by editors.</p>
<p><strong>Make sure that you read up on how the authentication, location and authorization-tags works in <em>web.config</em> before you try to understand security in EPiServer CMS.</strong></p>
<h3>Check list for ASP.NET security</h3>
<ul>
<li><strong>MachineKey</strong> – Always add a machinekey-tag to your <em>web.config</em>-file. Use this <a href="http://www.orcsweb.com/articles/aspnetmachinekey.aspx" target="_blank">online tool to generate the MachineKey</a>. </li>
<li><strong>Authentication</strong> – I almost always use ASP.NET Forms authentication because it gives you the most flexibility. This is all you need and I always set timeout high to get the “Remember Me”-checkbox to work as expected. Sometimes I also use the <em>defaultUrl</em>-attribute to control what happens after login.
<pre><code>&lt;authentication mode=&quot;Forms&quot;&gt;
  &lt;forms loginUrl=&quot;Util/login.aspx&quot; defaultUrl=&quot;/&quot;
    timeout=&quot;<strong>129600</strong>&quot; /&gt;
&lt;/authentication&gt;</code></pre>
</li>
<li><strong>Membership</strong> and <strong>RoleProvider</strong> – Configures how a username and password is validated and how to retrieve what groups a user is a member of. </li>
<li><strong>Authorization</strong> – EPiServer uses authorization tags together with location tags to control access to physical folders like the EPiServer user interface. </li>
</ul>
<h3>Select Security PROVIDERS</h3>
<p>Select the right providers for your site:</p>
<ul>
<li><strong>SqlMembershipProvider</strong> and <strong>SqlRoleProvider</strong> from Microsoft stores username, password and group membership in a SQL database. EPiServer is preconfigured with the needed tables so you can just start using them by changing <em>defaultProvider</em>-attribute.</li>
<li><strong>WindowsMembershipProvider</strong> and <strong>WindowsRoleProvider</strong> from EPiServer enabled forms login but with windows credentials. This is the default provider for a new installation. A big limitation if an editor needs to work with Access Control is that Window Users and Groups are only synchronized when a user log on. So it is not possible to add rights to a user before it has logged in at least one time and the security admin tool shows cached data for who is a member of a group.</li>
<li><strong>ActiveDirectoryMembershipProvider</strong> from Microsoft and <strong>ActiveDirectoryRoleProvider</strong> from EPiServer. Tries to workaround the problem with cached Users and Groups by talking directly to the Active Directory. I have personally have had a lot of issues with exceptions from the Active Directory providers and trouble to get it to work in a DMZ. They are also sensitive to interruptions if the LDAP server is not available. I recommend to use WindowsMembershipProvider if possible since it also uses the local machine as a cache.</li>
<li><strong>MultiplexingMembershipProvider</strong> and <strong>MultiplexingRoleProvider</strong> from EPiServer forwards the requests to a list of providers and this enables you to combine both SQL and Windows accounts.</li>
</ul>
<h3>TIPS – IF you Can not login with your Windows Account</h3>
<p>EPiServer <strong>WindowsMembershipProvider</strong> does not work if you try to login with a domain account but do your machine does not have a working connection to your Domain Controler. </p>
<p>Workaround by creating a local account that is a member of the local administrators group.</p>
<h3>Tips – Use a local group to optimize and handle Groups in groups </h3>
<p>EPiServer <strong>WindowsRoleProvider</strong> uses queries that only retrieve a list of groups you are a member of directly. It does not discover if you indirectly are a member of group through another group.</p>
<p>This is quite annoying and and AD-admin get something sad in their eyes if you suggest that you should not use groups in groups.</p>
<p>Workaround this by creating a local group on the web server and add the AD group that is using groups in groups. <strong>WindowsRoleProvider</strong> will see that you are a direct member of the local group. </p>
<p>This technique can also be useful if a lot of different AD-groups should have the same access in EPiServer. The reason is that EPiServer stores one row in a table for each access control entry for each EPiServer page and directory in VPP. </p>
<p>It could simplify your web.config if you do not have to maintain a long list group names for edit and admin mode access. (EPiServer 6 has a new feature that takes care of this.)</p>
<h3>Break in to an EPiServer site </h3>
<p>Forgot the password? Only got ftp-access? Do not worry, as long as you have the right to change web.config you can always break in!</p>
<p>You need to comment out all “&lt;deny users=&quot;*&quot; /&gt;” in web.config and then it is possible to access edit and admin mode without authentication.</p>
<p>I suggest that you reset your password or create a new account in admin mode and turn on security as fast as possible!</p>
<p>Notice that you must login to be able to edit pages.</p>
<h3>Access Rights for pages and uploaded files</h3>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2010/02/image.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://blog.fredrikhaglund.se/wp-content/uploads/2010/02/image_thumb.png" width="244" height="145" /></a> EPiServer has the following Access Rights that can be set per page. You can also set access right for files in the File Manager. </p>
<ul>
<li><strong>Read</strong> – Let’s you see the page or download the file.</li>
<li><strong>Create</strong> – Allows you to create child pages that will inherit the same ACL as the parent, upload new files or create directories.</li>
<li><strong>Change</strong> – Allows you to save a new version of a page and mark it ready to publish. You can also check in a new version of an existing files.</li>
<li><strong>Delete</strong> – Allows you to move a page to the wastebasket or delete it permanently. You can delete files and directories.</li>
<li><strong>Publish</strong> – Allows you to change and publish pages. Not applicable on files.</li>
<li><strong>Administer</strong> – Allows you to change the ACL for this page or directory as an editor and change dynamic properties on this page (and indirectly all children)</li>
</ul>
<p>Users with access to admin mode can always change access control lists and do not need Administer right.</p>
<p><a href="http://blog.fredrikhaglund.se/wp-content/uploads/2010/02/image1.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://blog.fredrikhaglund.se/wp-content/uploads/2010/02/image_thumb1.png" width="240" height="190" /></a>Notice that you can only set Access Rights per directory and not on individual files.</p>
<p>Page Files are special. Each page can have its own page folder and files uploaded to this directory have the same availability as the page. So if the page is not publish – no one can access the files in the page folder except editors. Very convenient since scheduled publishing also affects the files! </p>
</p>
<p>The same happens when the page is moved to the waste basket. No one can access the files in the page folder than editors. This is a common cause for broken images and links to document when editors copy and paste pages. If you delete the original page, no one can access the images its page folder!</p>
<h3>Tips for Access Right configuration</h3>
<p>If you follow these guidelines it will be much easier to administer access.</p>
<ul>
<li>Avoid giving users access rights directly. Always add roles (groups) and make users members of these instead.</li>
<li>Never give WebEditors group any access rights (except on small sites where you are not going to use Access Rights at all). This roles is intended as a master switch if you have access to edit mode or not.</li>
<li>Give the virtual role “Creator” the right to change and delete pages if you setup a site with writers and an editors-in-chief that publish pages. It will save a lot of maintenance work when writers makes mistakes. </li>
<li>Using role names with both location and role will simplify when you administer who is a member of what, i.e. pressrelease_writer, pressrelease_publisher, startpage_editor, article_writer, blog_admin</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2010/03/08/episerver-security-and-access-control-12/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Work with Unpublished PageData from code</title>
		<link>http://blog.fredrikhaglund.se/blog/2009/02/18/work-with-unpublished-pagedata-from-code/</link>
		<comments>http://blog.fredrikhaglund.se/blog/2009/02/18/work-with-unpublished-pagedata-from-code/#comments</comments>
		<pubDate>Wed, 18 Feb 2009 18:01:20 +0000</pubDate>
		<dc:creator>Fredrik Haglund</dc:creator>
				<category><![CDATA[EPiServer]]></category>
		<category><![CDATA[AccessLevel]]></category>
		<category><![CDATA[DataFactory]]></category>
		<category><![CDATA[EPiServer CMS]]></category>
		<category><![CDATA[GetChildren]]></category>
		<category><![CDATA[ILanguageSelector]]></category>
		<category><![CDATA[IsMasterLanguageBranch]]></category>
		<category><![CDATA[LanguageSelector]]></category>
		<category><![CDATA[PageVersion]]></category>
		<category><![CDATA[SaveAction]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[VersionStatus]]></category>

		<guid isPermaLink="false">http://blog.fredrikhaglund.se/blog/2009/02/18/work-with-unpublished-pagedata-from-code/</guid>
		<description><![CDATA[Mari Jørgensen wrote about Breaking change in GetChildren() and I would like to share some of my findings when working with PageData from code when you want to use the built-in flow for publishing. As you might know a Page Version can have VersionStatus Not Ready (CheckedOut), Ready To Publish (CheckedOut), Published and Previously Published. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://labs.episerver.com/en/Blogs/Mari-Jorgensen/">Mari Jørgensen</a> wrote about <a href="http://labs.episerver.com/en/Blogs/Mari-Jorgensen/Dates/2009/2/Breaking-change-in-GetChildren/">Breaking change in GetChildren()</a> and I would like to share some of my findings when working with <em>PageData</em> from code when you want to use the built-in flow for publishing.</p>
<p>As you might know a Page Version can have <em>VersionStatus</em> <strong>Not Ready </strong>(<em>CheckedOut</em>), <strong>Ready To Publish</strong> (<em>CheckedOut</em>), <strong>Published</strong> and <strong>Previously Published</strong>. Since you in almost all cases are only interested in the published version most methods in <em>DataFactory</em> class only returns <em>PageData</em> objects with the published version.</p>
<h3>Get unpublished pages and pages not in current language branch</h3>
<p><em>GetPage()</em> and <em>GetChildren()</em> returns page(s) published in the current language. You always have to use in a <em>ILanguageSelector</em> if you want to get <em>PageData</em> for another Language Branch than the current language branch.</p>
<pre class="csharpcode">PageDataCollection pages =
  DataFactory.Instance.GetChildren(
    CurrentPage.PageLink,  LanguageSelector.AutoDetect(<span class="kwrd">true</span>));</pre>
<p>This will retrieve all children the same way as the Page Tree in the Structure Tab in Edit Mode. If there is no published version in the <strong>Current Content Language</strong> it will return <em>PageData</em> for the Master Langauge Branch, regardless of Publish Status.</p>
<h3>Saving a page without publishing it</h3>
<p>It is easy to create a new page and not publish it. This can be used for moderation where an Editor uses the publish button in Edit mode to approve.</p>
<pre class="csharpcode">PageData page = DataFactory.Instance.GetDefaultPageData(
                  rootpage.PageLink, <span class="str">"My Page Type"</span>);
page.PageName = <span class="str">"New Page"</span>;
DataFactory.Instance.Save(page, SaveAction.CheckIn,
                          AccessLevel.NoAccess);</pre>
<p><em>SaveAction.CheckIn</em> will make you page Ready to Publish.</p>
<h3>Access Rights</h3>
<p>Even if the current your is not an Editor you may give them Edit access rights to their pages.  It is very easy to add access rights for the current user <span style="text-decoration: underline;">after</span> the page is saved. Note that all existing access right on the parent page will be inherited as usual.</p>
<pre class="csharpcode">PageAccessControlList acl = <span class="kwrd">new</span> PageAccessControlList(page.PageLink);
acl.Add(<span class="kwrd">new</span> AccessControlEntry(
          Membership.GetUser().UserName,
          AccessLevel.Read | AccessLevel.Edit | AccessLevel.Create | AccessLevel.Delete,
          SecurityEntityType.User));
acl.Save();</pre>
<p>It is also easy to filter a collection and remove pages you should not be able to change.</p>
<pre class="csharpcode"><span class="kwrd">new</span> FilterAccess(AccessLevel.Edit).Filter(pages);</pre>
<p>Another approach is to show the page but maybe disable the edit button.</p>
<pre class="csharpcode"><span class="kwrd">bool</span> canChange = page.QueryDistinctAccess(AccessLevel.Edit);</pre>
<h3>Page Versions and Unpublished Pages</h3>
<p>Property Values for the Published Version of a Page is stored in different tables in the database than all other versions of the page. You need something called <strong>WorkID</strong> in your <em>PageReference</em> to load other versions of a page than the published version.</p>
<p><strong>WARNING! Last time I checked <em>GetPage()</em> and <em>GetPages()</em> returned skeleton <em>PageData</em> objects, where all user defined properties are null, for unpublished pages if you did not have a <em>WorkID</em>.</strong></p>
<p>This is an example of how you have to use <em>PageVersion</em> class to retrieve a list of all versions of a page. Each <em>PageVersion</em> has a <em>PageReference</em> with both <em>PageID</em> and <em>WorkID</em>. </p>
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">static</span> PageData GetLastVersion(PageReference pageRef)
{
    PageVersionCollection pageVersions = PageVersion.List(pageRef);
    PageReference lastVersion = pageVersions[0].ID;
    <span class="kwrd">foreach</span> (PageVersion pageVersion <span class="kwrd">in</span> pageVersions)
    {
        <span class="kwrd">if</span> (pageVersion.IsMasterLanguageBranch)
        {
            lastVersion = pageVersion.ID;
        }
    }
    <span class="kwrd">return</span> DataFactory.Instance.GetPage(lastVersion,
             LanguageSelector.AutoDetect(<span class="kwrd">true</span>));
}</pre>
<p>When you have a <em>PageReference</em> with <em>WorkID</em> you can use it with <em>GetPage()</em> to retrieve other versions of a Page. Using and a <em>LanguageSelector</em> with fallback to Master Language is required to get around the filter.</p>
<h3>Update a page without creating a new version</h3>
<p>Sometimes you want to change a PageData object without creating a new version. In the example below UpdatePageFromForm copies values from text boxes to the page. If a value has changed it will be saved.</p>
<pre class="csharpcode">page = GetLastVersion(pageRef).CreateWritableClone();
UpdatePageFromForm(page);
<span class="kwrd">if</span> (page.IsModified)
{
    SaveAction saveAction = SaveAction.CheckIn;
    <span class="kwrd">if</span> (page.Status != VersionStatus.Published)
    {
        <span class="rem">// Update existing version if it is not published</span>
        saveAction = saveAction | SaveAction.ForceCurrentVersion;
    }
    DataFactory.Instance.Save(page, saveAction);
}</pre>
<p>That&#8217;s all for now folks!</p>
<p>Please, leave a comment if you learned something. It is good for my blogging morale to know that someone got helped&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.fredrikhaglund.se/blog/2009/02/18/work-with-unpublished-pagedata-from-code/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
	</channel>
</rss>

