<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Basic-Auth on blog.iankulin.com</title><link>https://blog.iankulin.com/tags/basic-auth/</link><description>Recent content in Basic-Auth on blog.iankulin.com</description><generator>Hugo</generator><language>en-AU</language><lastBuildDate>Mon, 09 Dec 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.iankulin.com/tags/basic-auth/index.xml" rel="self" type="application/rss+xml"/><item><title>NGINX proxy manager - setting headers to use basic auth in your apps</title><link>https://blog.iankulin.com/nginx-proxy-manager-setting-headers-to-use-basic-auth-in-your-apps/</link><pubDate>Mon, 09 Dec 2024 00:00:00 +0000</pubDate><guid>https://blog.iankulin.com/nginx-proxy-manager-setting-headers-to-use-basic-auth-in-your-apps/</guid><description>&lt;p&gt;When I&amp;rsquo;m spinning up side projects, I frequently ignore auth, and just rely on NGINX basic auth - one of the side benefits of reverse-proxying everything.&lt;/p&gt;
&lt;h3 id="regular-nginx"&gt;Regular NGINX&lt;/h3&gt;
&lt;p&gt;This &lt;a href="https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/"&gt;article in the docs&lt;/a&gt; explains how to set up basic auth to protect different paths. To make it work in my node apps, I need the successful user name passed in so I check it against the user table to work out access rights etc.&lt;/p&gt;
&lt;p&gt;To get it passed in with every request, we need to stick it in the headers. We do this in the NGINX conf for the site:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	root &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;var&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;www&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;ct&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;example&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;com&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	index index&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;html&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	server_name ct&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;example&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;com&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	location &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		auth_basic &lt;span style="color:#a3be8c"&gt;&amp;#34;Secure app&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 auth_basic_user_file &lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;etc&lt;span style="color:#81a1c1"&gt;/&lt;/span&gt;nginx&lt;span style="color:#81a1c1"&gt;/.&lt;/span&gt;htpasswd&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		proxy_pass http&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt;localhost&lt;span style="color:#eceff4"&gt;:&lt;/span&gt;&lt;span style="color:#b48ead"&gt;3000&lt;/span&gt;&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		proxy_http_version &lt;span style="color:#b48ead"&gt;1.1&lt;/span&gt;&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		proxy_set_header Upgrade &lt;span style="color:#81a1c1"&gt;$&lt;/span&gt;http_upgrade&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		proxy_set_header Connection &lt;span style="color:#a3be8c"&gt;&amp;#39;upgrade&amp;#39;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		proxy_set_header Host &lt;span style="color:#81a1c1"&gt;$&lt;/span&gt;host&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		proxy_set_header X&lt;span style="color:#81a1c1"&gt;-&lt;/span&gt;Username &lt;span style="color:#81a1c1"&gt;$&lt;/span&gt;remote_user&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		proxy_cache_bypass &lt;span style="color:#81a1c1"&gt;$&lt;/span&gt;http_upgrade&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then in my app, I just check the header like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; USERNAME_HEADER &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; &lt;span style="color:#a3be8c"&gt;&amp;#34;x-username&amp;#34;&lt;/span&gt;&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; basic auth middleware
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;app&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;use&lt;span style="color:#eceff4"&gt;((&lt;/span&gt;req&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; res&lt;span style="color:#eceff4"&gt;,&lt;/span&gt; next&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; username &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; req&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;headers&lt;span style="color:#eceff4"&gt;[&lt;/span&gt;USERNAME_HEADER&lt;span style="color:#eceff4"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;!&lt;/span&gt;username&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;return&lt;/span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;status&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;400&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;send&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#bf616a"&gt;`&lt;/span&gt;Missing header&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;$&lt;/span&gt;&lt;span style="color:#eceff4"&gt;{&lt;/span&gt;USERNAME_HEADER&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;&lt;span style="color:#bf616a"&gt;`&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;const&lt;/span&gt; user &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; usersArray&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;find&lt;span style="color:#eceff4"&gt;((&lt;/span&gt;user&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;=&amp;gt;&lt;/span&gt; user&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;user &lt;span style="color:#81a1c1"&gt;===&lt;/span&gt; username&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;if&lt;/span&gt; &lt;span style="color:#eceff4"&gt;(&lt;/span&gt;user&lt;span style="color:#eceff4"&gt;)&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#81a1c1"&gt;//&lt;/span&gt; Save user details to req object
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; req&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;role &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; user&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;role&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; req&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;username &lt;span style="color:#81a1c1"&gt;=&lt;/span&gt; username&lt;span style="color:#eceff4"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; next&lt;span style="color:#eceff4"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt; &lt;span style="color:#81a1c1;font-weight:bold"&gt;else&lt;/span&gt; &lt;span style="color:#eceff4"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; res&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;status&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#b48ead"&gt;401&lt;/span&gt;&lt;span style="color:#eceff4"&gt;)&lt;/span&gt;&lt;span style="color:#81a1c1"&gt;.&lt;/span&gt;send&lt;span style="color:#eceff4"&gt;(&lt;/span&gt;&lt;span style="color:#bf616a"&gt;`&lt;/span&gt;User unauthorised&lt;span style="color:#eceff4"&gt;:&lt;/span&gt; &lt;span style="color:#81a1c1"&gt;$&lt;/span&gt;&lt;span style="color:#eceff4"&gt;{&lt;/span&gt;username&lt;span style="color:#eceff4"&gt;}&lt;/span&gt;&lt;span style="color:#bf616a"&gt;`&lt;/span&gt;&lt;span style="color:#eceff4"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#eceff4"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#eceff4"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s a bit of a fudge, but for personal use apps it&amp;rsquo;s quick to set up, and pretty robust from a security point of view.&lt;/p&gt;
&lt;h3 id="nginx-proxy-manager"&gt;NGINX Proxy Manager&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve moved to using NGINX Proxy Manager (NPM) rather than raw NGINX since it makes getting SSL certificates super simple. NPM basically wraps all the reverse proxy functionality of NGINX into a nice click ops web GUI.&lt;/p&gt;
&lt;p&gt;We now specify the user names and passwords in the gui (instead of faffing around installing apache2-utils and running it to build the &lt;code&gt;.htpasswd&lt;/code&gt; file. This is done by creating an access list:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.43.16-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.43.16-am.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then in the Authorization tab, adding your users:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.42.44-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.42.44-am.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once that&amp;rsquo;s saved, we apply it to the proxy record:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.47.38-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.47.38-am.png" width="900" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But then how do we set the x-username header? Since there&amp;rsquo;s an advanced tab, you may think it&amp;rsquo;s in there, and that looks promising till you read the warning below the text box.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.52.24-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.52.24-am.png" width="839" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Setting a header is exactly what we want to do, so let&amp;rsquo;s head to the &amp;ldquo;locations&amp;rdquo; tab.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.55.04-am.png"&gt;&lt;img src="https://blog.iankulin.com/images/screen-shot-2024-10-27-at-11.55.04-am.png" width="674" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We just use the root path &amp;ldquo;/&amp;rdquo; for our path so it applies to every request, proxy those requests to our app, and set the header in the text box (which appears when you click the gear button).&lt;/p&gt;</description></item></channel></rss>