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

<channel>
	<title>Azure &#8211; My Shitty Code</title>
	<atom:link href="https://myshittycode.com/tag/azure/feed/" rel="self" type="application/rss+xml" />
	<link>https://myshittycode.com</link>
	<description>Embracing the Messiness in Search of Epic Solutions</description>
	<lastBuildDate>Tue, 24 Sep 2024 18:14:02 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://myshittycode.com/wp-content/uploads/2022/04/cropped-icon-32x32.png</url>
	<title>Azure &#8211; My Shitty Code</title>
	<link>https://myshittycode.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">205304208</site>	<item>
		<title>MSAL: Caching Access Token</title>
		<link>https://myshittycode.com/2024/09/24/msal-caching-access-token/</link>
					<comments>https://myshittycode.com/2024/09/24/msal-caching-access-token/#respond</comments>
		
		<dc:creator><![CDATA[Shitty Author]]></dc:creator>
		<pubDate>Tue, 24 Sep 2024 18:13:59 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Development Tools]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[MacOS]]></category>
		<category><![CDATA[MSAL]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://myshittycode.com/?p=2701</guid>

					<description><![CDATA[<p>Why Cache Access Token with MSAL? Building upon the previous post that performs delegated access authentication with MSAL, suppose your program uses this function to get the access token. In this case, it will always launch the browser to complete the authentication flow and retrieve the access token every time the program runs. While it [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2024/09/24/msal-caching-access-token/">MSAL: Caching Access Token</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#why-cache-access-token-with-msal">Why Cache Access Token with MSAL?</a></li><li><a href="#solution-a-use-custom-persistence-cache">Solution A: Use custom persistence cache</a></li><li><a href="#solution-b-use-the-os-platforms-encrypted-vault-preferred">Solution B: Use the OS platform&#8217;s encrypted vault (PREFERRED)</a></li></ul></nav></div>



<h2 class="wp-block-heading" id="why-cache-access-token-with-msal">Why Cache Access Token with MSAL?</h2>



<p>Building upon <a href="https://myshittycode.com/2024/09/23/msal-delegated-access-authentication/" data-type="post" data-id="2678">the previous post</a> that performs delegated access authentication with MSAL, suppose your program uses this function to get the access token.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
def get_access_token():
    app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY)
    result = app.acquire_token_interactive(scopes=SCOPES)
    access_token = result&#x5B;&#039;access_token&#039;]

    return access_token
</pre></div>


<p>In this case, it will always launch the browser to complete the authentication flow and retrieve the access token every time the program runs.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="1650" height="1096" src="https://myshittycode.com/wp-content/uploads/2024/09/msal-browser.png?x45560" alt="" class="wp-image-2703" srcset="https://myshittycode.com/wp-content/uploads/2024/09/msal-browser.png 1650w, https://myshittycode.com/wp-content/uploads/2024/09/msal-browser-300x199.png 300w, https://myshittycode.com/wp-content/uploads/2024/09/msal-browser-1024x680.png 1024w, https://myshittycode.com/wp-content/uploads/2024/09/msal-browser-768x510.png 768w, https://myshittycode.com/wp-content/uploads/2024/09/msal-browser-1536x1020.png 1536w" sizes="(max-width: 1650px) 100vw, 1650px" /></figure>



<p>While it works, it introduces a slight latency to your program. Fortunately, MSAL provides the capability to cache the access token.</p>



<h2 class="wp-block-heading" id="solution-a-use-custom-persistence-cache">Solution A: Use custom persistence cache</h2>



<p>In this solution, we can introduce our custom persistence cache.</p>



<p>First, we can use these functions to load the access token from the cache file and save it to the cache file.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import os
import msal

...
CACHE_FILE = &#039;msal_token_cache.json&#039;

def load_cache():
    cache = msal.SerializableTokenCache()

    if os.path.exists(CACHE_FILE):
        with open(CACHE_FILE, &#039;rb&#039;) as f:
            cache.deserialize(f.read())

    return cache

def save_cache(cache):
    if cache.has_state_changed:
        with open(CACHE_FILE, &#039;wb&#039;) as f:
            f.write(cache.serialize().encode())
</pre></div>


<p>We can first attempt to get a valid access token from the cache. It will only get the token interactively via the browser if the access token doesn&#8217;t exist or has expired.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; highlight: [2,6,8,9,10,11,12,13,14,17]; title: ; notranslate">
def get_access_token():
    cache = load_cache()
    app = msal.PublicClientApplication(
        CLIENT_ID,
        authority=AUTHORITY,
        token_cache=cache,
    )
    result = None
    accounts = app.get_accounts()

    if accounts:
        result = app.acquire_token_silent(SCOPES, account=accounts&#x5B;0])

    if not result:
        result = app.acquire_token_interactive(scopes=SCOPES)

    save_cache(cache)
    access_token = result&#x5B;&#039;access_token&#039;]

    return access_token
</pre></div>


<p>While this solution works, the implementation code is very lengthy. Furthermore, the access token is stored in the cache file as clear text.</p>



<h2 class="wp-block-heading" id="solution-b-use-the-os-platforms-encrypted-vault-preferred">Solution B: Use the OS platform&#8217;s encrypted vault (PREFERRED)</h2>



<p>A Python package called <a href="https://github.com/AzureAD/microsoft-authentication-extensions-for-python" target="_blank" rel="noopener">msal-extensions</a> allows the access token to be stored securely in the OS platform&#8217;s encrypted vault. For example, If the program runs on MacOS, KeyChain will be used. Windows uses DPAPI, and Linux uses LibSecret.</p>



<p>To begin, install that Python package.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; highlight: [4]; title: ; notranslate">
# requirements.txt

msal
msal-extensions
</pre></div>


<p>The configuration is much simpler than Solution A.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; highlight: [2,5,11]; title: ; notranslate">
import msal
from msal_extensions import build_encrypted_persistence, PersistedTokenCache

...
CACHE_FILE = &#039;msal_token_cache.json&#039;

def get_access_token():
    app = msal.PublicClientApplication(
        CLIENT_ID,
        authority=AUTHORITY,
        token_cache=PersistedTokenCache(build_encrypted_persistence(CACHE_FILE)),
    )

    result = None
    accounts = app.get_accounts()

    if accounts:
        result = app.acquire_token_silent(SCOPES, account=accounts&#x5B;0])

    if not result:
        result = app.acquire_token_interactive(scopes=SCOPES)

    access_token = result&#x5B;&#039;access_token&#039;]

    return access_token
</pre></div>


<p>When running the program on MacOS, the access token is stored in the KeyChain.</p>



<figure class="wp-block-image size-full"><img decoding="async" width="1940" height="1068" src="https://myshittycode.com/wp-content/uploads/2024/09/msal-keychain.png?x45560" alt="" class="wp-image-2704" srcset="https://myshittycode.com/wp-content/uploads/2024/09/msal-keychain.png 1940w, https://myshittycode.com/wp-content/uploads/2024/09/msal-keychain-300x165.png 300w, https://myshittycode.com/wp-content/uploads/2024/09/msal-keychain-1024x564.png 1024w, https://myshittycode.com/wp-content/uploads/2024/09/msal-keychain-768x423.png 768w, https://myshittycode.com/wp-content/uploads/2024/09/msal-keychain-1536x846.png 1536w" sizes="(max-width: 1940px) 100vw, 1940px" /></figure>



<p><strong>Note:</strong> An empty cache file named msal_token_cache.json has also been created. Unfortunately, there is no option in <code>msal-extensions==1.2.0</code> to disable the creation of this file at the moment.</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2024/09/24/msal-caching-access-token/">MSAL: Caching Access Token</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://myshittycode.com/2024/09/24/msal-caching-access-token/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2701</post-id>	</item>
		<item>
		<title>MSAL: Launching Specific Browser with Delegated Access Authentication</title>
		<link>https://myshittycode.com/2024/09/24/msal-launching-specific-browser-with-delegated-access-authentication/</link>
					<comments>https://myshittycode.com/2024/09/24/msal-launching-specific-browser-with-delegated-access-authentication/#respond</comments>
		
		<dc:creator><![CDATA[Shitty Author]]></dc:creator>
		<pubDate>Tue, 24 Sep 2024 15:16:59 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Development Tools]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[MacOS]]></category>
		<category><![CDATA[MSAL]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://myshittycode.com/?p=2689</guid>

					<description><![CDATA[<p>Why Launch a Specific Browser with MSAL? Building upon the previous post that performs delegated access authentication with MSAL, your institution may sometimes allow you to access Microsoft 365 products only on the approved browsers. By default, MSAL launches the default browser on your machine to obtain the access token interactively. If your institution only [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2024/09/24/msal-launching-specific-browser-with-delegated-access-authentication/">MSAL: Launching Specific Browser with Delegated Access Authentication</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#why-launch-a-specific-browser-with-msal">Why Launch a Specific Browser with MSAL?</a></li><li><a href="#overriding-with-browser-environment-variable">Overriding with BROWSER environment variable</a></li><li><a href="#what-if-the-browser-environment-variables-predefined-value-doesnt-work">What if the BROWSER environment variable&#8217;s predefined value doesn&#8217;t work?</a></li></ul></nav></div>



<h2 class="wp-block-heading" id="why-launch-a-specific-browser-with-msal">Why Launch a Specific Browser with MSAL?</h2>



<p>Building upon <a href="https://myshittycode.com/2024/09/23/msal-delegated-access-authentication/" data-type="post" data-id="2678">the previous post</a> that performs delegated access authentication with MSAL, your institution may sometimes allow you to access Microsoft 365 products only on the approved browsers.</p>



<p>By default, MSAL launches the default browser on your machine to obtain the access token interactively. </p>



<p>If your institution only allows Chrome and your default browser is Firefox, you will get the following message:</p>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="774" height="690" src="https://myshittycode.com/wp-content/uploads/2024/09/firefox-blocked.png?x45560" alt="msal" class="wp-image-2693" srcset="https://myshittycode.com/wp-content/uploads/2024/09/firefox-blocked.png 774w, https://myshittycode.com/wp-content/uploads/2024/09/firefox-blocked-300x267.png 300w, https://myshittycode.com/wp-content/uploads/2024/09/firefox-blocked-768x685.png 768w" sizes="(max-width: 774px) 100vw, 774px" /></figure>



<h2 class="wp-block-heading" id="overriding-with-browser-environment-variable">Overriding with BROWSER environment variable</h2>



<p>MSAL relies on Python&#8217;s built-in module called <a href="https://github.com/AzureAD/microsoft-authentication-library-for-python/blob/331c16fdd803df6a629cb215a6372dbad93f0ba8/msal/oauth2cli/authcode.py#L68" target="_blank" rel="noopener">webbrowser</a> to launch the browser. This allows us to change the browser by setting the <a href="https://docs.python.org/3/library/webbrowser.html" target="_blank" rel="noopener">BROWSER environment variable</a> to the predefined values (&#8216;firefox&#8217;, &#8216;chrome&#8217;, etc.)</p>



<p>For example, to launch Firefox instead of the default browser, we can do this:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; highlight: [5]; title: ; notranslate">
import os
import msal

# ... 
os.environ&#x5B;&#039;BROWSER&#039;] = &#039;firefox&#039;
app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY)
result = app.acquire_token_interactive(scopes=SCOPES)
</pre></div>


<h2 class="wp-block-heading" id="what-if-the-browser-environment-variables-predefined-value-doesnt-work">What if the BROWSER environment variable&#8217;s predefined value doesn&#8217;t work?</h2>



<p>I discovered that Python&#8217;s webbrowser failed to launch the correct browser, especially when dealing with Chromnium-based browsers.</p>



<p>For example, suppose my default browser is Brave, and I set the BROWSER environment variable to Chrome. In that case, it will still launch the Brave browser.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; highlight: [3]; title: ; notranslate">
# default browser = Brave

os.environ&#x5B;&#039;BROWSER&#039;] = &#039;chrome&#039;  # doesn&#039;t work
app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY)
result = app.acquire_token_interactive(scopes=SCOPES)
</pre></div>


<p>Fortunately, it is possible to <a href="https://github.com/AzureAD/microsoft-authentication-library-for-python/discussions/750#discussioncomment-10710600" target="_blank" rel="noopener">specify a full path ending with &#8216;%s&#8217;</a> instead:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; highlight: [3]; title: ; notranslate">
# default browser = Brave

os.environ&#x5B;&#039;BROWSER&#039;] = &#039;open -a /Applications/Google\\ Chrome.app %s&#039;  # works
app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY)
result = app.acquire_token_interactive(scopes=SCOPES)
</pre></div>


<p>If you are stuck on the &#8220;Approve sign in request&#8221; or<em> </em>&#8220;Set up your device to get access&#8221; screen indefinitely, consider clearing the browser cache and then try again.</p>



<p></p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2024/09/24/msal-launching-specific-browser-with-delegated-access-authentication/">MSAL: Launching Specific Browser with Delegated Access Authentication</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://myshittycode.com/2024/09/24/msal-launching-specific-browser-with-delegated-access-authentication/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2689</post-id>	</item>
		<item>
		<title>MSAL: Delegated Access Authentication</title>
		<link>https://myshittycode.com/2024/09/23/msal-delegated-access-authentication/</link>
					<comments>https://myshittycode.com/2024/09/23/msal-delegated-access-authentication/#respond</comments>
		
		<dc:creator><![CDATA[Shitty Author]]></dc:creator>
		<pubDate>Mon, 23 Sep 2024 20:17:14 +0000</pubDate>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Programming Language]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[MS 365]]></category>
		<category><![CDATA[MSAL]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://myshittycode.com/?p=2678</guid>

					<description><![CDATA[<p>The Microsoft Authentication Library (MSAL) supports various programming languages and frameworks to simplify the authentication flow against the Microsoft identity platform, which is a prerequisite to invoke APIs such as Microsoft Graph. In this example, we will write a Python script that performs delegated authentication flow using the user&#8217;s credentials. Once authenticated, the script will [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2024/09/23/msal-delegated-access-authentication/">MSAL: Delegated Access Authentication</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-rank-math-toc-block" id="rank-math-toc"><h2>Table of Contents</h2><nav><ul><li><a href="#app-registration-and-configuration">App Registration and Configuration</a></li><li><a href="#custom-python-script">Custom Python Program</a></li></ul></nav></div>



<p>The <a href="https://learn.microsoft.com/en-us/entra/msal/overview" target="_blank" rel="noopener">Microsoft Authentication Library (MSAL)</a> supports various programming languages and frameworks to simplify the authentication flow against the Microsoft identity platform, which is a prerequisite to invoke APIs such as Microsoft Graph.</p>



<p>In this example, we will write a Python script that performs delegated authentication flow using the user&#8217;s credentials. Once authenticated, the script will pull the user&#8217;s OneNote data via Microsoft Graph.</p>



<p><strong>Note:</strong> While we can also authenticate via app-only access, this is generally scrutinized in larger institutions due to the blast radius. This is because the app can modify other users&#8217; content stored in Microsoft 365 products (emails, calendars, etc).</p>



<h2 class="wp-block-heading" id="app-registration-and-configuration">App Registration and Configuration</h2>



<p>Even if you plan to run your program on your local machine, you must register it in the Azure Portal to generate a unique client ID to authenticate.</p>



<ul class="wp-block-list">
<li>Go to <a href="https://portal.azure.com/" target="_blank" rel="noopener">https://portal.azure.com/</a> and sign in.</li>



<li>Go to <strong>App Registrations</strong> and register your app.</li>



<li>Go to the registered app -> <strong>Manage</strong> (<em>step 1</em>) -> <strong>Authentication</strong> (<em>step </em>2). Ensure the following configurations exist:
<ul class="wp-block-list">
<li>A <strong>Mobile and desktop applications</strong> platform with the redirect URI set as <strong>http://localhost</strong> (<em>step </em>3).</li>



<li>The <strong>Access tokens (used for implicit flows)</strong> option is checked (<em>step </em>4).</li>
</ul>
</li>
</ul>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="2114" height="2908" src="https://myshittycode.com/wp-content/uploads/2024/09/msal-authentication.png?x45560" alt="" class="wp-image-2680" srcset="https://myshittycode.com/wp-content/uploads/2024/09/msal-authentication.png 2114w, https://myshittycode.com/wp-content/uploads/2024/09/msal-authentication-218x300.png 218w, https://myshittycode.com/wp-content/uploads/2024/09/msal-authentication-744x1024.png 744w, https://myshittycode.com/wp-content/uploads/2024/09/msal-authentication-768x1056.png 768w, https://myshittycode.com/wp-content/uploads/2024/09/msal-authentication-1117x1536.png 1117w, https://myshittycode.com/wp-content/uploads/2024/09/msal-authentication-1489x2048.png 1489w" sizes="auto, (max-width: 2114px) 100vw, 2114px" /></figure>



<ul class="wp-block-list">
<li>Go to the registered app -> <strong>Manage</strong> (<em>step 1</em>) -> <strong>API permissions</strong> (<em>step </em>2).</li>



<li>Add the permissions you need (<em>step </em>3). OneNote&#8217;s permissions are added in this example because the script will query OneNote via Microsoft Graph. </li>



<li>Before we can call the Microsoft Graph API, these permissions must have green check marks (<em>step </em>5), accomplished by clicking the <strong>Grant admin consent</strong> button (<em>step </em>4). If this button is grayed out, request your institution&#8217;s Azure administrators to perform this step on your behalf.</li>
</ul>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="2110" height="1484" src="https://myshittycode.com/wp-content/uploads/2024/09/msal-permissions.png?x45560" alt="" class="wp-image-2681" srcset="https://myshittycode.com/wp-content/uploads/2024/09/msal-permissions.png 2110w, https://myshittycode.com/wp-content/uploads/2024/09/msal-permissions-300x211.png 300w, https://myshittycode.com/wp-content/uploads/2024/09/msal-permissions-1024x720.png 1024w, https://myshittycode.com/wp-content/uploads/2024/09/msal-permissions-768x540.png 768w, https://myshittycode.com/wp-content/uploads/2024/09/msal-permissions-1536x1080.png 1536w, https://myshittycode.com/wp-content/uploads/2024/09/msal-permissions-2048x1440.png 2048w" sizes="auto, (max-width: 2110px) 100vw, 2110px" /></figure>



<h2 class="wp-block-heading" id="custom-python-script">Custom Python Program</h2>



<p>Now that the app is registered and configured in the Azure Portal, we can work on the custom script.</p>



<p>Install the msal library.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
# requirements.txt

requests
msal
</pre></div>


<p>Define the needed variables. The client ID and tenant ID can be retrieved from your registered app in the Azure Portal.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
import msal
import requests

CLIENT_ID = &#039;&#x5B;YOUR_CLIENT_ID]&#039;
TENANT_ID = &#039;&#x5B;TENANT_ID]&#039;
AUTHORITY = f&#039;https://login.microsoftonline.com/{TENANT_ID}&#039;
SCOPES = &#x5B;&#039;Notes.Read&#039;, &#039;User.Read&#039;]
</pre></div>


<p>A function to perform the authentication and to retrieve the access token. MSAL will seamlessly create a web server running on localhost to accept the incoming token data (hence, the need to configure the redirect URI in the Azure Portal).</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
def get_access_token():
    app = msal.PublicClientApplication(CLIENT_ID, authority=AUTHORITY)
    result = app.acquire_token_interactive(scopes=SCOPES)
    access_token = result&#x5B;&#039;access_token&#039;]

    return access_token
</pre></div>


<p>A simple function to query OneNote pages using Microsoft Graph.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
def get_onenote_pages(access_token):
    url = &#039;https://graph.microsoft.com/v1.0/me/onenote/pages&#039;

    headers = {
        &#039;Authorization&#039;: f&#039;Bearer {access_token}&#039;,
        &#039;Accept&#039;: &#039;application/json&#039;
    }

    response = requests.get(url, headers=headers)
    response.raise_for_status()

    return response.json()
</pre></div>


<p>Finally, run the app to test if the app registration and configuration are set up correctly in the Azure Portal.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: python; title: ; notranslate">
def run():
    access_token = get_access_token()
    print(access_token)

    onenote_pages = get_onenote_pages(access_token)
    print(onenote_pages)


if __name__ == &#039;__main__&#039;:
    run() 
</pre></div><p>The post <a rel="nofollow" href="https://myshittycode.com/2024/09/23/msal-delegated-access-authentication/">MSAL: Delegated Access Authentication</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://myshittycode.com/2024/09/23/msal-delegated-access-authentication/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2678</post-id>	</item>
		<item>
		<title>Azure: Deploying WAR File to Tomcat</title>
		<link>https://myshittycode.com/2019/05/02/azure-deploying-war-file-to-tomcat/</link>
					<comments>https://myshittycode.com/2019/05/02/azure-deploying-war-file-to-tomcat/#respond</comments>
		
		<dc:creator><![CDATA[Shitty Author]]></dc:creator>
		<pubDate>Fri, 03 May 2019 00:53:14 +0000</pubDate>
				<category><![CDATA[Development Tools]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Tomcat]]></category>
		<guid isPermaLink="false">http://myshittycode.com/?p=1106</guid>

					<description><![CDATA[<p>PROBLEM Typically, when using ZipDeploy to push a WAR file (ex: my-app.war) to an Azure instance, we need to:- This zip file will automatically be unzipped under site/wwwroot:- Tomcat detects ROOT.war and will try to unpack the WAR file under ROOT/:- The problem is sometimes Tomcat is unable to fully unpack ROOT.war because some files [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://myshittycode.com/2019/05/02/azure-deploying-war-file-to-tomcat/">Azure: Deploying WAR File to Tomcat</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">PROBLEM</h2>



<p>Typically, when using ZipDeploy to push a WAR file (ex: <b>my-app.war</b>) to an Azure instance, we need to:-</p>



<ul class="wp-block-list">
<li>Rename <b>my-app.war</b> to <b>ROOT.war</b>.</li>



<li>Place <b>ROOT.war</b> under <b>webapps/</b>.</li>



<li>Zip up <b>webapps/</b>.</li>



<li>Use ZipDeploy to push the zip file to an Azure instance.</li>
</ul>



<p>This zip file will automatically be unzipped under <b>site/wwwroot</b>:-</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; highlight: [2,3]; title: ; notranslate">
D:\home\site\wwwroot
└── webapps
    └── ROOT.war
</pre></div>


<p>Tomcat detects <b>ROOT.war</b> and will try to unpack the WAR file under <b>ROOT/</b>:-</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; highlight: [3,4,5,6,7]; title: ; notranslate">
D:\home\site\wwwroot
└── webapps
    ├── ROOT
    │   ├── META-INF
    │   │   └── ...
    │   └── WEB-INF
    │       └── ...
    └── ROOT.war
</pre></div>


<p>The problem is sometimes Tomcat is unable to fully unpack <b>ROOT.war</b> because some files may be locked by some running processes. As a result, the web page fails to load and shows 404 error.</p>



<h2 class="wp-block-heading">SOLUTION</h2>



<p>A better and more stable solution is to use WarDeploy to push WAR file to an Azure instance because:-</p>



<ul class="wp-block-list">
<li>It simplifies the deployment process because we don&#8217;t need to create a zip file with <b>webapps/</b> containing a WAR file named <b>ROOT.war</b>.</li>



<li>Instead of relying on Tomcat to unpack the WAR file, WarDeploy will do the unpacking step elsewhere before copying to <b>site/wwwroot/webapps/</b>.</li>
</ul>



<p>To use WarDeploy, you can use <b>curl</b> command or PowerShell script to do so.</p>



<p>Here&#8217;s an example of the PowerShell script:-</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
Param(
    &#x5B;string]$filePath,
    &#x5B;string]$apiUrl,
    &#x5B;string]$username,
    &#x5B;string]$password
)

$base64AuthInfo = &#x5B;Convert]::ToBase64String(&#x5B;Text.Encoding]::ASCII.GetBytes((&quot;{0}:{1}&quot; -f $username, $password)))

Invoke-RestMethod -Uri $apiUrl -Headers @{ Authorization = (&quot;Basic {0}&quot; -f $base64AuthInfo) } -Method POST -InFile $filePath -ContentType &quot;multipart/form-data&quot;
</pre></div>


<p>If the PowerShell script above is called <b>deploy.ps1</b>, to push <b>my-app.war</b> to <b>my-app</b> Azure instance:-</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
deploy.ps1 -filePath D:\my-app.war -apiUrl https://my-app.scm.azurewebsites.net/api/wardeploy -username &#x5B;USER] -password &#x5B;PASSWORD]
</pre></div>


<p>Depending on the size of the WAR file, you may get &#8220;The operation has timed out&#8221; error after 100 seconds:-</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
Invoke-RestMethod : The operation has timed out
At D:\agent\_work\2ea6e947a\my-app\deploy.ps1:18 char:1
+ Invoke-RestMethod -Uri $apiUrl -Headers @{Authorization=(&quot;Basic {0}&quot;  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) &#x5B;Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
</pre></div>


<p>This will most likely to occur if the WAR file is too big (80MB+).</p>



<p>To fix this, increase the time out duration by adding <b>-TimeoutSec</b> option to <b>Invoke-RestMethod</b> statement:-</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: powershell; title: ; notranslate">
Invoke-RestMethod &#x5B;OTHER_OPTIONS...] -TimeoutSec 300
</pre></div><p>The post <a rel="nofollow" href="https://myshittycode.com/2019/05/02/azure-deploying-war-file-to-tomcat/">Azure: Deploying WAR File to Tomcat</a> appeared first on <a rel="nofollow" href="https://myshittycode.com">My Shitty Code</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://myshittycode.com/2019/05/02/azure-deploying-war-file-to-tomcat/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1106</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 
Lazy Loading (feed)
Database Caching using Disk

Served from: myshittycode.com @ 2026-02-18 13:38:37 by W3 Total Cache
-->