<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Peek Read Info (Posts about SSO)</title><link>https://peekread.info/</link><description></description><atom:link href="https://peekread.info/tags/sso.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2024 &lt;a href="mailto:dugite-code@peekread.info"&gt;Dugite-Code&lt;/a&gt; 
&lt;a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-SA"
width="88px" height="31px" style="border-width:0; margin-bottom:12px;"
src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Wed, 14 Feb 2024 06:33:09 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Authentik Gotifiy Login Notifications</title><link>https://peekread.info/tech/20220506-authentik-gotifiy-login-notifications/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2022/0428-sso-with-authentik/image01.png" alt="SSO all the things"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;Continuing with my journy of utilising Authentik for my SSO. After reading a rather good comment by &lt;a href="https://www.reddit.com/r/selfhosted/comments/ub7dvb/authentik_or_keycloak/i62o6hf/"&gt;/u/internallogictv&lt;/a&gt; over on the reddit &lt;a href="https://www.reddit.com/r/selfhosted/"&gt;/r/selfhosted&lt;/a&gt;, I wanted to add a few more protections. The simplest of which is to send myself a notification whenever a login or a failed login occurs.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Step 1&lt;/h2&gt;
&lt;p&gt;First things first we create a new application in gotify in order to generate a token for authentik use. Select the &lt;code&gt;Apps&lt;/code&gt; tab and press the &lt;code&gt;Create Application&lt;/code&gt; button.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Gotify create an application" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="185" max-width="800" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image01.png"&gt;&lt;/p&gt;
&lt;h2&gt;Step 2&lt;/h2&gt;
&lt;p&gt;Create a new gotify property mapping in the &lt;code&gt;Admin Interface -&amp;gt; Customisation -&amp;gt; Property Mappings&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="426" max-width="800" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image02.png"&gt;&lt;/p&gt;
&lt;p&gt;I've built this so a login failed is set to the maximum gotify priority level regardless of the user group. For successful logins I divide the levels based on the group gotify-users. I algo create a geo uri for mapping applications on android. You will be able to click the notification and it will open the city co-ordinates, although you may have to skip this if you don't have the &lt;code&gt;geoipupdate&lt;/code&gt; container configured.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Get the login failed username&lt;/span&gt;
    &lt;span class="n"&gt;event_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Get the login succeeded username&lt;/span&gt;
    &lt;span class="n"&gt;event_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"login_failed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"warning"&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;ak_is_group_member&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ak_user_by&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;event_user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"gotify-users"&lt;/span&gt; &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;# Check if the user belongs to group&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# default notification settings&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;severity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;

&lt;span class="c1"&gt;# Build a geo uri for opening a mapping applications from the gotify notification.&lt;/span&gt;
&lt;span class="n"&gt;geo_uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"geo:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'lat'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'long'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?q=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'lat'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'long'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;severity&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from authentik &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"New &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;event_user&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; was detected coming from &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'city'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'geo'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'country'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from the IP address: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client_ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Build the gotify payload&lt;/span&gt;
&lt;span class="n"&gt;gotify_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"extras"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"client::notification"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"click"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;geo_uri&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;gotify_payload&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Step 3&lt;/h2&gt;
&lt;p&gt;Create a new notification transport &lt;code&gt;Admin Interface -&amp;gt; Events -&amp;gt;  Notification Transports&lt;/code&gt; using &lt;code&gt;Webhook (generic)&lt;/code&gt; your gotify message url with the token created in step one &lt;code&gt;https://example.tld/gotify/message?token=yourtokenhere&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="360" max-width="799" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image03.png"&gt;&lt;/p&gt;
&lt;h2&gt;Step 4&lt;/h2&gt;
&lt;p&gt;Finally we create the notification rule that actually calls the Notification transport. &lt;code&gt;Admin Interface -&amp;gt; Events -&amp;gt;  Notification Rules&lt;/code&gt; Create a new rule &lt;code&gt;login-notification&lt;/code&gt; sending to the group of your choice (This dosn't really matter but it will display an ugly json string as notification on the web UI). Select the &lt;code&gt;Gotify&lt;/code&gt; notification transport you created and set the Severity to &lt;code&gt;Notice&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="489" max-width="798" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image04.png"&gt;&lt;/p&gt;
&lt;p&gt;Now we have to create the policies &lt;code&gt;authentik-core-login&lt;/code&gt; and &lt;code&gt;authentik-core-login-failed&lt;/code&gt; to the event. Expand the &lt;code&gt;login-notification&lt;/code&gt; event and press &lt;code&gt;Create Policy&lt;/code&gt;. Select &lt;code&gt;Event Matcher Policy&lt;/code&gt;, name it &lt;code&gt;authentik-core-login&lt;/code&gt; enable the &lt;code&gt;Execution Logging&lt;/code&gt; option, select the &lt;code&gt;Login&lt;/code&gt; action and &lt;code&gt;authentik Core&lt;/code&gt; App. Finish and repeat for the &lt;code&gt;Login Failed&lt;/code&gt; action.&lt;/p&gt;
&lt;p&gt;Now you should be receiving Login and Login Failed notifications from your Authentik instance over Gotify. I Hope I'll be able to update this to pull different tokens from the user/group attributes in the future to better separate notifications to individual users/admins.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-height="294" max-width="797" src="https://peekread.info/images/2022/0506-authentik-gotifiy-login-notifications/image05.png"&gt;&lt;/p&gt;</description><category>authentik</category><category>gotify</category><category>notifications</category><category>security</category><category>SSO</category><guid>https://peekread.info/tech/20220506-authentik-gotifiy-login-notifications/</guid><pubDate>Thu, 05 May 2022 16:00:00 GMT</pubDate></item><item><title>Node-Red SSO with Authentik</title><link>https://peekread.info/tech/20220429-node-red-sso-with-authentik/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2019/1122-node-red-website-alerts/image01.png" alt="Node-RED is a flow-based programming tool, originally developed by IBM’s Emerging Technology Services team and now a part of the JS Foundation."&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;Following my &lt;a href="https://peekread.info/tech/20220325-sso-with-authentik/"&gt;last post regarding SSO with Authentik&lt;/a&gt; I thought I should post my passportjs configuration for Node-Red and OpenidConnect. Currently User accounts work, however I haven't gotten group based permissions setup yet.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Note This guide is based off the &lt;a href="https://goauthentik.io/integrations/services/gitea/"&gt;Gitea integration guide from the Authentik docs.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Preparation&lt;/h3&gt;
&lt;p&gt;The following placeholders will be used:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;authentik.company&lt;/code&gt; is the FQDN of authentik.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;nodered.company&lt;/code&gt; is the FQDN of nodered.&lt;/p&gt;
&lt;h3&gt;Step 1&lt;/h3&gt;
&lt;p&gt;In authentik, create an OAuth2/OpenID Provider (under Resources/Providers) with these settings:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;note&lt;/p&gt;
&lt;p&gt;Only settings that have been modified from default have been listed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Protocol Settings&lt;/h4&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;
&lt;span class="n"&gt;Signing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;note&lt;/p&gt;
&lt;p&gt;Take note of the Client ID and Client Secret, you'll need to give them to nodered in Step 3.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Step 2&lt;/h3&gt;
&lt;p&gt;In authentik, create an application (under Resources/Applications) which uses this provider. Optionally apply access restrictions to the application using policy bindings.
note&lt;/p&gt;
&lt;p&gt;Only settings that have been modified from default have been listed.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;
&lt;span class="n"&gt;Slug&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;
&lt;span class="n"&gt;Provider&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodered&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Step 3&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;note&lt;/p&gt;
&lt;p&gt;We are assuming node-red is installed under docker&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Navigate to the node-red data volume &lt;code&gt;data/node_modules/&lt;/code&gt;. Alternatively enter the docker container &lt;code&gt;sudo docker exec -it nodered bash&lt;/code&gt; and cd &lt;code&gt;/data/node_modules&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Use npm to install passport-openidconnect npm install passport-openidconnect&lt;/p&gt;
&lt;p&gt;Edit the node-red settings.js file &lt;code&gt;/data/settings.js&lt;/code&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nx"&gt;adminAuth&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"strategy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openidconnect"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Sign in with authentik'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"fa-cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"passport-openidconnect"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;issuer&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/&amp;lt;application-slug&amp;gt;/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;authorizationURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/authorize/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;tokenURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/token/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;userInfoURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://authentik.company/application/o/userinfo/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;clientID&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;Client ID (Key): Step 2&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;clientSecret&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;Client Secret: Step 2&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;callbackURL&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'https://nodered.company/auth/strategy/callback/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'profile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'openid'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;verify&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;permissions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><category>authentik</category><category>node-red</category><category>security</category><category>SSO</category><guid>https://peekread.info/tech/20220429-node-red-sso-with-authentik/</guid><pubDate>Thu, 28 Apr 2022 16:00:00 GMT</pubDate></item><item><title>SSO with Authentik</title><link>https://peekread.info/tech/20220325-sso-with-authentik/</link><dc:creator>Dugite-Code</dc:creator><description>&lt;p&gt;&lt;/p&gt;&lt;div class="d-flex position-relative pt-3 pb-3"&gt;
    &lt;div class="flex-shrink-0 me-3"&gt;
        &lt;img data-pagefind-meta="image[src], image_alt[alt]" style="height:89px;" src="https://peekread.info/images/2022/0428-sso-with-authentik/image01.png" alt="SSO all the things"&gt;
    &lt;/div&gt;
    &lt;div&gt;
        &lt;p class="mt-3"&gt;&lt;/p&gt;&lt;p&gt;A while back I wrote about minimising my attack surface by utilising default deny and whitelists in Nginx. Now I've gotten into the weeds with authentication and deployed an SSO (Signle sign-on) service on my selfhosted infrastructure.&lt;/p&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;What is Authentik?&lt;/h3&gt;
&lt;p&gt;Authentik is a SSO (Single Sign on) provider, much like with Google's services you sign in once and then you can access all your services. This has been a big bugbear with selfhosted applications, with &lt;a href="https://gitlab.com/dugite-code/rcmail_ttrss"&gt;Roundcubemail TTRSS plugin&lt;/a&gt;, &lt;a href="https://github.com/dugite-code/auth_rcmail"&gt;auto authentication for Tiny Tiny RSS against an IMAP Server&lt;/a&gt; and &lt;a href="https://github.com/dugite-code/codiad-imap_auth"&gt;Codiad External Authentication via IMAP &lt;/a&gt; to name a few work arounds to the issue I have hacked together over the years.&lt;/p&gt;
&lt;p&gt;Most importantly for my use case is the single pane of glass to access my services:&lt;/p&gt;
&lt;p&gt;&lt;img alt="A nice dashboard really brings it all together" class="img-fluid dark-image mx-auto d-block text-center text-light" loading="lazy" max-width="1110" src="https://peekread.info/images/2022/0428-sso-with-authentik/a-nice-dashboard-realy-brings-it-all-together.png"&gt;&lt;/p&gt;
&lt;h3&gt;The Issues&lt;/h3&gt;
&lt;p&gt;Introducing a SSO system introduces complexity and potential problems so it's not all smooth sailing, passwords are a thing still as they are simple and reliable and understandable.&lt;/p&gt;
&lt;h4&gt;New Project new problems, limited reviews&lt;/h4&gt;
&lt;p&gt;Authentik's first beta release was in Jan 2020 so it's very new and has had a few teething issues and quite a few bugs. I highly recommend utilising additional security methods in front of authentik (IDS/IPS, Geo Blocking and ideally using a VPN to access) until it reaches maturity.&lt;/p&gt;
&lt;h4&gt;Poor Documentation&lt;/h4&gt;
&lt;p&gt;Quite frankly the documentation isn't great if you are attempting to figure out &lt;strong&gt;HOW&lt;/strong&gt; it’s supposed to work. Thankfully they have integration guides included in the docs that covers the gaps, so some reading between the lines is needed for a while yet.&lt;/p&gt;
&lt;h4&gt;Limited compatibility&lt;/h4&gt;
&lt;p&gt;Not everything has SSO support (SAML, Oauth/OpenidConnect or reverse Proxy Authentication), thankfully this isn't as hard to deal with as it once was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://discourse.nodered.org/t/nextcloud-oauth-2-login/4403/8?u=dugite-code"&gt;My post on adding openidconnect to node-red&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ArchiveBox/ArchiveBox/pull/866#discussion_r839151488"&gt;My minor contribution to the Reverse Proxy authentication pull request for ArchiveBox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main issue I have faced is with HomeAssistant. The developers have been reluctant/resistant to adding additional authentication methods to the project. There is the &lt;a href="https://github.com/BeryJu/hass-auth-header"&gt;hass-auth-header&lt;/a&gt; project created by the developer of Authentik, however the HomeAssistant Android app is frustratingly a &lt;a href="https://github.com/home-assistant/android/issues/1438"&gt;major sticking point&lt;/a&gt;.&lt;/p&gt;</description><category>authentication</category><category>authentik</category><category>rss</category><category>security</category><category>SSO</category><guid>https://peekread.info/tech/20220325-sso-with-authentik/</guid><pubDate>Thu, 24 Mar 2022 16:00:00 GMT</pubDate></item></channel></rss>