<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[AJ's Security & Development Blog]]></title><description><![CDATA[Identity Security Expert, Automation Engineer, ADMS Specialist, Powershell Enthusiast]]></description><link>https://blog.ajlindner.net</link><generator>RSS for Node</generator><lastBuildDate>Thu, 21 May 2026 08:28:03 GMT</lastBuildDate><atom:link href="https://blog.ajlindner.net/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Artifacts MMO - Learn how to code with REST APIs by playing a game]]></title><description><![CDATA[Artifacts is a Sandbox MMORPG where you can use any programming language to control your characters with our API. I first heard about it from this Reddit post on r/programming from the sole developer Muigetsu, and immediately dedicated my lazy Sunday...]]></description><link>https://blog.ajlindner.net/artifacts-mmo-learn-how-to-code-with-rest-apis-by-playing-a-game</link><guid isPermaLink="true">https://blog.ajlindner.net/artifacts-mmo-learn-how-to-code-with-rest-apis-by-playing-a-game</guid><category><![CDATA[Powershell]]></category><category><![CDATA[gaming]]></category><category><![CDATA[mmo]]></category><category><![CDATA[development]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[AJ Lindner]]></dc:creator><pubDate>Wed, 27 Aug 2025 00:20:20 GMT</pubDate><content:encoded><![CDATA[<p><a target="_blank" href="https://artifactsmmo.com/">Artifacts</a> is <code>a Sandbox MMORPG where you can use any programming language to control your characters with our API.</code> I first heard about it from <a target="_blank" href="https://www.reddit.com/r/programming/comments/1eea8qy/artifacts_is_a_apibased_mmorpg_game_use_any/">this Reddit post on r/programming</a> from the sole developer <a target="_blank" href="https://www.reddit.com/user/Muigetsu/">Muigetsu</a>, and immediately dedicated my lazy Sunday to figuring out how to play this game that is inherently just grinding by automating the grinding so I don't have to do the grinding myself. Yeah, you don't play this game by playing the game. You play this game by writing code to automate playing the game so you don't have to play the game. It's genius.</p>
<p>For some, this game presents a really fun way to learn programming, or practice working with REST APIs, or try out a new language or framework. But as soon as I hopped in <a target="_blank" href="https://discord.com/invite/prEBQ8a6Vs">the Discord</a> and checked the announcements, there was only one goal I had in mind. The Lich Race. Kill the big bad endgame Lich boss enough times, get the crazy-low-drop-rate Life Crystal before anyone else, win the season.</p>
<p>When I start a new project, there's typically 2 diametrically opposed approaches I'll take. The first, I'd call the "production approach", where I try to meticulously plan out as much as I can in advance, consider all the use cases in scope, all the different systems or endpoints or whatever it is I need to work with, all the parameters I need to accept, and design a plan to implement to that spec. You know, the boring approach. Then there's the "if it works, it works" approach, which is way more fun. Load up VSCode, create a new .ps1 file, and just throw shit at the wall until it sticks. I don't care about writing code that's <em>good</em>, it just needs to <em>work</em>. As I repeated way too many times in the Discord, <code>we got a lich to kill.</code></p>
<p>WARNING (pretend these are those stupid siren emojis). I wrote this thing a year ago. I decided not to publish it because I didn’t feel like sharing my code at the time. That was a bad decision. My <a target="_blank" href="https://github.com/AJLindner/Artifacts">disgusting, horrific spaghetti code</a> is now available along with this post for <em>your viewing pleasure.</em> I highly recommend having a strong drink and an empty stomach if you decide to delve into its depths. Also it’s been a year of changes to the reference API so…I can guarantee it will not work at all in any way whatsoever.</p>
<h1 id="heading-the-alpha-experience">The Alpha Experience</h1>
<p>Being a part of this open alpha test from the beginning felt, even at the time, like a small moment in history. Not that it's necessarily anything monumental, just the feeling of <code>I was there, live, when Muigetsu implemented an unannounced rate limit change that broke everyone's code, man what a fun time</code>. It's an inviting community of higher skilled (than me) but equally degenerate developers building crazy GUIs, TUIs, &amp; VSCUIs (my term for "VS Code User Interface". You're welcome for that nightmare.), writing complex combat simulations to generate the optimal equipment loadout for different enemies, tracking the General Exchange over time to speculate on the market and try to crash the economy, developing tiny micro-optimizations so their bots perform 2% faster on average than others, and building crazy AI algorithms to automate the entire process of grinding up a team of 5 characters to take on the lich while they sit back in an armchair smoking a pipe and wearing a robe, or something like that.</p>
<p>And then there's this idiot using Windows Powershell (the older, uglier Powershell 5.1, not the hip cool Powershell 7) spamming <code>who needs OpenAPI codegen, we got a lich to kill</code>.</p>
<p>But, <code>if it works, it works</code>. And so it did for a while. I was at the top of the leaderboards, contending with a few others that were obsessively focused on getting the first Life Crystal drop, grinding away by not grinding away. And then the "alpha" part of the alpha test started to creep in.</p>
<p>Take a sole developer with a day job running an open alpha test on a game that skyrocketed way beyond what they expected, and a bunch of idiots like me slamming their API with shoddy code, and you get outages, crashes, bugs, unplanned production changes, and a whole lot of messy fun with it.</p>
<p>So, if you decide to dig through the dumpster fire that is my code and you ask yourself <code>what the hell was this idiot thinking?</code>, I'm right there with you. And there was certainly a reason I wrote it that way at the time -- it got the job done, quickly, and I had a lich to kill.</p>
<h1 id="heading-what-the-hell-this-idiot-was-thinking">What the hell this idiot was thinking</h1>
<p>It was actually pretty simple - figure out what I need my characters to do next to work towards the lich, write some code to hit that endpoint on a loop, and let it run. Rinse and repeat as the tasks got more varied and complex, as new API changes were announced (or just done haphazardly, followed by a delightful <code>whoops</code> from Muigetsu in Discord), as downtime and outages during the night broke my loops, and that's how I ended up here.</p>
<p>The best part is, I didn't even win the Lich Race. No, the actual best part is, Artifacts works on a wipe system, where every season ends with the entire server being wiped so everyone can start fresh on a new set of challenges. And while others were diligently writing <em>good code</em>, which might require a few tweaks or additions to adapt for the changes in each season, the thought of updating my monstrosity is less appealing than just starting from scratch with the tried-and-true "production approach". Although it may be a back alley dumpster fire smoldering away behind an abandoned Waffle House, I had a damn fun time making it, and a lot more fun getting picked on by all the smarter, ACTUAL devs in the Discord using things like <em>async</em> and <em>the OpenAPI spec</em> and <em>AI systems that aren't just me highlighting a few lines of code and pressing F8 in 5 different terminals to tell my characters what to do.</em></p>
<p>But who needs all that stuff. <code>We got a lich to kill</code>.</p>
<h1 id="heading-join-the-cult-or-kill-it-i-guess">Join The Cult (or, kill it I guess?)</h1>
<p>When I originally wrote this article, I was announcing the release of Season 2. Well, my bad Muigetsu. It is now to hype up SEASON 6, planned for early October 2025. Although I certainly don't have the time to commit to this season like I did the first, I'll be back around poking at the API, taking shots at Rosenstjerne (the winner of the Lich Race, what a nerd), and luring people to the <code>#powershell</code> channel in Discord with a siren song of sunshine and rainbows.</p>
<p>I hope to see you there.</p>
<h1 id="heading-oh-yeah-i-published-the-code">Oh, yeah I published the code</h1>
<p>Honestly, I don’t remember how half of it works, outside of the fact I would just highlight + f8 some stuff in <code>Artifacts_Tasks.ps1</code> and run it in multiple Powershell terminals, and that uses functions defined in <code>Artifacts.ps1</code>, and equips armor/weapons defined in <code>Loadouts.ps1</code>. Oh well, I have fun getting made fun of, here you go.</p>
<p><a target="_blank" href="https://github.com/AJLindner/Artifacts">https://github.com/AJLindner/Artifacts</a></p>
]]></content:encoded></item><item><title><![CDATA[5 Things You Can Do RIGHT NOW to Protect Your AD Against Attackers]]></title><description><![CDATA[You live in a constant state of fear. Fear that at any moment, Bob from accounting is going to click that email link promising a free $25 gift card as thanks for his unwavering loyalty to Chipotle. And the next morning you'll be greeted by a very int...]]></description><link>https://blog.ajlindner.net/5-things-you-can-do-right-now-to-protect-your-ad-against-attackers</link><guid isPermaLink="true">https://blog.ajlindner.net/5-things-you-can-do-right-now-to-protect-your-ad-against-attackers</guid><category><![CDATA[Active Directory]]></category><category><![CDATA[satire]]></category><category><![CDATA[Security]]></category><category><![CDATA[#cybersecurity]]></category><dc:creator><![CDATA[AJ Lindner]]></dc:creator><pubDate>Thu, 14 Mar 2024 14:49:23 GMT</pubDate><content:encoded><![CDATA[<p>You live in a constant state of fear. Fear that at any moment, Bob from accounting is going to click that email link promising a free $25 gift card as thanks for his unwavering loyalty to Chipotle. And the next morning you'll be greeted by a very intimidating character named <a target="_blank" href="https://en.wikipedia.org/wiki/Petya_(malware_family)">Petya</a> who wants millions in either Dogecoin or Walmart gift cards in exchange for restoring all your data and pinky promising they won't sell it to the highest bidder.</p>
<p>Luckily for you, I have 5 tactics that I've discovered in my <a target="_blank" href="https://en.wikipedia.org/wiki/Active_Directory#:~:text=Microsoft%20previewed%20Active%20Directory%20in,administration%20in%20Windows%20Server%202003.">35 years of Active Directory experience</a> to <em>guarantee</em> that you will never have to worry again.</p>
<h2 id="heading-1-just-get-rid-of-ad">1. Just get rid of AD</h2>
<p>You know it's not secure, and you're not entirely sure how to truly fix it. Sure, you have some ideas, but every time you suggest them your executive leadership reminds you that they're too busy and important to deal with the hassle of remembering any password that isn't "password" and that you have more important things to focus on like giving them Domain Admin permissions. Why's that taking so long by the way? You said it would take "about a week" to "program that feature" but you remind them that you're still waiting on critical updates to complete for <a target="_blank" href="https://www.cvedetails.com/vulnerability-list/vendor_id-53/product_id-6761/Adobe-Flash-Player.html">Adobe Flash</a>.</p>
<p>You decide to take the internet's most common advice. Lawyer up, hit the gym, delete Active Directory. Something like that. You think to yourself "this year will <em>definitely</em> be <a target="_blank" href="https://www.reddit.com/r/linuxmasterrace/comments/uok9p9/2023_will_be_the_year_of_linux_desktop/">the year of the Linux desktop</a>". You said that last year and the year before as well, but you're just as confident about it now as you are about finally upgrading your domain controllers off of Server 2003. You daydream of a glorious day in the office, a fresh breeze wafting the cool taste of <a target="_blank" href="https://linuxmint.com/">Mint</a> into your mouth, the rich smell of <a target="_blank" href="https://github.com/linuxmint/cinnamon">Cinnamon</a> deep into your nostrils, and the sweet sounds of computer mice being thrown in the trash while keyboards tap away dumping text into terminals. At lunch you sit as a team, sharing <a target="_blank" href="https://blog.quest.com/understanding-kerberoasting-attacks-and-how-to-prevent-them/">Kerberoast</a> beef sandwiches while you <a target="_blank" href="https://blog.quest.com/pass-the-hash-pth-attacks-how-they-work-and-how-to-defend-against-them/">Pass the Hash</a>browns, <a target="_blank" href="https://www.crowdstrike.com/cybersecurity-101/lateral-movement/">moving laterally</a> around the table handing out <a target="_blank" href="https://blog.quest.com/golden-ticket-attacks-how-they-work-and-how-to-defend-against-them/">Golden Tickets</a> to show how much you appreciate everyone, especially <a target="_blank" href="https://github.com/ParrotSec/mimikatz">Mimi the office cat</a>.</p>
<p>And then the ping of a fresh email from Bob who locked himself out for the 4th time this week snaps you back to the reality that your abusive relationship with AD isn't ending any time soon.</p>
<h2 id="heading-2-set-ludicrously-strong-passwords">2. Set Ludicrously Strong Passwords</h2>
<p>Look, you don't want "the hackers" to get your passwords and you sure as hell don't trust your users to stick with the pass phrases you've been yelling about since you started. You know for a fact that the 10 people you wrangled for a trial just copied Bob and used "<a target="_blank" href="https://xkcd.com/936/">correct horse battery staple</a>", so it falls on you. And you're up for the task. You wrote the perfect password generation script last year and spend every weekly status meeting practically begging to enforce its use as a requirement.</p>
<p>You go through all the magnificent details. It generates a random assortment of the hex values of 128 non-repeating characters from a set including numbers &amp; symbols, the English, Cyrillic, Arabic, Bengali, and Hebrew alphabets, and a <a target="_blank" href="https://www.youtube.com/watch?v=lIFE7h3m40U">selection of your favorite emojis</a>. Then it generates a SHA-512 hash, salted with the answer to a random <a target="_blank" href="https://lichess.org/api#tag/Puzzles">Lichess puzzle</a> concatenated with a random cat fact from the <a target="_blank" href="https://catfact.ninja/">catfact.ninja</a> API. Finally, it uses that as a seed to generate a random number that's thrown at the end for good measure.</p>
<p>You know good and well they'd just write it down so they can remember it. That's why you spearheaded a company initiative to go completely paperless, under the guise of caring about your environmental impact. You also personally show up first to the office and remove every piece of paper people sneak in anyway, knowing you won't get caught because you never manage to get budget for the security cameras you keep asking for. You put on a huge show-and-tell ensuring everyone is aware that any complaints would lead to their laptop getting replaced with the leftover stock from 6 years ago running a build of <a target="_blank" href="https://knowyourmeme.com/memes/install-gentoo">Gentoo</a>. <a target="_blank" href="https://knowyourmeme.com/memes/btw-i-use-arch">You use Arch, btw</a>.</p>
<p>But you can breathe a sigh of relief. There's no way the hackers are logging in now. Actually no one is logging in now. You're fine with that.</p>
<h2 id="heading-3-lock-down-permissions">3. Lock Down Permissions</h2>
<p>You're sure you've been breached when you discover a stealthy foothold the hackers clearly left behind, an account named with some random letters they thought you wouldn't notice. Goodbye "<a target="_blank" href="https://blog.quest.com/what-is-krbtgt-and-why-should-you-change-the-password/">krbtgt</a>", whoever you are. You pat yourself on the back and resolve to clean up everything else.</p>
<p>First off, why does EVERYONE have read permissions to the entire directory? That sounds like a bad idea, you just go ahead and turn that off. And where the hell did all these service accounts come from? You see svc_sql, svc_smb, svc_cert, so many more. There's no owner, no description, and they have weird group memberships like "PostGres_PRD_RW" and "CertSvAdm" which seem particularly sketchy. You just go ahead and delete those.</p>
<p>Speaking of, better clean up all those other group memberships. Just a quick little bit of powershell.</p>
<pre><code class="lang-powershell"><span class="hljs-keyword">ForEach</span> (<span class="hljs-variable">$Group</span> <span class="hljs-keyword">in</span> (<span class="hljs-built_in">Get-ADGroup</span> <span class="hljs-literal">-Filter</span> *)) {
    <span class="hljs-variable">$Group</span> | <span class="hljs-built_in">Set-ADGroup</span> <span class="hljs-literal">-Clear</span> member
}
</code></pre>
<p>You sign out for the day and turn off your work phone to enjoy the weekend.</p>
<h2 id="heading-4-quit-your-job">4. Quit Your Job</h2>
<p>It's not <em>your</em> AD anymore.</p>
<h2 id="heading-5-become-a-linkedinfluencer">5. Become a LinkedInfluencer</h2>
<p>You're not a disillusioned former admin from a now-defunct company that went bankrupt after failing to recover from a ransomware attack that exposed the fact your CISO was embezzling millions of dollars from the security budget. No, you're a battle-hardened cyber warrior hunting threats in the shadows, yearning to share the gospel of your knowledge as a veritable guru of IT Security. With gusto, you embrace your newfound career, sharing photos of you in a black hoodie, your blurred-out face staring down 6 monitors scrolling green text on a black background as you mash your keyboard on <a target="_blank" href="https://hackertyper.net/">Hacker Typer</a>.</p>
<p>Immediately after, it's you in a tailored bespoke suit, hair slicked back and wrapped into a tidy man bun, obvious fake Rolex front and center right above your favorite quote "<a target="_blank" href="https://knowyourmeme.com/memes/in-this-moment-i-am-euphoric">I am enlightened by my intelligence</a>". And then, to show how far you've come, an old picture of you as a fresh <a target="_blank" href="https://bofh.bjash.com/">pimply-faced youth</a>, not yet scarred by the rigors of experience, toasting the camera with a 2-liter bottle of mountain dew that left an obvious stain on the cargo pants you unironically called "business tactical".</p>
<p>All this, accompanied by a list of your greatest hits. The captivating thought pieces that rocketed you into the spotlight of immense fame, riches, and success gathered from all 571 of your loyal followers.</p>
<ul>
<li><p>6 Ways to Tell if Someone is a Hacker Just by their Smell (number 4 will SHOCK you!)</p>
</li>
<li><p>Do You Have What It Takes to Perform a Successful Multi-Factor Cryptographic Authentication Against a Domain-Joined Virtual Appliance? Take this quiz to find out!</p>
</li>
<li><p>Why The Best IT Admins Wear the Same Shirt to Work Every Day</p>
</li>
<li><p>Your Domain Controller Does NOT Need <a target="_blank" href="https://hackdefense.com/publications/het-belang-van-smb-signing/">SMB Signing</a>, and Here's Why.</p>
</li>
<li><p>How to Become a Successful IT Guru Like Me for Only $150 (buy this book!)</p>
</li>
</ul>
<h1 id="heading-conclusion">Conclusion</h1>
<p>By following these 5 easy steps, you too can build a successful career and massively inflate your ego overnight, while you sleep soundly on your mom's 1992 IKEA sleeper sofa, just like me.</p>
]]></content:encoded></item><item><title><![CDATA[Post-War Analysis: How a Forest Trust Broke Federated Authentication]]></title><description><![CDATA[This is the journey of troubleshooting a complex, niche problem that surprisingly resulted in a very simple solution. I ignored many common sense principles, instead diving deep into StackOverflow rabbit holes in desperate search of the complicated t...]]></description><link>https://blog.ajlindner.net/post-war-analysis-how-a-forest-trust-broke-federated-authentication</link><guid isPermaLink="true">https://blog.ajlindner.net/post-war-analysis-how-a-forest-trust-broke-federated-authentication</guid><category><![CDATA[software development]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[Developer]]></category><category><![CDATA[C#]]></category><category><![CDATA[ASP.NET]]></category><category><![CDATA[SSO]]></category><category><![CDATA[SAML]]></category><category><![CDATA[Active Directory]]></category><category><![CDATA[authentication]]></category><dc:creator><![CDATA[AJ Lindner]]></dc:creator><pubDate>Thu, 30 Nov 2023 15:03:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/KeFyYzxqmH0/upload/2ae245ba2d234dd5897b06f153bb4c1c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is the journey of troubleshooting a complex, niche problem that surprisingly resulted in a very simple solution. I ignored many common sense principles, instead diving deep into StackOverflow rabbit holes in desperate search of the complicated technical answer I thought I needed, not realizing I was exploring a series of red herrings disguising what frankly should have been an obvious answer that I just never considered. I'd like to blame a lack of sleep, or my determination to overcome a difficult challenge, but the whole time I was simply ignoring the basics.</p>
<p>And, as it often goes, the saving grace that smacked some sense back into me came from a 13-year-old article on a WordPress blog I'd never heard of.</p>
<h1 id="heading-setting-the-stage">Setting the Stage</h1>
<p>I have a .NET web application hosted in IIS, let's call it <strong>WebApp.</strong> WebApp allows users to authenticate with their Domain accounts via Basic Authentication or Windows Authentication. It <em>also</em> supports federation via WS-Fed and SAML2.0, utilizing ASP.NET Impersonation behind the scenes. When using ADFS for federation in an interesting AD environment, I encountered the following issue, which was completely novel to me.</p>
<h2 id="heading-a-wild-ad-environment-appears">A Wild AD Environment Appears</h2>
<p>This environment has the following 2 forests, in a 2-way transitive trust, with the following UPN Suffixes:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>example.com</td><td><strong>company.com</strong></td></tr>
</thead>
<tbody>
<tr>
<td>example.net</td><td>company.net</td></tr>
<tr>
<td>acme.com</td><td>acme.com</td></tr>
</tbody>
</table>
</div><p>WebApp is installed in <code>example.com</code>, and configured with Basic Authentication. If I authenticate as a user with each UPN Suffix across both forests using their <code>UserPrincipalName</code> as the username, here is what happens.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>User's Domain</strong></td><td><strong>User</strong></td><td><strong>Result</strong></td></tr>
</thead>
<tbody>
<tr>
<td>example.com</td><td>Bob@example.com</td><td>Success</td></tr>
<tr>
<td>example.com</td><td>Alice@example.net</td><td>Success</td></tr>
<tr>
<td>example.com</td><td>Sally@acme.com</td><td>Success</td></tr>
<tr>
<td>company.com</td><td>Joe@company.com</td><td>Success</td></tr>
<tr>
<td>company.com</td><td>John@company.net</td><td>Success</td></tr>
<tr>
<td>company.com</td><td>Jacob@acme.com</td><td><strong>Failure</strong></td></tr>
</tbody>
</table>
</div><p>When Jacob authenticates as <code>Jacob@acme.com</code>, it fails for this web app. Although I didn't realize this at the time, I now know this is due to <a target="_blank" href="https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc784334(v=ws.10)?redirectedfrom=MSDN#collision-detection">Microsoft’s Collision Detection</a> when routing name suffixes across forests. If I authenticate to <code>example.com</code> using my UPN, and my UPN Suffix exists in multiple forests in the trust, Microsoft will <em>not</em> cross the trust to find my account. It will only search in <code>example.com</code>.</p>
<p>However, if I <em>instead</em> authenticate with the username in the legacy form of <code>NetBiosName\SamAccountName</code>, then every user can successfully authenticate.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>User's Domain</strong></td><td><strong>User</strong></td><td><strong>Result</strong></td></tr>
</thead>
<tbody>
<tr>
<td>example.com</td><td>example\Bob</td><td>Success</td></tr>
<tr>
<td>example.com</td><td>example\Alice</td><td>Success</td></tr>
<tr>
<td>example.com</td><td>example\Sally</td><td>Success</td></tr>
<tr>
<td>company.com</td><td>company\Joe</td><td>Success</td></tr>
<tr>
<td>company.com</td><td>company\John</td><td>Success</td></tr>
<tr>
<td>company.com</td><td>company\Jacob</td><td>Success</td></tr>
</tbody>
</table>
</div><h2 id="heading-federation-uses-confusion-its-a-critical-hit">Federation Uses Confusion. It's a Critical Hit.</h2>
<p>After this, I switched to Federated Authentication using ADFS. As expected, when authenticating to ADFS, I experienced the same results. <code>company\Jacob</code> succeeds, <code>jacob@acme.com</code> fails. However, once Jacob authenticates to ADFS and tries to federate to WebApp, WebApp fails to authenticate.</p>
<pre><code class="lang-plaintext">WebApp: Authentication Failed.
</code></pre>
<p>So, what's going on here? Again I didn't know about forest trusts sharing UPN Suffixes across multiple forests, the collision detection enforcement that triggers, or how authentication with different username formats would apply. After my initial testing and research, I gathered this conclusion:</p>
<blockquote>
<p>Authentication with UPN fails. Authentication with NetBiosName\SamAccountName works. The code uses UPN. Let's change that.</p>
</blockquote>
<h1 id="heading-webapp-is-confused-it-hit-itself-in-its-confusion">WebApp is Confused... It hit itself in its confusion!</h1>
<p>Now let's examine what's happening in the code. Well, some abstract pseudocode, at least.</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Search for user in forest &amp; trusted forests</span>
user = findUserByclaims(claimAttribute, claimValue);

<span class="hljs-comment">// Throw error if no user was found</span>
<span class="hljs-keyword">if</span> (user == <span class="hljs-literal">null</span>) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Exception(<span class="hljs-string">"User could not be identified from the provided claims."</span>);
};

<span class="hljs-comment">// Else, create WindowsIdentity object from UPN and impersonate</span>
<span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Error is here</span>
    WindowsIdentity userIdentity = <span class="hljs-keyword">new</span> WindowsIdentity(user.upn);

    userIdentity.Impersonate();
};
</code></pre>
<p>So when a user federates to WebApp, I first search for that user's Active Directory account in the current domain and all trusted domains and forests based on the provided claims. If I find an account, I then try to instantiate a <code>WindowsIdentity</code> object from the user's UPN value, and then impersonate that user.</p>
<p>The problem doesn't occur on the <code>.Impersonate()</code> method as I thought it might, but when trying to create the <code>WindowsIdentity</code> from the UPN value. This works perfectly fine for users in <code>example.com</code> and users in <code>company.com</code> who have a routable UPN Suffix, but not for users in <code>company.com</code> who have a non-routable UPN Suffix, i.e. <code>acme.com</code> which exists in both forests.</p>
<p>Okay, easy fix. I'll just use <code>NetBiosName\SamAccountName</code> instead of <code>userPrincipalName</code>. Unfortunately, that throws an error.</p>
<pre><code class="lang-csharp">An unhandled exception of type <span class="hljs-string">'System.Security.SecurityException'</span> occurred <span class="hljs-keyword">in</span> System.Security.Principal.Windows.dll: <span class="hljs-string">'The name provided is not a properly formed account name.'</span>
</code></pre>
<p>Okay, what else can I try? Let's <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity?view=netframework-4.8.1">read the docs</a> for the WindowsIdentity class.</p>
<h2 id="heading-why-documentation-is-sometimes-the-enemy">Why Documentation is Sometimes the Enemy</h2>
<p>Here's where the aquatic assault began as red herrings attacked me from all angles. Per the docs, I am using <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.-ctor?view=netframework-4.8.1#system-security-principal-windowsidentity-ctor(system-string)">this constructor</a>, which just requires the user's UPN as an argument. Assuming the service account has the right permissions, creating a <code>WindowsIdentity</code> object with this constructor will automatically retrieve a token for that user via the <code>LsaLogonUser</code> function, utilizing the <code>KERB-S4U_LOGON</code> structure. This is how WebApp can then impersonate the user without knowing their password. Per the docs:</p>
<blockquote>
<p>...The UPN identified in <code>sUserPrincipalName</code> is used to retrieve a token for that user through the Windows API <code>LsaLogonUser</code> function. In turn that token is used to identify the user. An exception might be returned due to the inability to log on using the supplied UPN.</p>
<p>...this constructor uses the <a target="_blank" href="https://go.microsoft.com/fwlink/?LinkId=143533"><strong>KERB_S4U_LOGON structure</strong></a>, which was first introduced in Windows Server 2003</p>
</blockquote>
<p>It's clear as day, right there in the remarks! <code>LsaLogonUser</code> may fail due to the UPN value I'm supplying. So what I <em>really</em> should be doing is...calling <code>LsaLogonUser</code> directly with my own arguments and using a different <code>WindowsIdentity</code> constructor that accepts the Kerberos Token that returns...right?</p>
<h2 id="heading-i-was-not-right">I Was Not Right</h2>
<p>And here begins a furious, relentless, desperate session of intense Google-fu, prying for any relevant sample code to copy/paste. Sprinkled with very reassuring <a target="_blank" href="https://stackoverflow.com/questions/12537834/web-app-impersonation-for-remote-server-logonuser-or-lsalogonuser">StackOverflow threads</a> annotating that I'm wading in waters that have never been waded in before, experiencing a unique issue that no one but me seems to understand.</p>
<blockquote>
<p>...<strong>In conclusion</strong></p>
<p>There is only one use case were[sic] LsaLogonUser is better than LogonUser. But since <a target="_blank" href="http://msdn.microsoft.com/en-us/library/td3046fc.aspx">WindowsIdentity provides a constructor for that (S4U)</a>, I don't see why one would ever use LsaLogonUser in a .Net application.</p>
</blockquote>
<p>No, <a target="_blank" href="https://stackoverflow.com/users/591064/ixe013">ixe013, Security Engineer at Google</a>, there are TWO use cases! I've outsmarted you! Now please point me to sample code that my (at this point) fully-rotted-husk of a brain can steal!</p>
<p>Of course, ixe013 was right. The more I looked, the more the realization struck that even if I <em>had</em> to use <code>LsaLogonUser</code> myself, it's...uhh...very complicated. Daunting. The thought alone gives me stress-induced cold sweats and shivers.</p>
<p>I started looking elsewhere, digging into Kerberos Authentication, the details of Forest Trust Relationships, "how the f*** does IIS Basic Auth work". Finally, I looped back to a simple question.</p>
<blockquote>
<p>What even IS a UPN?</p>
</blockquote>
<h2 id="heading-the-lightbulbeurekagotem-momentits-super-effective">The Lightbulb/Eureka/Got'Em Moment...It's Super Effective</h2>
<p>Buried deep in the comments section of yet another long-abandoned StackOverflow thread, I encountered a link to <a target="_blank" href="https://jorgequestforknowledge.wordpress.com/2010/10/12/">this 2010 series of articles</a> from the <a target="_blank" href="https://jorgequestforknowledge.wordpress.com/">Jorge's Quest for Knowledge Wordpress site</a>. Jorge's Knowledge reminded me of a basic fact about UPNs, which had been so irrelevant to me for so many years that my hollow husk-brain never once considered it as the obvious answer it was.</p>
<p><strong>Users have 2 UPNs.</strong></p>
<ol>
<li><p>Explicit UPN (eUPN). This is the value that shows in the user's <code>userPrincipalName</code> attribute, and is configurable on every user account. This value contains my particularly frustrating UPN Suffix that breaks the rules of a forest trust.<br /> <code>jacob@acme.com</code></p>
</li>
<li><p>Implicit UPN (iUPN). ALL users have this, whether you define an eUPN or not, but is <em>not</em> stored in any AD Attribute. The iUPN is always available in the format <code>sAMAccountName</code>@<code>FQDN</code>.<br /> <code>jacob@company.com</code></p>
</li>
</ol>
<p>Yeah, it was that simple the whole time. Instead of passing the user's <code>userPrincipalName</code> attribute, I can pass the iUPN instead. <code>new WindowsIdentity("jacob@company.com");</code>. It doesn't matter that Jacob's UPN attribute is <code>jacob@acme.com</code>. I have the domain, and I have a user object with a bunch of AD Attributes, including <code>sAMAccountname</code>. Sure enough, this solves the issue with an <em>incredibly</em> simple code change. No tricky <code>LsaLogonUser</code> implementation, no major code rewrite. Just send a different value for UPN that uniquely identifies the user across all trusted forests.</p>
<p>As a side note, if you're also thinking "well, he isn't authenticating to ADFS with <code>jacob@acme.com</code> either", you're correct. But, this is federation. It could be ADFS or any other SAML or WS-Fed provider, and I'm not necessarily getting the value entered in the username field, or even the UPN as a claim. It might be something else like <code>objectGUID</code> or <code>email</code>. Either way, I'm still searching for his AD account across all trusted forests/domains, and attempting to impersonate him with a UPN value.</p>
<h1 id="heading-you-defeated-trainer-annoying-problem-you-gained-100">You Defeated Trainer "Annoying Problem". You Gained ¥100.</h1>
<p>Here are my final takeaways.</p>
<ol>
<li><p>Breaking down the problem into simple, testable scenarios is <em>always</em> a great first step.</p>
</li>
<li><p>Occam's Razor is often the reason I can't sleep.</p>
</li>
<li><p>Documentation doesn't lie, but it often omits relevant details for niche situations.</p>
</li>
<li><p>The StackOverflow user you think is wrong probably isn't.</p>
</li>
<li><p>I don't know how to write .NET apps.</p>
</li>
<li><p>Heading sections of your blog post with Pokémon references is <em>always</em> a great first step.</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Why You Need Active Roles, Even if You Have IGA]]></title><description><![CDATA[Here are 3 scenarios I come across frequently, with customers of all sizes, in all industries, when discussing Active Roles by One Identity:

"We have an IGA solution. It already manages our Active Di]]></description><link>https://blog.ajlindner.net/why-you-need-active-roles-even-if-you-have-iga</link><guid isPermaLink="true">https://blog.ajlindner.net/why-you-need-active-roles-even-if-you-have-iga</guid><category><![CDATA[Security]]></category><category><![CDATA[identity-management]]></category><category><![CDATA[Active Directory]]></category><dc:creator><![CDATA[AJ Lindner]]></dc:creator><pubDate>Fri, 23 Jun 2023 17:28:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687542498647/e9966b66-7464-4631-a2b9-7c56199af850.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Here are 3 scenarios I come across frequently, with customers of all sizes, in all industries, when discussing <a href="https://www.oneidentity.com/products/active-roles">Active Roles by One Identity</a>:</p>
<ol>
<li><p>"We have an IGA solution. It already manages our Active Directory just fine. Why do I need this?"</p>
</li>
<li><p>"We don't have an IGA solution yet, but would like to implement one in the next X months/years. Wouldn't we just be repeating ourselves if we implement this now?"</p>
</li>
<li><p>"We have an IGA solution. It's not quite doing everything we need in Active Directory today, but it could with additional implementation. Why would we bring in a separate solution for that?"</p>
</li>
</ol>
<p>These situations come from customers on all points of the "Identity Security Maturity" spectrum. Those who have <em>nothing</em> in place or <em>some things</em> in place or an <em>entire stack</em> of fully implemented solutions in every category. Although all of them have different needs, pain points and solution gaps, as long as they have Active Directory (AD), they <em>all</em> need an <a href="https://www.oneidentity.com/what-is-active-directory-management-and-security/">AD Management</a> solution like Active Roles.</p>
<p>Before discussing the benefits Active Roles provides that <a href="https://www.oneidentity.com/what-is-iga/">Identity Governance &amp; Administration (IGA)</a> solutions can't, it helps to highlight what each of these solutions is designed to do, what they typically do and where they overlap.</p>
<h2>IGA Solution Overview</h2>
<p>IGA solutions, like <a href="https://www.oneidentity.com/products/identity-manager/">Identity Manager by One Identity</a>, aim to <em>fully govern</em> the identities within your organization. This includes all accounts, entitlements, permissions, etc., across your entire on-premises and cloud infrastructure. These identities typically include employees, contractors and others who need access to any number of corporate systems. Often, this extends to vendors and other third parties, and sometimes service identities, customers and more. The picturesque end goal is to build a consolidated, unified source for all identities that have access to <em>anything</em> within your organization by correlating data from <strong>source systems</strong>, like an HRIS or ERP, and by automatically controlling the access they have to all possible <strong>target systems</strong>, like AD, email, on-premises and cloud applications.</p>
<p>IGA solutions offer a broad spectrum of capabilities, and anyone who's implemented one <em>knows</em> that it's not just a project to implement these features, but an ongoing journey.</p>
<h3>Common Features of an IGA Solution</h3>
<ul>
<li><p><a href="https://www.oneidentity.com/learn/what-is-identity-lifecycle-management.aspx"><strong>Identity/User Lifecycle Management (ILM/ULM)</strong></a><strong>:</strong> Automated provisioning of user access to all target systems within your environment, access changes within those systems stemming from requests or role changes and deprovisioning of access to those systems</p>
</li>
<li><p><a href="https://www.oneidentity.com/learn/what-is-role-based-access-control.aspx"><strong>Role-Based Access Controls (RBAC)</strong></a><strong>:</strong> ILM/ULM processes are commonly driven in part by <em>roles</em> granted automatically to identities based on attributes like their job title, department or location</p>
</li>
<li><p><strong>Self-Service Access Requests:</strong> End users or their managers can request appropriate access to target systems or applications needed to do their job, usually with an approval process</p>
</li>
<li><p><strong>Access Management for Administrators:</strong> System admins and owners can manage who has access (and how and when) to the systems or applications that they are responsible for</p>
</li>
<li><p><a href="https://www.oneidentity.com/learn/what-is-cyber-security-certification-and-attestation.aspx"><strong>Attestations (a.k.a Certifications)</strong></a><strong>:</strong> System owners, managers and others can be required to perform regular, or ad-hoc, campaigns to ensure that only the <em>right</em> people have the <em>right</em> access to the <em>right</em> systems at the <em>right</em> time</p>
</li>
<li><p><strong>Segregation/Separation of Duties:</strong> Policies <em>enforce</em> the access identities have across all managed <em>target systems</em> so that no inappropriate access is possible, outside of exceptions that are configured, approved, logged and auditable</p>
</li>
<li><p><strong>Reporting &amp; Auditing:</strong> Custom reporting features and audit portals allow the necessary people to ensure that <em>all access</em> is correct and/or to validate how and why someone may have inappropriate or otherwise non-compliant access across all <em>target systems</em></p>
</li>
</ul>
<p>In summary, IGA solutions are identity centric. They keep track of a <em>person</em>. This person was created directly or came from some other <em>source system.</em> This person has access to one or more <em>target systems,</em> and within those, they have <em>entitlements.</em> The entitlements they have in those systems are managed automatically via RBAC rules based on data from the <em>source system</em> or from that access being requested, and is kept in check by system owners and managers testifying to that access regularly. When that person is no longer with the company, all their access is removed.</p>
<p><strong>IGA solutions, generally, treat Active Directory just like any other target system.</strong> However, <a href="https://www.oneidentity.com/what-is-active-directory-management-and-security/">Active Directory</a> is much more than just an application that employees need access to.</p>
<h3>AD Management Overview (Active Roles)</h3>
<p>Active Roles, on the other hand, aims to be your "Swiss Army Knife" for securing access to and performing day-to-day operations in AD. And, whenever I say "AD," that includes Exchange, Azure AD and Microsoft 365. While IGA solutions focus on <em>identities</em> or <em>people</em>, Active Roles focuses on <em>directory objects</em> (e.g., user accounts, groups, OUs, mailboxes, computers, etc.).</p>
<p>At the core of Active Roles is its delegation model, which acts somewhat like a proxy or a firewall in front of AD, providing fine-grained access controls to enforce a <em>true</em> least privilege access model for all users and administrators. Think of this as <a href="https://www.oneidentity.com/what-is-privileged-access-management/">Privileged Access Management (PAM)</a> for AD and Azure AD. Taking advantage of this and other features in the toolset further allows you to:</p>
<ul>
<li><p>Enforce data standards to ensure that your objects and their attributes align with your requirements</p>
</li>
<li><p>Automatically organize objects into virtual containers based on queries or group memberships, and delegate access to those objects</p>
</li>
<li><p>Manually or automatically clean up unused and non-compliant objects</p>
</li>
<li><p>Simplify Help Desk processes and shift responsibilities from Help Desk staff to system owners and managers</p>
</li>
<li><p>Automate the management of directory objects and much more</p>
</li>
</ul>
<p>In short, they're designed around two entirely different paradigms, and each have distinct features. However, the slight functional overlap is what often brings about confusion.</p>
<h3>The Functional Overlap</h3>
<p>There are three key functions that both IGA solutions and Active Roles can perform, to varying degrees, in AD and Azure AD:</p>
<ol>
<li><p>Identity/User Lifecycle Management (ILM/ULM)</p>
</li>
<li><p>Role-Based and Attribute-Based Access Controls (RBAC/ABAC)</p>
</li>
<li><p>Administrative Access</p>
</li>
</ol>
<p>When an IGA solution is in place, or is planned for implementation, best practices dictate that it be the driver of these functions for your employees. So, to reiterate, why would you still need Active Roles? Let's return to the two questions from the beginning of the article and discuss how it fits into both scenarios.</p>
<h3>AD-Centric Identity</h3>
<blockquote>
<p>We don't have an IGA solution yet, but would like to implement one in the next X months/years. Wouldn't we just be repeating ourselves if we implement this now?</p>
</blockquote>
<p>This approach is typically for organizations that are new or not very mature in their identity strategy, and for whom AD is the primary source of user access. In this scenario, Active Roles provides User Lifecycle Management capabilities to provision, update and deprovision AD accounts for your user identities.</p>
<p><strong>User Lifecycle Management</strong></p>
<p>For those that have a reliable HR system or another accurate employee data source, this process can be entirely automated with the Active Roles Synchronization Service. For those that don't, users can be managed <em>semi-automatically</em> via the Active Roles web interface. You can delegate appropriate access to those with the authority to create, update and de-provision user accounts and streamline the process by auto-generating certain attributes, restricting certain fields (like <em>department</em> or <em>title</em>) to a predefined list of options or automating additional provisioning tasks with workflows. So, even if manual provisioning is required, the entire process can be delegated and streamlined.</p>
<p><strong>Role-Based and Attribute-Based Access Controls</strong></p>
<p>Active Roles can automatically assign access to AD groups via <em>dynamic group membership.</em> This membership is calculated based on a query you configure and is updated automatically whenever a user's relevant attributes are changed. Based on group hierarchy and the query logic, this can enable both RBAC and ABAC.</p>
<p><strong>Administrative Access</strong></p>
<p>By "Administrative Access," I mean delegating responsibility to people within your organization to manage some degree of operations on users or objects. Active Roles is designed around its delegation model for AD, which allows you to grant permissions to people like HR, Help Desk staff and system owners to manage the users, groups or other objects they are responsible for.</p>
<p><strong>Summary</strong></p>
<p>For an AD-centric organization, Active Roles is a simpler, more lightweight approach to quickly get started with building an identity strategy when compared to the more laborious process of implementing IGA. It gets you from a state of little-to-no identity management into a state where you have automated lifecycle processes, clean and accurate user data, roles defined for users based on their attributes and a clear idea on who needs access to manage these users.</p>
<p>As your organization matures and your needs expand to include IGA capabilities, you already have a clear model in place to jumpstart that project. Or, in the case of Identity Manager, the direct integration with Active Roles can utilize much of what you've already built, allowing you to focus your implementation on other target systems.</p>
<p>Meanwhile, Active Roles is still utilized for the <em>other</em> functionality it offers that is either not possible in your IGA solution or not <em>rational</em> to do with IGA.</p>
<h3>IGA for Identities, Active Roles for Everything Else AD</h3>
<blockquote>
<p>We have an IGA solution. It already manages our Active Directory just fine. Why do I need this?</p>
</blockquote>
<p>For organizations that <em>already have</em> an IGA solution, or otherwise don’t need to manage the lifecycle of user AD accounts, the premise is this:</p>
<p>IGA covers your employees, contractors, vendors, etc. It creates their AD accounts with the appropriate access, updates their access upon role changes, access requests and attestations and de-provisions their account upon termination. However, managing AD requires much more than managing employee user accounts.</p>
<p><strong>AD Management Questions to Consider</strong></p>
<ul>
<li><p>Who’s responsible for and how are they currently managing the following: organizational units, groups, mailboxes, service accounts, computers, contacts, etc.?</p>
</li>
<li><p>Is everything structured in a way that makes sense for your business requirements?</p>
</li>
<li><p>Does access to AD objects follow a least privilege model? Remember, by default, everyone in your organization has full read access to the directory</p>
</li>
<li><p>Do all your other AD objects follow the standard practices that you've defined within your organization? Here are a few basic examples:</p>
<ul>
<li><p>Service Accounts</p>
<ul>
<li><p>All begin with SVC_</p>
</li>
<li><p>Have an owner, description and department assigned</p>
</li>
<li><p>Are set to “Password Never Expires”</p>
</li>
<li><p>Have a “Service Type” attribute set that is either “Server, Database, Application or Other,” and have a computer object assigned to the “Server” attribute if “Service Type” is set to “Server”</p>
</li>
</ul>
</li>
<li><p>Computers</p>
<ul>
<li><p>Are linked either to a user (for workstations) or an owner (for servers)</p>
</li>
<li><p>Have a “Cost Center” attribute that’s restricted based on a list populated by a data feed</p>
</li>
<li><p>Have an "Eligible for Refresh Date" attribute, which is auto-calculated based on the date they were created, and eligible computers are automatically available in a custom container where IT staff can see them</p>
</li>
</ul>
</li>
<li><p>AD Groups</p>
<ul>
<li><p>Have a primary and secondary owner who have the ability to manage attributes of that group and its memberships</p>
</li>
<li><p>Require approvals if anyone besides the owner changes the group memberships</p>
</li>
<li><p>Have an “Applications” attribute to denote which apps they grant access to</p>
</li>
</ul>
</li>
<li><p>Are you tracking unused objects and risky permissions and either automatically remediating those or delegating restricted access to manually remove them? For example:</p>
<ul>
<li><p>A team of three people has access to all computer objects that have not logged on in more than 90 days. They can read all properties, disable the object, change the owner and check/uncheck an "exception" that requires approval from an IT admin before they are removed from the list</p>
</li>
<li><p>Changes to domain admins, enterprise admins and other privileged groups require multi-step approval and trigger notifications to administrators. This membership is evaluated regularly and, where possible, access is granted via more fine-grained permissions</p>
</li>
<li><p>De-provisioned groups and user accounts, including service accounts, are automatically deleted after a retention period. Disabled objects that are <em>not</em> scheduled for deletion are regularly checked and remediated appropriately</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3>Enhanced Active Directory Governance</h3>
<blockquote>
<p>We have an IGA solution. It's not quite doing everything we need in Active Directory today, but it could with additional implementation. Why would we bring in a separate solution for that?</p>
</blockquote>
<p>Whether it’s due to time constraints, budgetary limitations, a lack of planning, or some combination thereof, IGA implementations rarely account for the entirety of the nuances of managing accounts in a complex enterprise AD environment. Too often, there are elements missing within role definitions, workflow processes, attribute generation rules, and so many other nuances that may, quite frankly, be a bit of a headache to architect in IGA, but are mandatory to achieve a healthy AD. We need to not only cover the previous scenario, where Active Roles governs the non-identity objects in Active Directory, but break the dichotomy and allow its functionality to supplement what's already being driven by IGA, enabling <a href="https://www.oneidentity.com/solutions/enhanced-active-directory-governance/">Enhanced Active Directory Governance</a>.</p>
<p><strong>Common Pitfalls of IGA Solutions with AD Account Lifecycle Management</strong></p>
<ul>
<li><p>Role definitions are too broad in scope, requiring manual assignment of hundreds of AD groups that could otherwise be assigned automatically by a more granular set of Attribute-Based Access Controls. The Dynamic Group functionality discussed earlier enables this easily, while still allowing IGA to governs the account by controlling the attribute data upon which the Dynamic Group engine operates.</p>
</li>
<li><p>Accounts do not flow in and out of all the appropriate OUs throughout their lifecycle, causing issues in reports, downstream automations, and Group Policy assignments. This often gets extra complex with employees transferring between subsidiaries, contractors becoming full time employees, or many of the vertical-specific complications like student workers. With Active Roles, simple Change Workflows can detect user account creations and attribute updates to place objects in their correct OUs throughout their entire lifecycle, bypassing the need to configure those logic flows in the IGA solution.</p>
</li>
<li><p>Certain attributes, especially multi-valued attributes with specific formatting expectations, are not being set correctly; others, especially custom schema attributes, are not being set at all. Some of those attributes combine multiple fields with complex logic that is then used for reporting purposes, but those are still being controlled by custom powershell scripts because it's a larger effort to define that with the IGA solution. Active Roles can define Provisioning Policies to enforce attribute values and naming conventions, or otherwise fully generate the values of any attributes with a simple-to-use rule engine that is purpose designed for AD.</p>
</li>
<li><p>Helpdesk staff, IT administrators, and even HR still regularly access AD directly to make changes to user accounts and other objects, often when immediate changes are required or synchronization errors occurred. Since this doesn't go through IGA, there is no enforcement around these changes or an audit trail for them. This returns to the topic of Administrative Access or Delegated Administration, where least-privileged permissions can be delegated to any staff who needs to manage objects in AD, and the same policies and workflows mentioned earlier can be used to enforce standards and naming conventions, prompt for approvals, automate tasks, and so much more, while all actions are logged in an audit trail.</p>
</li>
</ul>
<p><strong>Summary</strong></p>
<p>Active Roles enables you to delegate access to <em>any</em> user to make <em>only</em> the changes they need to in AD, streamlines the day-to-day management of AD and provides capabilities that native AD tools and IGA solutions don't offer.</p>
<p><em>Could</em> you build some of this in an IGA solution to meet your requirements? Sure, most IGA solutions are endlessly customizable. However, the effort involved would be extensive, the user experience would be more complicated and lacking and extending it to adapt to future requirements would be daunting. IGA solutions are <em>simply not designed</em> for directory management the way Active Roles is.</p>
<p>To stick with the "Swiss Army Knife" analogy: you can consider both IGA and Active Roles as multitools, but with different tools available. They both have a screwdriver, scissors and a file. However, IGA has a serrated knife and a bottle opener, while Active Roles has a straight blade and a can opener. Sure, you could use IGA's serrated knife to open a can, but it's going to be tedious, and you'll probably cut yourself a few times. The same applies the other way around. The straight blade could probably open a bottle, but I'm not going to try that when I have a bottle opener.</p>
<p>However, by combining both tools and using each where they make the most sense, you can achieve full governance of all your identities, their AD accounts, and all your other AD objects and eliminate all chaos from AD.</p>
<h1>External Links</h1>
<p>View this article elsewhere:</p>
<ul>
<li><a href="https://www.oneidentity.com/community/blogs/b/active-directory-management-and-security/posts/why-you-need-active-roles-even-if-you-have-iga">One Identity Blog</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Eliminate Compromised Passwords With One Identity Password Manager & Have I Been Pwned]]></title><description><![CDATA[Have I Been Pwned? Or rather, have you?
It's a good question, and if you're curious about whether any of your email addresses or passwords were included in a data breach, you can easily find out at HaveIBeenPwned.com. This entirely free service, mana...]]></description><link>https://blog.ajlindner.net/eliminate-compromised-passwords-with-one-identity-password-manager-have-i-been-pwned</link><guid isPermaLink="true">https://blog.ajlindner.net/eliminate-compromised-passwords-with-one-identity-password-manager-have-i-been-pwned</guid><category><![CDATA[passwords]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[AJ Lindner]]></dc:creator><pubDate>Fri, 17 Feb 2023 15:54:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676649304469/4f3cbbbe-3a71-4ff9-a822-e0f9a01efc06.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-have-i-been-pwned-or-rather-have-you">Have I Been Pwned? Or rather, have you?</h1>
<p>It's a good question, and if you're curious about whether any of your email addresses or passwords were included in a data breach, you can easily find out at <a target="_blank" href="https://haveibeenpwned.com/">HaveIBeenPwned.com</a>. This entirely free service, managed by <a target="_blank" href="https://www.troyhunt.com/">Microsoft Regional Director &amp; MVP Troy Hunt</a>, lets you enter an <a target="_blank" href="https://haveibeenpwned.com/">email address</a> or <a target="_blank" href="https://haveibeenpwned.com/Passwords">password</a> to see how many breaches it has been included in. For an email, it goes as far as informing you which breaches included your data, and you can check the <a target="_blank" href="https://haveibeenpwned.com/PwnedWebsites">"Who's been pwned"</a> page to get the full list of breaches included in the repository. If you want to go really crazy, you can download the entire pwned passwords list as a torrent, in SHA-1 or NTLM formats.</p>
<h2 id="heading-it-gets-better">It Gets Better</h2>
<p>Have I Been Pwned also includes a <a target="_blank" href="https://haveibeenpwned.com/API/v3">set of APIs</a> that you can use to programatically access data from the collection. The <a target="_blank" href="https://haveibeenpwned.com/API/v3#PwnedPasswords">PwnedPasswords endpoint</a> allows you to check if a Password appears in the pwned passwords list using a REST call. The best part is this is entirely free, with no rate limits or license requirements!</p>
<h2 id="heading-can-i-trust-this-site">Can I trust this site?</h2>
<p>Well, I'll leave that entirely up to you, but Troy is a highly respected security expert, and you can <a target="_blank" href="https://haveibeenpwned.com/About">read all about the Have I Been Pwned service</a>, <a target="_blank" href="https://haveibeenpwned.com/Privacy">how it handles privacy</a>, and <a target="_blank" href="https://haveibeenpwned.com/FAQs">what all this stuff means</a> directly on the website, as well as <a target="_blank" href="https://www.troyhunt.com/tag/have-i-been-pwned-3f/">tons of detailed blog posts on Troy's website</a>. The short answer is that this is a well-known, trusted, and secure service that's been used by organizations and government entities all around the world for years as another security layer to protect against attacks like <a target="_blank" href="https://blog.quest.com/password-spraying-credential-stuffing-brute-force-attacks-what-you-need-to-know/">Password Spraying and Credential Stuffing</a>. In the end, I'll just reiterate Troy's own words from the FAQ:</p>
<blockquote>
<p>The site is simply intended to be a free service for people to assess risk in relation to their account being caught up in a breach. As with any website, if you're concerned about the intent or security, don't use it.</p>
</blockquote>
<h1 id="heading-how-does-this-apply-to-me">How does this apply to me?</h1>
<p>Glad you asked. The short answer is we can use this service with One Identity Password Manager to ensure that the passwords your users are setting have not been compromised in a data breach!</p>
<p>I've <a target="_blank" href="https://blog.ajlindner.info/secure-password-resets-with-one-identity-password-manager-onelogin">talked before</a> about <a target="_blank" href="https://www.oneidentity.com/products/password-manager/">One Identity Password Manager</a>, and how configurable and customizable it is. One of the configurable options is to enable the "Credential Checker on" setting, which runs all passwords through a Powershell script before allowing users to set them. See where I'm going with this?</p>
<p>By default, this script utilizes a service called <a target="_blank" href="https://www.vericlouds.com/compromised-credentials/">CredVerify from VeriClouds</a>, which requires authentication. If you have, or can obtain, a URL, Client Key, and Client Secret for this service, you can simply plug them into the script and get going.</p>
<p>However, we can use Have I Been Pwned as an alternative, which is totally free, and has no authentication requirements or rate limiting for the PwnedPasswords API!</p>
<p>The full script, and install instructions, are available on <a target="_blank" href="https://github.com/OneIdentity/Password-Manager-PwnedPasswords-Checker-with-HIBP">GitHub</a>. You can simply replace the out-of-the-box script with the new one, enable the "Credential Checker on" setting, and you're good to go. Your Password Reset processes will now reject any passwords found in the HIBP database.</p>
<p>If that's all you need, head on over to GitHub and get going! If you're interested in the details of how this all works, keep reading.</p>
<h1 id="heading-exploring-the-pwnedpasswords-api">Exploring the PwnedPasswords API</h1>
<p>The first thing to get straight is that HIBP passwords are provided as <a target="_blank" href="https://en.wikipedia.org/wiki/SHA-1">SHA1 hashes</a>. Now if you're thinking <code>SHA1? Isn't that an unreliable algorithm these days?</code>, I'll let Troy speak for himself:</p>
<blockquote>
<p>It doesn't matter that SHA1 is a fast algorithm unsuitable for storing your customers' passwords with because that's not what we're doing here, it's simply about ensuring the source passwords are not immediately visible.</p>
</blockquote>
<p>When the <a target="_blank" href="https://www.troyhunt.com/introducing-306-million-freely-downloadable-pwned-passwords/">PwnedPasswords API was first launched</a>, you could query the API with the full SHA1 hash of the password to return any hits. However, <a target="_blank" href="https://www.troyhunt.com/ive-just-launched-pwned-passwords-version-2/">version 2</a> improved privacy (and speed) by introducing Cloudflare's k-Anonimity model. This model is still in use in the current version 3 of the API, and if you're still not convinced, have <a target="_blank" href="https://www.troyhunt.com/understanding-have-i-been-pwneds-use-of-sha-1-and-k-anonymity/">another Troy Hunt blog post</a> explaining the model in depth.</p>
<h2 id="heading-how-do-we-use-this-thing">How do we use this thing?</h2>
<p>In practice, the model for this API works by accepting a 5 character substring of the SHA-1 hash for a password, and returning a list with all matches, only containing the remaining substring of the hash. Sounds more complicated than it is, let's walk through it.</p>
<p>Take my incredibly secure password, "Password123". First, I need to compute the SHA-1 Hash of that password. With Powershell, that's simple enough.</p>
<pre><code class="lang-plaintext">PS C:\&gt; $PlaintextPassword = "Password123"
PS C:\&gt; $PasswordStream = [IO.MemoryStream]::new([byte[]][char[]]$PlaintextPassword)
PS C:\&gt; $HashedPassword = (Get-FileHash -InputStream $PasswordStream -Algorithm SHA1).Hash
PS C:\&gt; $HashedPassword
B2E98AD6F6EB8508DD6A14CFA704BAD7F05F6FB1
</code></pre>
<p>Now to..."k-Anonymize". We need to send the first 5 characters of the hash to HIBP, so let's call that the <code>$hashPrefix</code> and the remainder of the hash the <code>$hashSuffix</code>.</p>
<pre><code class="lang-plaintext">PS C:\&gt; $hashPrefix = $HashedPassword.Substring(0,5)
PS C:\&gt; $hashPrefix
B2E98
</code></pre>
<p>Great, now we can send that to the PwnedPasswords API to get a list of matches. But first, we need to ensure we are using at least TLS 1.2</p>
<pre><code class="lang-plaintext">PS C:\&gt; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
</code></pre>
<p>Now we can make our REST Web Request:</p>
<pre><code class="lang-plaintext">PS C:\&gt; $url = "https://api.pwnedpasswords.com/range/$hashPrefix"
PS C:\&gt; $HIBP = Invoke-RestMethod -Uri $url -Method GET -UseBasicParsing
</code></pre>
<p>If we inspect the $HIBP response, we'll see that it's a large string of newline-delimited results. Each of these results contains a <em>hash suffix</em> for a matching password beginning with our prefix, followed by a colon (:) and the count of how many times that password has appeared.</p>
<pre><code class="lang-plaintext">PS C:\&gt; $HIBP
004FAC2FA6779235D4D835A4B518D563F3F:3
00540184B698E09B3977E74434933FF1A6D:8
0078FBA31E1A8034F55AAB06C61337D377A:1
00D24723161C97D6C16B9139B1279DD7B53:2
01183CA5E4C40A960A98EC3F9DB4A705007:1
011969830985B5E941F7285B22393130EA0:1
0123A5B3069D0CA31210A184BB79927B9C9:64
012A94FB50CFC1267DEC3EE8C3826AA2405:3
01A148B7911D34BC9697D1FB203706D00BC:1
01E8A15747D1289B6E8D960008BC990C798:1
01FB7A423C3AD369B173E4F88EC836B1BA9:2
0283F368CB5A6850390AF940A4D79097637:4
02A5DB2458D4235579AED00A5D6304F6043:2
032BF92F00C1C365999BCE1F6B8A74403BD:1
045EB79206C8C42998D632FB0619542ABEB:1
...
</code></pre>
<p>For our purposes, we really only care about 1 thing. Is our original password hash in this list of breached passwords? To check, we need to standardize this response.</p>
<p>We first need to split this giant string into an array of strings, one item for each line. We can split on the newline character with <code>$HIBP.Split("`n")</code>. Then, we can loop through each of these lines and do 2 things.</p>
<ol>
<li><p>Split it on the colon (:) so we can parse out the <code>$hashSuffix</code> in the first index [0].</p>
</li>
<li><p>Append the original <code>$hashPrefix</code> to the beginning of the string.</p>
</li>
</ol>
<p>Finally, store the result of this in a nice <code>$HashMatches</code> array.</p>
<pre><code class="lang-plaintext">$HashMatches = ForEach ($result in $HIBP.Split("`n")) {
        $hashSuffix = $Result.Split(":")[0]
        "$hashPrefix$hashSuffix".ToUpper()
}

PS C:\&gt; $HashMatches
B2E98004FAC2FA6779235D4D835A4B518D563F3F
B2E9800540184B698E09B3977E74434933FF1A6D
B2E980078FBA31E1A8034F55AAB06C61337D377A
B2E9800D24723161C97D6C16B9139B1279DD7B53
B2E9801183CA5E4C40A960A98EC3F9DB4A705007
B2E98011969830985B5E941F7285B22393130EA0
B2E980123A5B3069D0CA31210A184BB79927B9C9
B2E98012A94FB50CFC1267DEC3EE8C3826AA2405
B2E9801A148B7911D34BC9697D1FB203706D00BC
B2E9801E8A15747D1289B6E8D960008BC990C798
B2E9801FB7A423C3AD369B173E4F88EC836B1BA9
B2E980283F368CB5A6850390AF940A4D79097637
B2E9802A5DB2458D4235579AED00A5D6304F6043
B2E98032BF92F00C1C365999BCE1F6B8A74403BD
B2E98045EB79206C8C42998D632FB0619542ABEB
B2E98049670AA6A430AE0911C189E8E456FF92E0
...
</code></pre>
<p>Great, we have a lovely array filled with hashes that begin with the same 5 characters as our password's hash. Now we just need to see if our password is in that array, and if so, return <code>$true</code>.</p>
<pre><code class="lang-plaintext">$PasswordLeaked = ($HashedPassword.ToUpper() -in $HashMatches)
Return $PasswordLeaked
</code></pre>
<p>And of course, we can wrap all this up in a cmdlet, let's call it <code>Confirm-PwnedPassword</code>. As part of that, it should also be able to support both a plaintext password and a SHA1 hash as options, just for flexibility. If it receives a plaintext password, it can perform the hashing function before processing.</p>
<pre><code class="lang-plaintext">function Confirm-PwnedPassword {

    [cmdletbinding()]
    param(
        [parameter(position=1,mandatory,ParameterSetName="Plaintext")]
        [string]
        $PlaintextPassword,

        [parameter(position=1,mandatory,ParameterSetName="Hash")]
        [string]
        $HashedPassword
    )

    if ($PSCmdlet.ParameterSetName -eq "Plaintext") {
        # Get &amp; Hash the entered password
        $PasswordStream = [IO.MemoryStream]::new([byte[]][char[]]$PlaintextPassword)
        $HashedPassword = (Get-FileHash -InputStream $PasswordStream -Algorithm SHA1).Hash
    }

# the rest of the cmdlet here
</code></pre>
<p>The full function can be found in a standalone <code>Confirm-PwnedPassword.ps1</code> script in the associated <a target="_blank" href="https://github.com/OneIdentity/Password-Manager-PwnedPasswords-Checker-with-HIBP">GitHub Repo</a>, along with all the other files for this project.</p>
<h1 id="heading-password-managers-built-in-credential-checker">Password Manager's Built-in Credential Checker</h1>
<p>We now have a nice cmdlet to check if a password appears in the PwnedPasswords database, so how do we get Password Manager to run that against a user's about-to-be-set password?</p>
<p>The out-of-the-box Password Manager Credential Checker runs a Powershell Script that comes included with the Password Manager installation. This script runs 2 functions with specific data passed in for the parameters. We just need to modify this script appropriately.</p>
<h2 id="heading-the-script">The Script</h2>
<p>With "Credential Checker On", any time a user tries to set a new password, it will first run this script against their username &amp; password to determine if that should be accepted.</p>
<p><code>Get-HashAlgorithm</code> returns a string for the hashing algorithm that Password Manager should use to hash the user's password. This defaults to <code>SHA1</code>, which is what we need for the PwnedPasswords API. Password Manager will hash the password using this algorithm before passing it into the following function.</p>
<p><code>Test-IsCompromisedCredential</code> takes the username of the user resetting their password, and the SHA-1 hash provided by Password Manager, and runs some code with those parameters. If this code returns <code>$true</code>, Password Manager will reject the password the user entered.</p>
<p>To make this work with the PwnedPasswords API, all we need to do is plug in our <code>Confirm-PwnedPassword</code> cmdlet, and call that inside <code>Test-IsCompromisedCredential</code>, instead of the default API call to CredVerify.</p>
<p>Putting this all together, first Password Manager will run <code>Get-HashAlgorithm</code>, which will return the string <code>SHA1</code>. Next, Password Manager will hash the about-to-be-set password using the SHA-1 algorithm. Finally, Password Manager will call <code>Test-IsCompromisedCredential</code>, passing in the username to the <code>$username</code> parameter, and the SHA1 hash for the <code>$passwordHash</code> parameter. If that returns <code>$true</code>, the password will be rejected, and the user will see an error message. Otherwise, the password will be accepted, allowing the workflow to continue.</p>
<p>Some solutions, like the default CredVerify, check the combination of username and password against their database. Since HaveIBeenPwned only needs the password, we can simply ignore the <code>$username</code> parameter.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>You now have another method of increasing your password security by ensuring your users can't set passwords that have been released or compromised as the result of a breach. If you're following NIST best practices for passwords, you'll know that this is one of the key principles:</p>
<blockquote>
<p>Compare the set password against the list of breached passwords (commonly used passwords).</p>
</blockquote>
<p>Take this a step further and combine this with a <a target="_blank" href="https://support.oneidentity.com/technical-documents/password-manager/5.11/administration-guide/76#TOPIC-1898788">Password Policy</a> that prioritizes length over complexity, restricts usage of particular AD Attributes in the password, and utilizes a curated dictionary. Even better, make sure the authentication process for your forgotten password process includes <a target="_blank" href="https://blog.ajlindner.info/secure-password-resets-with-one-identity-password-manager-onelogin">MultiFactor Authentication</a>.</p>
<p>As always, you can keep up with the latest code changes on <a target="_blank" href="https://github.com/AJLindner/Password-Manager-PwnedPasswords-Checker-with-HIBP">my personal GitHub</a> or grab the latest stable release on the <a target="_blank" href="https://github.com/OneIdentity/Password-Manager-PwnedPasswords-Checker-with-HIBP">One Identity GitHub</a>. Refer to the README for instructions.</p>
<h1 id="heading-one-identity-github-note">One Identity GitHub Note</h1>
<p>One Identity open source projects are supported through <a target="_blank" href="https://github.com/OneIdentity/OneIdentity-Password-Manager-PwnedPasswords-Checker/issues">One Identity GitHub issues</a> and the <a target="_blank" href="https://www.oneidentity.com/community/">One Identity Community</a>. This includes all scripts, plugins, SDKs, modules, code snippets or other solutions. For assistance with any One Identity GitHub project, please raise a new Issue on the <a target="_blank" href="https://github.com/orgs/OneIdentity/projects?query=is%3Aopen">One Identity GitHub project page</a>. You may also visit the <a target="_blank" href="https://www.oneidentity.com/community/">One Identity Community</a> to ask questions. Requests for assistance made through official One Identity Support will be referred back to GitHub and the One Identity Community forums where those requests can benefit all users.</p>
<h1 id="heading-external-links">External Links</h1>
<p>View this article elsewhere:</p>
<ul>
<li><a target="_blank" href="https://www.oneidentity.com/community/blogs/b/one-identity/posts/eliminate-compromised-passwords-with-password-manager-and-have-i-been-pwned">One Identity Blog</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Secure One Identity Password Manager with OneLogin for Administrators and Help Desk Personnel]]></title><description><![CDATA[Recently, I wrote about how you can add Multi-Factor Authentication to your Self-Service Password Resets with One Identity Password Manager and OneLogin.

Read it on the One Identity blog, One Login blog, or my personal blog

In that scenario, a user...]]></description><link>https://blog.ajlindner.net/secure-one-identity-password-manager-with-onelogin-for-administrators-and-help-desk-personnel</link><guid isPermaLink="true">https://blog.ajlindner.net/secure-one-identity-password-manager-with-onelogin-for-administrators-and-help-desk-personnel</guid><category><![CDATA[passwords]]></category><category><![CDATA[Security]]></category><category><![CDATA[MFA]]></category><category><![CDATA[Multi Factor Authentication]]></category><category><![CDATA[SSO]]></category><dc:creator><![CDATA[AJ Lindner]]></dc:creator><pubDate>Fri, 20 Jan 2023 18:31:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1674239346719/a7ebe6c4-f0dd-4c8a-9c00-69e6c760300a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently, I wrote about how you can add Multi-Factor Authentication to your Self-Service Password Resets with <a target="_blank" href="https://www.oneidentity.com/products/password-manager/">One Identity Password Manager</a> and <a target="_blank" href="https://www.onelogin.com/">OneLogin</a>.</p>
<blockquote>
<p>Read it on the <a target="_blank" href="https://www.oneidentity.com/community/blogs/b/active-directory-management-and-security/posts/secure-password-resets-password-manager-and-onelogin">One Identity blog</a>, <a target="_blank" href="https://www.onelogin.com/blog/secure-password-resets-with-one-identity-password-manager-onelogin">One Login blog</a>, or <a target="_blank" href="https://blog.ajlindner.info/secure-password-resets-with-one-identity-password-manager-onelogin">my personal blog</a></p>
</blockquote>
<p>In that scenario, a user with a forgotten or expired password authenticates to the self-service portal with a combination of their Security Questions and <a target="_blank" href="https://www.onelogin.com/learn/what-is-mfa">MFA</a> provided by OneLogin in order to reset their password.</p>
<p>With the release of <a target="_blank" href="https://support.oneidentity.com/technical-documents/password-manager/5.11/release-notes">Password Manager 5.11</a>, we can take this a step further by enabling MFA and/or Single Sign-On for Admins and Helpdesk staff accessing Password Manager using OneLogin, or any other IdP (Identity Provider) that supports standard protocols like SAML (Security Assertion Markup Language).</p>
<h1 id="heading-introducing-secure-token-server">Introducing Secure Token Server</h1>
<p>I'll spare you the details on what this is and keep it simple. rSTS is the same component used in other One Identity products, like <a target="_blank" href="https://www.oneidentity.com/products/one-identity-safeguard-for-privileged-passwords/">Safeguard for Privileged Passwords</a>, to provide federated authentication or multi-step authentication using various providers and protocols like <a target="_blank" href="https://www.onelogin.com/learn/saml">SAML</a>, OAuth, RADIUS, and more. This has now been brought over to Password Manager for use within workflows, and for authentication to the helpdesk and admin web interfaces.</p>
<p>The cybersecurity frameworks, cyber insurance companies, and consulting firms are all correctly on the same page — MFA should be required for access to any privileged application. The admin and helpdesk pages for Password Manager are no exception. Admins can configure the product to do whatever they desire to accounts on all the included domains. Helpdesk staff often have access to unlock or enable accounts, reset passwords, issue BitLocker recovery keys, and more. Enabling MFA as a requirement to access these resources is a logical step towards securing your password reset process.</p>
<h1 id="heading-options-options">Options, options...</h1>
<p>There are 2 supported methods of configuring federated authentication for the Password Manager Admin and Helpdesk pages, and since I love having options, I'll walk through them both.</p>
<ul>
<li><p><a target="_blank" href="https://blog.ajlindner.info/secure-one-identity-password-manager-with-onelogin-for-administrators-and-help-desk-personnel#heading-external-federation-sso">External Federation (SSO)</a></p>
</li>
<li><p><a target="_blank" href="https://blog.ajlindner.info/secure-one-identity-password-manager-with-onelogin-for-administrators-and-help-desk-personnel#heading-primary-directory-authentication-secondary-authentication">Primary Directory Authentication + Secondary Authentication</a></p>
</li>
</ul>
<h2 id="heading-external-federation-sso">External Federation (SSO)</h2>
<p>This is a common standards-based scenario where your external Identity Provider of choice acts as the authentication mechanism. This can be both Service-Provider Initiated — where a user navigates to the Password Manager admin or helpdesk portal and gets redirected to the IdP (Identity Provider) for authentication — and Identity-Provider Initiated — where a user signs in to the IdP and clicks an icon on their dashboard to SSO into Password Manager.</p>
<p>Let's use OneLogin as an example. Since it supports SAML2.0, I can create a SAML application called Password Manager, point it to the Password Manager STS (Secure Token Server), and configure Password Manager to use that application for authentication.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673302773864/ecba9ec5-5b8f-4ec8-9b14-dd91f8cee850.png" alt="OneLogin SAML Application for Password Manager (Info)" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673302856206/8d4272ce-6063-4ddc-ab9f-5a22d998abf5.png" alt="OneLogin SAML Application for Password Manager (Configuration)" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673304156003/51841410-e3f8-4cd5-8d18-522f01915617.png" alt class="image--center mx-auto" /></p>
<p>When I access Password Manager's Admin or Helpdesk pages, it will automatically redirect me to authenticate through OneLogin.</p>
<p>But we can take this a step further. OneLogin QuickLinks allow you to create custom applications that show up on the user's SSO Dashboard. These can simply be a URL that the link takes them to, with a custom name and icon to make it easy to identify. So, you can have a single SAML application to handle the authentication, and a QuickLink each for the Admin and Helpdesk pages, that can be assigned to users appropriately.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673303101333/edee3d52-8e48-45a0-a340-66f930a7eaae.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673303119691/19a2b24a-25b5-45e9-908e-d7acde4dffbd.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673303154127/fe1f3202-410d-41de-82ed-30ee0c2359e1.png" alt class="image--center mx-auto" /></p>
<p>When users sign in to their OneLogin Dashboard, they'll see these links if they are assigned:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1668105386248/19yaL4MeH.png" alt="image.png" /></p>
<p>Clicking the link will take them directly to the associated Password Manager URL. And, since they are already authenticated to OneLogin, they'll be automatically signed in.</p>
<h3 id="heading-right-but-what-about-the-mfa">Right, but what about the MFA?</h3>
<p>Of course, the user may already have to authenticate with a second factor when initially signing into their OneLogin dashboard. However, depending on your configuration, this may not be the case. Certain OneLogin Users may have a Security Policy that does <em>not</em> require a second factor when authenticating to their dashboard, or you may be using <a target="_blank" href="https://www.onelogin.com/product/smartfactor-authentication">OneLogin SmartFactor Authentication</a> to suppress the MFA prompt when a low-risk sign-in is detected. In order to ensure MFA is provided when accessing critical applications, regardless of how the user authenticates to their dashboard, OneLogin allows you to create application-specific security policies.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673303308697/7824f549-772b-418c-87f0-c4e228e06231.png" alt class="image--center mx-auto" /></p>
<p>These policies allow you to force an MFA prompt for specific applications, and can of course be configured to suppress that prompt for those users who already provided one in the last X minutes, to avoid multiple prompts in a row.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1673303320711/dd2afc21-a7b5-4aea-9264-a593cbab88d0.png" alt class="image--center mx-auto" /></p>
<p>With an Application Security Policy that requires MFA assigned to the Password Manager SAML application, we can ensure that users will <em>always</em> need to provide a second authentication factor in order to access the Password Manager Administration and Helpdesk pages.</p>
<h3 id="heading-what-about-other-idps">What about other IdPs?</h3>
<p>Other Identity Providers have their own processes for configuring SAML, OAuth, or WS-Fed authentication, but it's all the same to Password Manager. Even better, it can support multiple Identity Providers for different user groups federating from multiple domains. Keep in mind, however, that this scenario typically expects the Identity Provider to handle both the Primary &amp; Secondary authentication...but it doesn't have to!</p>
<h2 id="heading-primary-directory-authentication-secondary-authentication">Primary Directory Authentication + Secondary Authentication</h2>
<p>Our STS allows you to separately configure a primary and secondary authentication method from a choice of standard providers. Want to still have AD (Active Directory) Authentication but use a RADIUS server for MFA? No problem! How about LDAP (Lightweight Directory Access Protocol) &amp; Duo? That works too.</p>
<p>This scenario is more flexible for organizations who are not standardized to an IdP across the board or have existing standalone MFA solutions that only provide secondary authentication and rely on a primary authentication source like Active Directory.</p>
<h1 id="heading-summary">Summary</h1>
<p>Whether you're fully committed to the latest and greatest of security frameworks, fighting an uphill battle to implement any security controls you can, or balancing security and usability concerns anywhere in between, One Identity Password Manager offers configuration and extensibility options to help you design a secure password reset process that adheres to your unique requirements, without compromising the experience for your end users.</p>
<p>Requiring MFA for the privileged Admins and Helpdesk Users accessing Password Manager, and for the end users performing password resets, is one of the easiest first steps you can take towards securing the entire process.</p>
<h1 id="heading-external-links">External Links</h1>
<p>Read the first post in the series on Secure Password Resets with One Identity Password Manager:</p>
<ul>
<li><p><a target="_blank" href="https://www.oneidentity.com/community/blogs/b/active-directory-management-and-security/posts/secure-password-resets-password-manager-and-onelogin">One Identity Blog</a></p>
</li>
<li><p><a target="_blank" href="https://www.onelogin.com/blog/secure-password-resets-with-one-identity-password-manager-onelogin">One Login Blog</a></p>
</li>
<li><p><a target="_blank" href="https://blog.ajlindner.info/secure-password-resets-with-one-identity-password-manager-onelogin">My Personal Blog</a></p>
</li>
</ul>
<p>View this article elsewhere:</p>
<ul>
<li><p><a target="_blank" href="https://www.onelogin.com/blog/secure-one-identity-password-manager-with-onelogin">One Login Blog</a></p>
</li>
<li><p><a target="_blank" href="https://www.oneidentity.com/community/blogs/b/active-directory-management-and-security/posts/secure-one-identity-password-manager-with-onelogin-for-administrators-and-help-desk-personnel">One Identity Blog</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Secure Password Resets with One Identity Password Manager & OneLogin]]></title><description><![CDATA[Introduction to Secure Password Resets
As a Solutions Architect, the best part of my job is finding ways to make our products do what our customers want them to do...even when they don't exactly do that. So, when One Identity acquired OneLogin last O...]]></description><link>https://blog.ajlindner.net/secure-password-resets-with-one-identity-password-manager-onelogin</link><guid isPermaLink="true">https://blog.ajlindner.net/secure-password-resets-with-one-identity-password-manager-onelogin</guid><category><![CDATA[passwords]]></category><category><![CDATA[sdk]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Powershell]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[AJ Lindner]]></dc:creator><pubDate>Wed, 17 Aug 2022 17:55:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660744206562/XcvVUdA_D.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-introduction-to-secure-password-resets">Introduction to Secure Password Resets</h1>
<p>As a Solutions Architect, the best part of my job is finding ways to make our products do what our customers want them to do...even when they don't exactly do that. So, when <a target="_blank" href="https://www.oneidentity.com/community/partners/b/blog/posts/one-identity-acquires-onelogin-to-deliver-on-its-vision">One Identity acquired OneLogin</a> last October, we entered an exciting interim period—a time during which our products would not have native, built in, fully-supported integration, but one in which we would soon be <em>selling</em> integration, and customers would be asking to see integration.</p>
<p>So began a mad dash to <a target="_blank" href="https://youtu.be/lIFE7h3m40U">configure, script, and pull</a> together all the integrations we could feasibly manage--Single Sign-On into everything (Active Roles, Safeguard, Identity Manager) via native federation support (SAML2, WS-FED), lifecycle management of OneLogin accounts from Identity Manager via the API, <a target="_blank" href="https://www.onelogin.com/blog/onelogin-and-device-level-multi-factor-authentication-mfa">device-level MFA using One Identity Defender</a> (<strong>major</strong> kudos to Eric Hibar Jr. for that one). And, the topic of this blog post, OneLogin as a Multifactor Authentication step during a Self-Service Password Reset (or really ANY workflow) in One Identity Password Manager.</p>
<h1 id="heading-one-identity-password-manager">One Identity Password Manager</h1>
<p>For those unfamiliar with <a target="_blank" href="https://www.oneidentity.com/products/password-manager/">Password Manager</a> (PWM), it's a secure enterprise Self-Service Password Reset (SSPR) tool. What's particularly relevant here is that PWM is highly configurable and customizable, with a drag-and-drop interface for building end-user workflows, and custom activities built with PowerShell (my favorite!) and an in-depth SDK.</p>
<p>In short, you can customize the entire process an end-user goes through to do <em>anything</em> in PWM. In particular, we'll focus on a secure Password Reset.</p>
<h1 id="heading-onelogin-by-one-identity">OneLogin by One Identity</h1>
<p>For those unfamiliar with <a target="_blank" href="https://www.onelogin.com/">OneLogin</a>, it is a Market-Leading Identity &amp; Access Management platform, providing SSO, MFA, Unified Directory, User Lifecycle Management, and so much more.</p>
<p>For this integration, we will focus on <a target="_blank" href="https://www.onelogin.com/product/multi-factor-authentication">Multi-Factor Authentication (MFA)</a> to include as part of a PWM workflow.</p>
<h1 id="heading-sidebar-standards-based-authentication-radius">Sidebar: Standards-Based Authentication (RADIUS)</h1>
<p>There's a reason I'm calling this "API-Based" MFA, and not just "MFA" or "OneLogin Integration" — RADIUS. PWM natively supports the RADIUS protocol to provide multifactor authentication in any workflow. And, of course, <a target="_blank" href="https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010425">OneLogin includes a RADIUS server</a> that PWM can authenticate against. Since Day 1 (okay...maybe day 7) of our OneLogin acquisition, we've been able to demonstrate and support this scenario.</p>
<blockquote>
<p>But there are limitations.</p>
</blockquote>
<ol>
<li><p>RADIUS only works with TOTP or Push-based Security Factors in OneLogin.</p>
<ul>
<li><p>OneLogin Protect</p>
</li>
<li><p>Authenticator (TOTP-based)</p>
</li>
<li><p>RADIUS Token</p>
</li>
</ul>
</li>
<li><p>RADIUS only works for your <em>primary</em> Security Factor in OneLogin. You cannot select a different factor.</p>
</li>
<li><p>RADIUS configuration &amp; customization options in PWM are limited.</p>
<ul>
<li><p>There can only be 1 RADIUS provider configured for a PWM instance, that applies across the entire user base.</p>
</li>
<li><p>Customizing the text on the RADIUS action requires modifying an underlying .xml file, and therefore needs to be carried over and accounted for during upgrades</p>
</li>
<li><p>There is no SDK method for executing a RADIUS authentication with the stored RADIUS configuration, so a custom action cannot be built without implementing your own RADIUS authentication via PowerShell</p>
</li>
</ul>
</li>
</ol>
<p>Now, One Identity used to have an in-house MFA Solution, <a target="_blank" href="https://www.oneidentity.com/products/starling-two-factor-authentication/">Starling 2FA</a>, that had native support in PWM for auth via an Android &amp; iOS app, as well as SMS, Email, and Voice. RADIUS by definition cannot support all of these features...but OneLogin can, with its <a target="_blank" href="https://developers.onelogin.com/api-docs/1/getting-started/dev-overview">REST API</a>.</p>
<h1 id="heading-my-over-zealous-plan">My Over-Zealous Plan</h1>
<p>Before I even read the documentation of the OneLogin API, one of my talented colleagues in EMEA shared a set of scripts to do...well...exactly this. Use OneLogin for MFA in PWM. But also create users, register new Security Factors...really a whole dev kit of useful sample scripts (some more useful and relevant than others) that immediately grabbed my attention.</p>
<p>Now, my initial reaction was not to pop this into my lab and call it a day, or just to refactor it to fit the <a target="_blank" href="https://github.com/PoshCode/PowerShellPracticeAndStyle">Unofficial PowerShell Style Guide</a> (which, let's be honest...I rarely follow completely). It was "hey, pretty much all of our products support PowerShell for extensibility, it would be REALLY cool if there was a PowerShell Module SDK that wrapped the OneLogin API!</p>
<blockquote>
<p><a target="_blank" href="https://developers.onelogin.com/api-docs/2/getting-started/client-sdks">There was not</a></p>
</blockquote>
<p>So, I thought <em>"I can write that,"</em> and started working on what would be my first major PowerShell Module.</p>
<p>Perhaps I focused too much on trying to do it <em>proper</em>, and <em>official</em> or whatever, but after dumping tons of time and effort into the development with nothing to publicly share, I realized my scope was a bit large to start, at least for an "as I get the time during work hours" side project.</p>
<p>After getting the framework of an SDK, and wrapping enough endpoints to process MFA requests, I shifted focus to making this work <em>seamlessly</em> with Password Manager.</p>
<h1 id="heading-introducing">Introducing...</h1>
<h2 id="heading-password-manager-api-based-mfa-with-oneloginhttpsgithubcomoneidentityoneidentity-password-manager-onelogin-integration"><a target="_blank" href="https://github.com/OneIdentity/OneIdentity-Password-Manager-OneLogin-Integration">Password Manager: API-Based MFA with OneLogin</a></h2>
<p>I am excited to release this project, which allows you to utilize the OneLogin REST API to provide flexible, secure Multifactor Authentication capabilities to Password Manager Workflows, without the limitations of the RADIUS protocol.</p>
<p>Take advantage of PWM's extensibility, and OneLogin's powerful REST API to support a wide range of Security Factors, so your users can authenticate the way they prefer:</p>
<ul>
<li><p>OneLogin Protect</p>
</li>
<li><p>Voice</p>
</li>
<li><p>SMS</p>
</li>
<li><p>Email OTP &amp; Magic Link</p>
</li>
<li><p>TOTP-based Authenticators (e.g. Microsoft, Google)</p>
</li>
</ul>
<p>The included <code>OneLoginByOneIdentity</code> Powershell Module takes care of all the necessary steps to interact with the API, so the PWM Actions can focus on the logic. This "early stages" SDK can also be used to streamline other OneLogin automations.</p>
<p>By utilizing features of the PWM SDK, the UI is generated by the code; no UI elements need to be created manually.</p>
<p>Sample exports of the actions, and an example authentication workflow, are included in the repository for ease of deployment.</p>
<p>Keep up with progress on <a target="_blank" href="https://github.com/AJLindner/OneIdentity-Password-Manager-OneLogin-Integration">my personal Github</a>, or grab the latest stable release on the <a target="_blank" href="https://github.com/OneIdentity/OneIdentity-Password-Manager-OneLogin-Integration">One Identity Github</a>.</p>
<p>Refer to the README for instructions.</p>
<h1 id="heading-summary">Summary</h1>
<p>The initial purpose of this integration was to provide end users with a smoother experience when authenticating with MFA to reset their passwords. However, this same process can also be utilized by helpdesk staff when verifying the identities of users who need assistance.</p>
<p>Typically when a user contacts the helpdesk, a helpdesk staff member can run a workflow in Password Manager to verify that user’s identity based on the answers to their “helpdesk-only” security questions. Password Manager also natively supports the use of RADIUS MFA as part of this process to allow helpdesk staff to request an OTP from the end user as well. The OneLogin API-Based MFA Solution works in the same way! Including this in a Helpdesk Workflow will prompt the helpdesk staff member to select a Security Factor from the user’s list, and prompt the user for authentication. This can of course be combined with Push Authentication using the OneLogin Protect App so the helpdesk staff member never has to receive an OTP.</p>
<p>Combining this all together allows users to experience a seamless process for authenticating with OneLogin both when resetting their password, and when contacting the helpdesk for assistance.</p>
<h1 id="heading-one-identity-github-note">One Identity Github Note</h1>
<p>One Identity open source projects are supported through <a target="_blank" href="https://github.com/OneIdentity/OneIdentity-Password-Manager-OneLogin-Integration/issues">One Identity GitHub issues</a> and the <a target="_blank" href="https://www.oneidentity.com/community/">One Identity Community</a>. This includes all scripts, plugins, SDKs, modules, code snippets or other solutions. For assistance with any One Identity GitHub project, please raise a new Issue on the <a target="_blank" href="https://github.com/OneIdentity/OneIdentity-Password-Manager-OneLogin-Integration">One Identity GitHub project page</a>. You may also visit the <a target="_blank" href="https://www.oneidentity.com/community/">One Identity Community</a> to ask questions. Requests for assistance made through official One Identity Support will be referred back to GitHub and the One Identity Community forums where those requests can benefit all users.</p>
<h1 id="heading-external-links">External Links</h1>
<p>View the original post on the <a target="_blank" href="https://www.onelogin.com/blog/secure-password-resets-with-one-identity-password-manager-onelogin">OneLogin Blog</a> or the upload on the <a target="_blank" href="https://www.oneidentity.com/community/blogs/b/active-directory-management-and-security/posts/secure-password-resets-password-manager-and-onelogin">One Identity Blog</a></p>
]]></content:encoded></item></channel></rss>