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>