{"id":133,"date":"2020-01-23T15:38:37","date_gmt":"2020-01-23T14:38:37","guid":{"rendered":"https:\/\/wissing.me\/?p=133"},"modified":"2020-01-23T15:38:37","modified_gmt":"2020-01-23T14:38:37","slug":"net-core-authorizations-with-active-directory","status":"publish","type":"post","link":"https:\/\/daan.wsng.eu\/index.php\/2020\/01\/23\/net-core-authorizations-with-active-directory\/","title":{"rendered":".NET Core Authorizations with Active Directory"},"content":{"rendered":"\n<p>Some things sound too easy to do, but still end up eating a lot of time researching how to do it. Recently I made a small Web Application that had to integrate with Active Directory. To be precise: only a specific set of Active Directory groups is allowed to make use of the website functionality. All others should be met with a custom page telling them they are not allowed to do anything. Nothing special, right?<\/p>\n\n\n\n<p>First of all: what is authorization? There is a difference between authentication and authorization. <strong>Authorization<\/strong> means that you are who you say you are. Compare it with an ID card: the card has information about you, and somebody checking your ID card can use that information to verify that you are the one on the ID card. <strong>Authorization<\/strong> means that you are allowed to do what you want to do. Compare with a drivers license: it has the name and personal code (BSN in The Netherlands) of the person that is allowed to drive a car. (A drivers license is also often used as authorization, but that is beside the point).<\/p>\n\n\n\n<h2>Authentication<\/h2>\n\n\n\n<p>Setting up Active Directory authorization in .NET Core was pretty easy. We&#8217;re using IIS, so add the following to <code>ConfigureServices()<\/code><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nservices.Configure&lt;IISServerOptions&gt;(Configuration);\nservices.AddAuthentication(IISDefaults.AuthenticationScheme);\n<\/pre><\/div>\n\n\n<p>When building the project using <code>dotnet publish<\/code>, a web.config file will automatically be created for usage, no need to edit that.  <\/p>\n\n\n\n<p>Next, enable Windows Authentication in IIS itself (which is done by adding  the Windows Feature found as IIS > World Wide Web Services >  Security > Windows Authentication) and restart the host machine.<\/p>\n\n\n\n<p>Lastly, enable <span style=\"text-decoration: underline;\">only<\/span> Windows Authentication in IIS for this website (or web application) under the Authentication feature. <\/p>\n\n\n\n<p>The last thing to do is to publish the output to IIS. Easy Peasy<\/p>\n\n\n\n<h2>Authorization<\/h2>\n\n\n\n<p>Authorization was a bit more difficult. Eventually, this was made possible in four steps: Creating an Authorization Policy, configuring the groups to authorize, annotating the methods that need authorization and setting up a page to display if the user is not authorized.<\/p>\n\n\n\n<h3>Configuration<\/h3>\n\n\n\n<p>Configuring the groups is the most easy part. In appsettings.json, we&#8217;ve added a configuration item which lists the groups to authorize. For example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n{\n    &quot;AuthorizedGroups&quot; : &#91;&quot;Group1&quot;, &quot;Group2&quot;, &quot;Group3&quot;]\n}\n<\/pre><\/div>\n\n\n<p>These can be read like this: <\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nvar groups = Configuration.GetValue&lt;List&lt;string&gt;&gt;(&quot;AuthorizedGroups&quot;);\n<\/pre><\/div>\n\n\n<p>or something similar.<\/p>\n\n\n\n<h3>Creating policy<\/h3>\n\n\n\n<p>Setting up a Policy is the next step. For that, we can do this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nservices.AddAuthorization(options =&gt;\n    var groups = Configuration.GetValue&lt;List&lt;string&gt;&gt;(&quot;AuthorizedGroups&quot;);\n    options.AddPolicy(&quot;MyPolicy&quot;, policy =&gt;\n    {\n        policy.RequireAuthenticatedUser().RequireRole(groups);\n    }\n)\n<\/pre><\/div>\n\n\n<p>This should be easily extendable to multiple properties, by simply reading other settings and creating other policies based on those groups. Notice that we named the policy &#8220;MyPolicy&#8221;. This is important for the next step, where we will enforce the policy on restricted methods.<\/p>\n\n\n\n<h3>Enforcing policy<\/h3>\n\n\n\n<p> In the Controller we want to restrict, we can use the Authorize attribute to annotate the POST method:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&#91;HttpPost]\n&#91;Authorize(Policy = &quot;MyPolicy&quot;)]\npublic async Task&lt;IActionResult&gt; DoAction()\n{\n    \/\/ Do the action here...\n}\n\npublic IActionResult Index()\n{\n    return View();\n}\n<\/pre><\/div>\n\n\n<p>This will prevent unauthorized users for performing this POST function. <\/p>\n\n\n\n<h3>Unauthorized page<\/h3>\n\n\n\n<p>As you can see, the <code>Index()<\/code> method is not annotated with <code>Authorize<\/code>. We do want to show a page when an unauthorized user, but a bit altered. We can do this by adding a new Blazor layout. First, on all the pages we want to protect with authorization, we use a different layout file like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n@{\n    Layout = &quot;Authorized&quot;;\n    \/\/ ....\n}\n<\/pre><\/div>\n\n\n<p>Next, add a Blazor page in the Shared directory named Authorized.cshtml, with the following content:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n@using Microsoft.AspNetCore.Authorization\n@{\n    Layout = &quot;_Layout&quot;;\n    bool authorized = (await AuthorizationService.AuthorizeAsync(User, &quot;MyPolicy&quot;)).Succeeded;\n}\n\n@if (authorized)\n{\n    @RenderBody()\n}\nelse\n{\n    IgnoreBody();\n    &lt;p&gt;You are not authorized to view this page.&lt;\/p&gt;\n}\n\n@section Scripts {\n    @(await RenderSectionAsync(&quot;Scripts&quot;, false))\n}\n\n@* If you use other sections (e.g. css) render them here as well *@\n\n<\/pre><\/div>\n\n\n<p>This page will check if the user is authorized. If so, it will render the page normally. If not, it will display a simple message that the current user is not authorized. The trick here is that two layouts are used: this one first and then the &#8220;default&#8221; layout page. <\/p>\n\n\n\n<h2>Conclusion<\/h2>\n\n\n\n<p>Adding Active Directory authorization is done with a few steps in .NET Core, in a way that you can extend it later to use more fine-grained policies. Also we&#8217;ve created a custom view when a user is not authorized to view a page. We are using IIS however, so it is not clear how to establish this using a different hosting service. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some things sound too easy to do, but still end up eating a lot of time researching how to do it. Recently I made a small Web Application that had to integrate with Active Directory. To be precise: only a specific set of Active Directory groups is allowed to make use of the website functionality&#8230;.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"twitterCardType":"","cardImageID":0,"cardImage":"","cardTitle":"","cardDesc":"","cardImageAlt":"","cardPlayer":"","cardPlayerWidth":0,"cardPlayerHeight":0,"cardPlayerStream":"","cardPlayerCodec":""},"categories":[6,4],"tags":[],"_links":{"self":[{"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/posts\/133"}],"collection":[{"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/comments?post=133"}],"version-history":[{"count":10,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/posts\/133\/revisions"}],"predecessor-version":[{"id":145,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/posts\/133\/revisions\/145"}],"wp:attachment":[{"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/media?parent=133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/categories?post=133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/daan.wsng.eu\/index.php\/wp-json\/wp\/v2\/tags?post=133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}