<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Microsoft-Graph on Nicola Suter</title><link>https://nicolasuter.ch/tags/microsoft-graph/</link><description>Recent content in Microsoft-Graph on Nicola Suter</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><copyright>© 2026 Nicola Suter</copyright><lastBuildDate>Tue, 14 Jul 2020 00:00:00 +0000</lastBuildDate><atom:link href="https://nicolasuter.ch/tags/microsoft-graph/rss.xml" rel="self" type="application/rss+xml"/><item><title>Azure AD guest user review solution</title><link>https://nicolasuter.ch/azure-ad-guest-user-review-solution/</link><pubDate>Tue, 14 Jul 2020 00:00:00 +0000</pubDate><guid>https://nicolasuter.ch/azure-ad-guest-user-review-solution/</guid><description>&lt;p&gt;Azure Active Directory guest users really simplify the process to collaborate with external users. Although keeping a good governance on guest accounts can become quite a challenge.
The two biggest challenges I often observe are: &lt;em&gt;&amp;ldquo;Who invited that guest user?&amp;rdquo;&lt;/em&gt; and &lt;em&gt;&amp;ldquo;Does this guest user still need access to our infrastructure?&amp;rdquo;&lt;/em&gt;. Inspired by a recent post of Thomas Kurth regarding &lt;a href="https://www.wpninjas.ch/2020/06/azure-ad-guest-account-governance-and-cleanup/" target="_blank" rel="noreferrer"&gt;Azure AD Guest Account - Governance and Cleanup&lt;/a&gt; I also developed a solution which comes quite close to an &amp;ldquo;Azure AD Access review&amp;rdquo; like user experience.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Notable features
 &lt;div id="notable-features" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#notable-features" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The &amp;lsquo;Manager&amp;rsquo; attribute of your guest users get&amp;rsquo;s automatically populated with the identity of the inviter&lt;/li&gt;
&lt;li&gt;All Azure AD app registration information is stored in Azure Key Vault&lt;/li&gt;
&lt;li&gt;Almost zero touch deployment with ARM templates&lt;/li&gt;
&lt;li&gt;You can integrate existing guest users into this solution by populating the manager attribute in Azure AD&lt;/li&gt;
&lt;li&gt;You can configure the approval frequency for guest accounts&lt;/li&gt;
&lt;li&gt;Approval frequency respects last approval date for each guest account&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Architecture
 &lt;div id="architecture" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#architecture" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://nicolasuter.ch/content/images/2020/07/AzureADGuestReview-AzScheme.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Azure AD Guest User Review"
 src="https://nicolasuter.ch/content/images/2020/07/AzureADGuestReview-AzScheme.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The solution leverages function of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Azure Logic App&lt;/p&gt;</description></item><item><title>Exploring the new Microsoft Graph PowerShell Module(s)</title><link>https://nicolasuter.ch/exploring-the-new-microsoft-graph-powershell-modules/</link><pubDate>Tue, 12 May 2020 00:00:00 +0000</pubDate><guid>https://nicolasuter.ch/exploring-the-new-microsoft-graph-powershell-modules/</guid><description>&lt;p&gt;Microsoft is working on a new set of PowerShell modules grouped under the umbrella of &lt;a href="https://github.com/microsoftgraph/msgraph-sdk-powershell" target="_blank" rel="noreferrer"&gt;Microsoft.Graph&lt;/a&gt; that will (hopefully) cover all the Microsoft Graph resources available. I&amp;rsquo;ve already used some of them for my &lt;a href="https://github.com/nicolonsky/ConditionalAccessDocumentation" target="_blank" rel="noreferrer"&gt;Conditional Access Documentation Script&lt;/a&gt; and thought they have some notable features worth sharing.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Advantages and changes
 &lt;div id="advantages-and-changes" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#advantages-and-changes" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The Microsoft Graph modules use the new Microsoft Authentication Library (MSAL) instead of the old Azure AD Authentication Library (ADAL). The MSAL library in the modules implements a token cache which persists the access and refresh tokens.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;MSAL caches a token after it has been acquired. Application code should try to get a token silently (from the cache), first, before acquiring a token by other means. - &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-acquire-cache-tokens" target="_blank" rel="noreferrer"&gt;Microsoft docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;The token cache persists system reboots and re-opening PowerShell sessions. The module allows you to obtain tokens either for authentication via &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#client-credentials" target="_blank" rel="noreferrer"&gt;client credentials&lt;/a&gt; (certificate only) or &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code" target="_blank" rel="noreferrer"&gt;device code flow&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Furthermore, the new modules support a really broad spectrum of available entities on the Graph API. From an EM+S perspective this means for example: groups, users, identity protection, conditional access, and some of the Intune app management commands are also starting to appear.&lt;/p&gt;
&lt;p&gt;Just be aware that the modules are currently published as pre-release. If you encounter any issues share them with the development team on GitHub and submit issues or even better contribute directly to the project.&lt;/p&gt;</description></item><item><title>Validating a GUID with PowerShell</title><link>https://nicolasuter.ch/validating-a-guid-with-powershell/</link><pubDate>Tue, 05 May 2020 00:00:00 +0000</pubDate><guid>https://nicolasuter.ch/validating-a-guid-with-powershell/</guid><description>&lt;p&gt;For some recent Microsoft Graph scripts I wanted to translate some Azure AD Object ID / GUID entries to their respective display name. The array with the GUID&amp;rsquo;s contained already some readable text. Of course I only wanted to translate the GUID entries with according Graph API requests. Otherwise the Graph requests would fail. Google offered only some fancy regex functions and helpers but I had that .NET function in my mind which looks much nicer compared to whatever regex pattern that I don&amp;rsquo;t understand.&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;applications&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;includeApplications&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;797f4846-ba00-4fd7-ba43-dac1f8f63013&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;Office365&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So I needed a way to test a string for a valid GUID and only invoking the Graph calls for GUID values.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Matching a GUID with a regex
 &lt;div id="matching-a-guid-with-a-regex" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#matching-a-guid-with-a-regex" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;I found the following regex on &lt;a href="https://pscustomobject.github.io/powershell/functions/PowerShell-Validate-Guid-copy" target="_blank" rel="noreferrer"&gt;this site&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;d815c3bc-9c49-4633-9d16-29808242d063&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;-match&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;Matching a GUID with the .NET method
 &lt;div id="matching-a-guid-with-the-net-method" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#matching-a-guid-with-the-net-method" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Instead of the complex regex we can invoke this nice .NET member method which returns true or false based on the input:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;guid&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;TryParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;d815c3bc-9c49-4633-9d16-29808242d063&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vm"&gt;$&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="no"&gt;ref][guid&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I guess that&amp;rsquo;s much more convenient.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Helper Function
 &lt;div id="helper-function" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#helper-function" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s a helper function which can be used in PowerShell scripts:&lt;/p&gt;</description></item><item><title>Document Conditional Access Configuration with my Modern Workplace Concierge</title><link>https://nicolasuter.ch/document-conditional-access-configuration/</link><pubDate>Mon, 20 Apr 2020 19:22:33 +0000</pubDate><guid>https://nicolasuter.ch/document-conditional-access-configuration/</guid><description>&lt;p&gt;Documenting things sucks. If it involves a lot of klick(edi klack klack) in portals and copying information around even more. But there&amp;rsquo;s hope. And it&amp;rsquo;s called automation. For the Intune part Thomas Kurt did already an awesome job with his &lt;a href="https://github.com/ThomasKur/IntuneDocumentation" target="_blank" rel="noreferrer"&gt;IntuneDocumentation&lt;/a&gt;.  Now the &lt;a href="https://mwconcierge.azurewebsites.net/" target="_blank" rel="noreferrer"&gt;Modern Workplace Concierge&lt;/a&gt; is ready to help you with documenting your Conditional Access configuration. I promise you: we will get through this within under 15 minutes! Afterwards you can make an impression on your fellow Enterprise Mobility teammates.&lt;/p&gt;

&lt;h3 class="relative group"&gt;What&amp;rsquo;s inside?
 &lt;div id="whats-inside" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#whats-inside" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;A Conditional Access policy is returned by the Microsoft Graph API in the following JSON representation:&lt;/p&gt;
&lt;pre&gt;
&lt;code&gt;
{
 "id": "714b5737-5f13-415e-bf96-d659f3a5928e",
 "displayName": "PROD - Admin protection - Azure management: Require MFA",
 "createdDateTime": null,
 "modifiedDateTime": null,
 "state": "enabled",
 "grantControls": {
 "operator": "OR",
 "builtInControls": [
 "mfa"
 ],
 "customAuthenticationFactors": [],
 "termsOfUse": []
 },
 "conditions": {
 "signInRiskLevels": [],
 "clientAppTypes": [],
 "platforms": null,
 "locations": null,
 "deviceStates": null,
 "applications": {
 "includeApplications": [
 "797f4846-ba00-4fd7-ba43-dac1f8f63013"
 ],
 "excludeApplications": [],
 "includeUserActions": []
 },
 "users": {
 "includeUsers": [
 "All"
 ],
 "excludeUsers": [],
 "includeGroups": [],
 "excludeGroups": [
 "04988d96-ad01-4569-9aee-a199a1cb4f8e"
 ],
 "includeRoles": [],
 "excludeRoles": []
 }
 },
 "sessionControls": null
}
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s not really human readable. Especially the object id&amp;rsquo;s  (32 character UUIDs) make it difficult to guess to which users or apps a policy is assigned. But an API has definitely other goals than showing pretty formatted reports.&lt;/p&gt;</description></item><item><title>Connecting to foreign Intune tenants with Microsoft Graph and PowerShell</title><link>https://nicolasuter.ch/connecting-to-foreign-intune-tenants-with-microsoft-graph-and-powershell/</link><pubDate>Thu, 09 Jan 2020 13:25:02 +0000</pubDate><guid>https://nicolasuter.ch/connecting-to-foreign-intune-tenants-with-microsoft-graph-and-powershell/</guid><description>&lt;p&gt;If you manage multiple Intune tenants with your Azure AD account (invited as guest in the foreign tenant) we need a way to specify the tenant id we want to connect. Otherwise you will land in your home-tenant every time. This posts shows you how to accomplish that with the &lt;a href="https://github.com/microsoft/Intune-PowerShell-SDK" target="_blank" rel="noreferrer"&gt;Intune PowerShell SDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If we have a look at the default Graph settings in a PowerShell session with the Intune PowerShell SDK you will notice that all authentication requests will land on the /common endpoint.&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Get-MSGraphEnvironment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;AuthUrl&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;microsoftonline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;common&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ResourceId&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GraphBaseAddress&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;AppId&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;d1ddf0e4-d672&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;4dae-b554&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;9d5bdfd93547&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RedirectLink&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urn&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ietf&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;oauth&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;oob&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SchemaVersion&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To connect to a specific tenant we need to update the AuthUrl to contain the tenant id or any registered domain name of the target tenant before connecting:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Update-MSGraphEnvironment&lt;/span&gt; &lt;span class="n"&gt;-AuthUrl&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://login.microsoftonline.com/nicolonsky.ch&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Afterewards you can connect to Microsoft Graph as usual:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Connect-MSGraph&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;```&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Happy&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt; &lt;span class="nb"&gt;Graph-ing&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;multiple&lt;/span&gt; &lt;span class="n"&gt;tenants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description></item><item><title>Have you already started with Intune automation and Microsoft Graph?</title><link>https://nicolasuter.ch/getting-started-with-workplace-automation/</link><pubDate>Thu, 19 Dec 2019 21:16:47 +0000</pubDate><guid>https://nicolasuter.ch/getting-started-with-workplace-automation/</guid><description>&lt;p&gt;This post has the intention to give you an overview and starting point to automate things with the Microsoft Graph API and PowerShell. While having the focus on Intune and EM+S but the basics are also valid for other Microsoft services.&lt;/p&gt;

&lt;h3 class="relative group"&gt;The world is changing and so are you?
 &lt;div id="the-world-is-changing-and-so-are-you" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-world-is-changing-and-so-are-you" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;When talking about automation most people only think about some PowerShell code and scheduled tasks running on whatever box in an environment. But technology regarding Microsoft services and it&amp;rsquo;s automation possibilities have definitely evolved quickly. Automation can now be done with basically any scripting or programming language because Microsoft offers us the Microsoft Graph API. Although API (application program interface) sounds more like a developer term engineers should better get used to consuming API&amp;rsquo;s. As more and more services can be consumed as SaaS API&amp;rsquo;s are mostly offered for further data processing and automation.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Microsoft Graph API
 &lt;div id="microsoft-graph-api" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#microsoft-graph-api" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Microsoft describes it&amp;rsquo;s own Graph API as &amp;ldquo;Microsoft Graph is the gateway to data and intelligence in Microsoft 365&amp;rdquo;. Most of the API&amp;rsquo;s out there are built according the RESTful definition. A RESTful, also called REST API should implement the following operations (HTTP methods) to work with data:&lt;/p&gt;</description></item><item><title>Application based authentication with the Intune PowerShell SDK using a certificate</title><link>https://nicolasuter.ch/azure-ad-application-based-authentication-with-intune-using-certificate/</link><pubDate>Tue, 10 Dec 2019 15:43:58 +0000</pubDate><guid>https://nicolasuter.ch/azure-ad-application-based-authentication-with-intune-using-certificate/</guid><description>&lt;p&gt;As you might have noticed I have been doing quite a lot of automation stuff with Microsoft Graph for Intune and Azure AD. My preferred way to run PowerShell scripts which need to run on a regular basis is to use Azure automation. Unfortunately the official &amp;ldquo;Intune-PowerShell-SDK&amp;rdquo; does not support authentication with a client certificate. Therefore I updated the module and will show you how to use it with Azure automation.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Why I don&amp;rsquo;t like client secrets
 &lt;div id="why-i-dont-like-client-secrets" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#why-i-dont-like-client-secrets" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Azure automation brings us service principals (run as accounts) which simplify the access to Azure resources by providing an Azure AD app registration and certificates to authenticate against Azure AD. This provides more security and prevents the risk from having client secrets stored as plain text in scripts. Going with a client secret when having a nice certificate based authentication solution in place feels like making a step-backwards for me. This was the main reason why I decided to &amp;ldquo;upgrade&amp;rdquo; the Intune-PowerShell-SDK to support certificate based authentication.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Why I love the Intune-PowerShell-SDK
 &lt;div id="why-i-love-the-intune-powershell-sdk" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#why-i-love-the-intune-powershell-sdk" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;This PowerShell SDK provides nice Cmdlets to do any kind of automation with Microsoft Graph, not only limited to Intune because it offers a helper cmdlets like:&lt;/p&gt;</description></item><item><title>Intune export uploaded PowerShell scripts</title><link>https://nicolasuter.ch/view-and-export-uploaded-intune-powershell-scripts/</link><pubDate>Wed, 09 Oct 2019 16:36:57 +0000</pubDate><guid>https://nicolasuter.ch/view-and-export-uploaded-intune-powershell-scripts/</guid><description>&lt;p&gt;After you have uploaded a PowerShell script to the Intune portal you won&amp;rsquo;t be able to view the script or its content. Therefore things become complicated when an Intune tenant is managed by multiple admins and someone wants to update or review a script. In addition to the unknown script content things can go from bad to worse if you can&amp;rsquo;t find the script anymore. Fortunately we can recollect our PowerShell scripts directly from the Microsoft Graph API.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Taking advantage of the Intune-PowerShell-SDK
 &lt;div id="taking-advantage-of-the-intune-powershell-sdk" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#taking-advantage-of-the-intune-powershell-sdk" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/Intune-PowerShell-SDK#one-time-setup-powershell-gallery" target="_blank" rel="noreferrer"&gt;Install the Intune-PowerShell-SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/Intune-PowerShell-SDK#before-this-module-is-used-in-your-organization" target="_blank" rel="noreferrer"&gt;Consent MS Graph App registration&lt;/a&gt; if not done yet (uses default Microsoft Intune PowerShell App with ID: d1ddf0e4-d672-4dae-b554-9d5bdfd93547 )&lt;/li&gt;
&lt;li&gt;Execute the snippet below&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 class="relative group"&gt;Retrieve device configuration - PowerShell scripts
 &lt;div id="retrieve-device-configuration---powershell-scripts" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#retrieve-device-configuration---powershell-scripts" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;!--kg-card-begin: markdown--&gt;&lt;script src="https://gist.github.com/nicolonsky/80c4d36d29999a15dd79ddb271ebd48f.js"&gt;&lt;/script&gt;&lt;!--kg-card-end: markdown--&gt;

&lt;h2 class="relative group"&gt;Final words
 &lt;div id="final-words" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#final-words" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;This was more a minimalistic self-serving post instead of a good explained one but it hopefully helps you if in need to export your PowerShell scripts in Intune without reinventing the wheel.&lt;/p&gt;</description></item><item><title>Calling the Microsoft Graph API via PowerShell without a user</title><link>https://nicolasuter.ch/calling-the-microsoft-graph-api/</link><pubDate>Mon, 17 Jun 2019 18:47:47 +0000</pubDate><guid>https://nicolasuter.ch/calling-the-microsoft-graph-api/</guid><description>&lt;p&gt;A colleague recently asked me how to access the Microsoft Graph API using PowerShell without specifying his user account or credentials. So here&amp;rsquo;s a little post about the required configuration to authenticate against the OAuth 2.0 endpoint of Azure AD with an app registration. This is especially useful for automation services like Azure automation.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nicolasuter.ch/calling-the-microsoft-graph-api/#powershell-template" &gt;At the end of this post you&amp;rsquo;ll find a PowerShell template.&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Gather application information
 &lt;div id="gather-application-information" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#gather-application-information" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Create a new client secret for your app and note down the following values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Client Secret&lt;/li&gt;
&lt;li&gt;Application ID (client ID)&lt;/li&gt;
&lt;li&gt;Directory ID (tenant ID)&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="kg-card kg-image-card kg-card-hascaption"&gt;&lt;img src="https://nicolasuter.ch/content/images/2019/06/image-1.png" class="kg-image"&gt;&lt;figcaption&gt;Azure AD App registration&lt;/figcaption&gt;&lt;/figure&gt;
## PowerShell code

&lt;h3 class="relative group"&gt;Request authentication token
 &lt;div id="request-authentication-token" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#request-authentication-token" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;In order to use the Graph API we need an authentication token. The information we gathered before is now sent to the Azure AD OAuth 2.0 endpoint.&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://login.microsoftonline.com/{TenantID}/oauth2/v2.0/token&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In the request supply a body with the following content:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;8f9f420d-606c-4e13-889e-837072dbfb42&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BlaBlaExampleSecret&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;#Generated secret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://graph.microsoft.com/.default&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grant_type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;client_credentials&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;em&gt;scope&lt;/em&gt; and &lt;em&gt;grant_type&lt;/em&gt; are required attributes. A full example looks like:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;8f9f420d-606c-4e13-889e-837072dbfb42&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BlaBlaExampleSecret&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://graph.microsoft.com/.default&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grant_type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;client_credentials&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$tenantId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;7955e1b3-cbad-49eb-9a84-e14aed7f3400&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Invoke-WebRequest&lt;/span&gt; &lt;span class="n"&gt;-Uri&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://login.microsoftonline.com/&lt;/span&gt;&lt;span class="nv"&gt;$tenantId&lt;/span&gt;&lt;span class="s2"&gt;/oauth2/v2.0/token&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;-ContentType&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;application/x-www-form-urlencoded&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;-Body&lt;/span&gt; &lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="n"&gt;-Method&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If everything works we receive an access token object as HTML 200/ok response:&lt;/p&gt;</description></item></channel></rss>