avatarTeri Radichel

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

5810

Abstract

div id="2fc2"><pre>npm install express express-session keycloak-connect nodemon</pre></div><h2 id="592f">Define main execution file — app.js</h2><p id="f128">Add a file named app.js at the root level of your secure-express-service project.</p><p id="8d46">Define imports and express app</p><div id="54ca"><pre><span class="hljs-comment">// file - app.js</span>

<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>); <span class="hljs-keyword">const</span> session = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express-session"</span>); <span class="hljs-keyword">const</span> <span class="hljs-title class_">Keycloak</span> = <span class="hljs-built_in">require</span>(<span class="hljs-string">"keycloak-connect"</span>);

<span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>(); <span class="hljs-keyword">const</span> <span class="hljs-variable constant_">PORT</span> = <span class="hljs-number">3000</span>;

...</pre></div><p id="ccec">Setup Keycloak Middleware</p><div id="cefb"><pre><span class="hljs-comment">// file - app.js</span>

...

<span class="hljs-keyword">const</span> <span class="hljs-variable constant_">USER_ROLE</span> = process.<span class="hljs-property">env</span>.<span class="hljs-property">USER_ROLE</span> || <span class="hljs-string">'express-user'</span>; <span class="hljs-keyword">const</span> <span class="hljs-variable constant_">ADMIN_ROLE</span> = process.<span class="hljs-property">env</span>.<span class="hljs-property">ADMIN_ROLE</span> || <span class="hljs-string">'express-admin'</span>;

<span class="hljs-keyword">const</span> kcConfig = { <span class="hljs-attr">clientId</span>: process.<span class="hljs-property">env</span>.<span class="hljs-property">AUTH_CLIENT_ID</span> || <span class="hljs-string">'secure-express-service'</span>, <span class="hljs-attr">bearerOnly</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">serverUrl</span>: process.<span class="hljs-property">env</span>.<span class="hljs-property">AUTH_SERVER</span> || <span class="hljs-string">'http://localhost:8080'</span>, <span class="hljs-attr">realm</span>: process.<span class="hljs-property">env</span>.<span class="hljs-property">AUTH_REALM</span> || <span class="hljs-string">'master'</span> };

<span class="hljs-keyword">const</span> memoryStore = <span class="hljs-keyword">new</span> session.<span class="hljs-title class_">MemoryStore</span>();

<span class="hljs-title class_">Keycloak</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>.<span class="hljs-property">accessDenied</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">request, response</span>) { response.<span class="hljs-title function_">status</span>(<span class="hljs-number">401</span>) response.<span class="hljs-title function_">setHeader</span>(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'application/json'</span>) response.<span class="hljs-title function_">end</span>(<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>({ <span class="hljs-attr">status</span>: <span class="hljs-number">401</span>, <span class="hljs-attr">message</span>: <span class="hljs-string">'Unauthorized/Forbidden'</span>, <span class="hljs-attr">result</span>: { <span class="hljs-attr">errorCode</span>: <span class="hljs-string">'ERR-401'</span>, <span class="hljs-attr">errorMessage</span>: <span class="hljs-string">'Unauthorized/Forbidden'</span> } })) }

<span class="hljs-keyword">const</span> keycloak = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Keycloak</span>({ <span class="hljs-attr">store</span>: memoryStore }, kcConfig);

<span class="hljs-keyword">function</span> <span class="hljs-title function_">adminOnly</span>(<span class="hljs-params">token, request</span>) { <span class="hljs-keyword">return</span> token.<span class="hljs-title function_">hasRole</span>(<span class="hljs-string">realm:<span class="hljs-subst">${ADMIN_ROLE}</span></span>); }

<span class="hljs-keyword">function</span> <span class="hljs-title function_">isAuthenticated</span>(<span class="hljs-params">token, request</span>) { <span class="hljs-keyword">return</span> token.<span class="hljs-title function_">hasRole</span>(<span class="hljs-string">realm:<span class="hljs-subst">${ADMIN_ROLE}</span></span>) || token.<span class="hljs-title function_">hasRole</span>(<span class="hljs-string">realm:<span class="hljs-subst">${USER_ROLE}</span></span>); }

app.<span class="hljs-title function_">use</span>(<span class="hljs-title function_">session</span>({ <span class="hljs-attr">secret</span>: process.<span class="hljs-property">env</span>.<span class="hljs-property">APP_SECRET</span> || <span class="hljs-string">'BV&%R*BD66JH'</span>, <span class="hljs-attr">resave</span>: <span class="hljs-literal">false</span>, <span class="hljs-attr">saveUninitialized</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">store</span>: memoryStore }));

app.<span class="hljs-title function_">use</span>( keycloak.<span class="hljs-title function_">middleware</span>() );

...</pre></div><p id="bfe2">Setup REST endpoint and server</p><div id="5fc0"><pre>app.<span class="hljs-title function_">get</span>(<span class="hljs-string">'/public'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> { res.<span class="hljs-title function_">status</span>(<span class="hljs-number">200</span>).<span class="hljs-title function_">send</span>({ <span class="hljs-string

Options

">'message'</span>: <span class="hljs-string">"This is a public enpoint which can be accessed by anonymous users"</span>, }); })

app.<span class="hljs-title function_">get</span>(<span class="hljs-string">'/secured'</span>, [keycloak.<span class="hljs-title function_">protect</span>(isAuthenticated)], <span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> { res.<span class="hljs-title function_">status</span>(<span class="hljs-number">200</span>).<span class="hljs-title function_">send</span>({ <span class="hljs-string">'message'</span>: <span class="hljs-string">"This is a secured enpoint which can be accessed by any authenticated user"</span>, }); })

app.<span class="hljs-title function_">get</span>(<span class="hljs-string">'/secured-admin'</span>, [keycloak.<span class="hljs-title function_">protect</span>(adminOnly)], <span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> { res.<span class="hljs-title function_">status</span>(<span class="hljs-number">200</span>).<span class="hljs-title function_">send</span>({ <span class="hljs-string">'message'</span>: <span class="hljs-string">"This is a secured enpoint which can be accessed only by any authenticated user with role admin"</span>, }); })

app.<span class="hljs-title function_">listen</span>(<span class="hljs-variable constant_">PORT</span>, <span class="hljs-function">(<span class="hljs-params">error</span>) =></span> { <span class="hljs-keyword">if</span> (!error) { <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">"Server is Successfully Running, and App is listening on port "</span> + <span class="hljs-variable constant_">PORT</span>) } <span class="hljs-keyword">else</span> { <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">"Error occurred, server can't start"</span>, error); } } );</pre></div><h2 id="a530">Update package.json scripts to run server</h2><ul><li>Update the content in the <b>scripts </b>section of <b>package.json</b> as below. It will help you run your express server in both development and production mode</li></ul><div id="6d0e"><pre> <span class="hljs-attr">"scripts"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span> <span class="hljs-attr">"start"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"node app.js"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"dev"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"nodemon app.js"</span> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span></pre></div><ul><li>Start your express server in development mode(auto-reload on file change) using the below command</li></ul><div id="464c"><pre>npm run dev</pre></div><h1 id="1699">Testing your REST APIs</h1><h2 id="f8a6">Public Endpoint— http://localhost:3000/public</h2><ul><li>Even without an authentication token, this endpoint will fetch a response.</li></ul><figure id="74df"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*xjvkOCdQJ5VIolwBtu-TWg.png"><figcaption></figcaption></figure><h2 id="f796">Secured Endpoint — http://localhost:3000/secured</h2><ul><li>Without a token, you should get an authentication error</li></ul><figure id="ad69"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*rSANl9_J1BRma6p1UjgLPg.png"><figcaption></figcaption></figure><ul><li>Let’s set up the <b>Authorization</b> tab to generate a token using the <b>Configure New Token </b>section. You can use the values below.</li></ul><div id="3d60"><pre>Token <span class="hljs-type">Name</span> - secure-express-service <span class="hljs-keyword">Grant</span> <span class="hljs-keyword">type</span> - <span class="hljs-keyword">Password</span> Credentials <span class="hljs-keyword">Access</span> Token URL - http://localhost:<span class="hljs-number">8080</span>/realms/master/protocol/openid-<span class="hljs-keyword">connect</span>/token Client ID - secure-express-service Username - <span class="hljs-keyword">user</span>@nerdcore.com <span class="hljs-keyword">Password</span> - Client Authentication - Send <span class="hljs-keyword">as</span> basic auth <span class="hljs-keyword">header</span></pre></div><figure id="5d0e"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*AEhl6BHxVPT5J6X6wKnxGg.png"><figcaption></figcaption></figure><ul><li>Click on <b>Get New Access Token</b>, then P<b>roceed</b>, then <b>Use Token</b></li></ul><figure id="ea60"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*t7pdQRYhqsnhK_NDBSD19g.png"><figcaption></figcaption></figure><figure id="55e0"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*MwMrf1npagIRpGmXEfOWcw.png"><figcaption></figcaption></figure><ul><li>Now fire the <b>/secured</b> rest endpoint again, and you will get a successful response.</li></ul><figure id="e106"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*xsq6E7TWbMeTHXzNEQMD1Q.png"><figcaption></figcaption></figure><h2 id="97a4">Secured Admin Endpoint — http://localhost:3000/secured-admin</h2><ul><li>If you try to access the endpoint without any token — Auth error</li><li>If you try to access the endpoint with the token from [email protected] — Auth error</li><li>If you try to access the endpoint with the token from [email protected] — Success</li></ul><p id="db11">You can find the GitHub repository <a href="https://github.com/saurav-samantray/secure-express-service">here</a> for reference.</p><p id="eda2">Happy learning and happy coding!</p></article></body>

Using Personal Access Tokens With A GitHub Organization

ACM.478 If you are using a personal access token a GitHub organization can help you manage those tokens more securely.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

⚙️ Check out my series on Automating Cybersecurity Metrics. The Code.

🔒 Related Stories: Application Security | Secure Code | Github Security

💻 Free Content on Jobs in Cybersecurity | ✉️ Sign up for the Email List

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In the last post I wrote about setting up an organization and an enterprise in GitHub.

Now I’m going to explain how to use personal access tokens in an organization if you are doing that. Whether or not you should be using tokens is a discussion for another day. I hope to be trying out some other options in future posts as time allows.

In order to use personal access tokens with an organization, you first have to click on personal access tokens on the left. Then you have to enroll in that functionality.

Restrict use of classic personal access tokens which are not fine grained tokens.

Click on Active Tokens in the settings menu for your organization. See the prior post for more on GitHub organizations and enterprises if you’re not familiar already.

Initially there are no tokens here and no way to create them. They need to be created by a user.

As you can see above I require an administrator to approve them when created.

Now what I can do is create a user that only has access to my test repositories not my production repositories, even if the user has access to all of them.

Click on your user on the top right of the screen.

Click Your profile in the menu.

Click on Settings.

Scroll down and click on Developer settings.

Generate a new fine-grained token.

Choose your organization.

Once you do that you can limit the permission to select repositories and actions.

I’ve written about limiting permissions in other posts.

In this case, I am going to limit permissions to my test repositories only and not grant the token that is developing the code permission to access the public repositories.

Next under permissions I can specify which actions I want this token to be able to perform. Note that I was very confused once when adding repositories and failed to select any permissions and the repository never got added to my account even though there was no error message telling me I did anything wrong. Make sure you select some permissions.

There’s also a section for organization permissions which you can configure if you are allowed to perform these actions.

To develop code I only really need these actions:

The metadata action is required by default.

You may need other things depending on what functionality your organization allows, uses, and your particular responsibilities, but if you are using a token only for working with code, limit your token to that. Create a separate token with no access to edit code but that has access to do other things if required that can be used for automation.

Click Generate token.

You’ll see a token below. Make sure you copy it and save it somewhere safe as you won’t be able to see it again once you close this screen.

The best thing to do is put it in something like AWS Secrets Manager and use it from there as I’ve written about before in other Git and GitHub posts which you can read via the above link.

Return to the organization settings and click on Personal Access Tokens. Now you can see the token I just created as a user.

If I was not an administrator then an administrator would have to authorize this token before I could use it. You may want to have separate people authorizing tokens from those who can use the tokens. I always try to design security so the person granting the access is not the one using the access to help make it harder for an attacker to have access to all the things.

You can click on the token, see what access and permissions the token has, and revoke the token if needed.

Of course you might want to automate some of this token evaluation with a script so you can easily find excessive permissions or scour the logs for sensitive actions at unexpected times or from unexpected locations, for example, possibly with the help of canaries.

One of the best sources to explain what canaries are is a company that specializes in services for creating and monitoring them. I saw the founder of this company speak at BlackHat one year and was very impressed, though I haven’t used the service.

Canaries have helped uncover some major breaches. Maybe a topic for another post later.

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2024

About Teri Radichel:
~~~~~~~~~~~~~~~~~~~~
⭐️ Author: Cybersecurity Books
⭐️ Presentations: Presentations by Teri Radichel
⭐️ Recognition: SANS Award, AWS Security Hero, IANS Faculty
⭐️ Certifications: SANS ~ GSE 240
⭐️ Education: BA Business, Master of Software Engineering, Master of Infosec
⭐️ Company: Penetration Tests, Assessments, Phone Consulting ~ 2nd Sight Lab
Need Help With Cybersecurity, Cloud, or Application Security?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
🔒 Request a penetration test or security assessment
🔒 Schedule a consulting call
🔒 Cybersecurity Speaker for Presentation
Follow for more stories like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
❤️ Sign Up my Medium Email List
❤️ Twitter: @teriradichel
❤️ LinkedIn: https://www.linkedin.com/in/teriradichel
❤️ Mastodon: @teriradichel@infosec.exchange
❤️ Facebook: 2nd Sight Lab
❤️ YouTube: @2ndsightlab
Github
Organization
Personal Access Token
Security
Git
Recommended from ReadMedium