Features
HTTPS
Nidam supports HTTPS. Assuming your host is yourhost.nidam, configure it as follows.
1. Add the certificate files
Place the PEM-encoded certificate and private key for yourhost.nidam in Nidam's https folder.
Rename them to:
https/
├── host.pem
└── host-key.pem
host.pem should contain the server certificate (including the certificate chain, when applicable), while host-key.pem contains the corresponding private key.
2. Enable HTTPS in configuration.yml
Change the host to use https and set Nidam's protocol to https:
host: https://yourhost.nidam
nidam:
protocol: https
3. Update your frontend and backend URLs
Any application that communicates with Nidam must also use https.
For example, in the Next.js frontend from the introduction page:
NEXT_PUBLIC_REVERSE_PROXY_URI=https://yourhost.nidam:7080
And in the Node.js Express backend:
const ISSUER = "https://yourhost.nidam:7080/auth";
Make sure you update any other Nidam URLs in your frontend or backend from http to https as well.
4. Start Nidam
Start Nidam normally. Nidam will use the certificate and private key from the https folder to serve HTTPS.
By default, Nidam communicates with your custom backend and frontend over http:
# Custom backend
resource-server-origin: http://backend.nidam
# Custom frontend
react-origin: http://frontend.nidam
If your custom backend and frontend are also served over HTTPS, simply change their origins to https:
resource-server-origin: https://backend.nidam
react-origin: https://frontend.nidam
Nidam will then communicate with those services over HTTPS. No additional Nidam configuration is required.
nidam.protocol controls HTTPS for Nidam's own reverse proxy service, while the protocol in resource-server-origin
and react-origin controls how Nidam connects to your custom backend and frontend.
Playing With a Local Certificate
This section is for users who want to test Nidam with HTTPS locally, using a local domain name and a locally trusted certificate.
The example below uses Windows. The same idea applies to other operating systems, but the commands and certificate locations may differ.
1. Create a local domain
Let's say we want Nidam to be available at:
https://nidam.com:7080
For local testing, nidam.com does not need to be a real public domain. We can simply make it resolve to 127.0.0.1 on our computer.
On Windows, I'm using PowerToys to manage the Hosts file:
Address: 127.0.0.1
Hosts: nidam.com
This means that when you open https://nidam.com in your browser, your computer sends the request to your local machine.
Nidam must also be configured to use the same host:
host: https://nidam.com
nidam:
protocol: https
2. Create a local certificate
I'm using mkcert to create a locally trusted certificate for nidam.com.
First, install mkcert:
winget install FiloSottile.mkcert
Then create and install mkcert's local Certificate Authority:
mkcert -install
This creates a local CA and adds it to Windows' trusted certificates.
Now generate a certificate for nidam.com:
mkcert nidam.com
The command creates two PEM files in the folder where you run it:
nidam.com.pem
nidam.com-key.pem
These are the certificate and private key that Nidam will use.
The previous HTTPS section explains how to place them in Nidam's https folder and rename them to:
host.pem
host-key.pem
3. Make Nidam trust the local Certificate Authority
Nidam is a Java application, so its Java runtime must trust the CA created by mkcert.
Run the following command in PowerShell as Administrator:
runtime\bin\keytool.exe -importcert -trustcacerts -alias mkcert-local -file "$env:LOCALAPPDATA\mkcert\rootCA.pem" -cacerts
mkcert stores its root CA here:
C:\Users\YOURNAME\AppData\Local\mkcert\rootCA.pem
You can verify that the CA was added to Nidam's Java truststore:
runtime\bin\keytool.exe -list -cacerts -alias mkcert-local
Nidam can now trust certificates issued by mkcert, including the certificate you created for nidam.com.
4. Make your custom backend trust the same CA
Your custom backend also needs to trust mkcert's CA when it communicates with Nidam over HTTPS.
For example, if you are using the Node.js Express backend from the introduction page, set NODE_EXTRA_CA_CERTS before starting it:
$env:NODE_EXTRA_CA_CERTS = "C:\Users\YOURNAME\AppData\Local\mkcert\rootCA.pem"
npm start
Your backend can now trust certificates issued by mkcert.
When using a different language or framework, the exact configuration will depend on that platform. Look up how to add a custom Certificate Authority to its trust store.
For example, if your backend is also a Java application but you run it with a separately installed JDK, that JDK needs to trust mkcert's CA as well. In that case, repeat the same truststore step for that Java installation.
5. Start Nidam with HTTPS
At this point, everything is in place:
nidam.comresolves to127.0.0.1- You have a certificate and private key for
nidam.com - Nidam's Java runtime trusts mkcert's local CA
- Your custom backend trusts the same CA
Now follow the steps in the previous HTTPS section to configure the certificate files and start Nidam.
You should then be able to access Nidam locally at:
https://nidam.com:7080
Note: This setup is intended for local testing. mkcert creates certificates trusted by your local machine; it does not provide a publicly trusted certificate for internet users.
nidam.com is a real domain owned and operated by its respective owner. It is not affiliated with Nidam, the software described in this documentation.
The domain is used here purely as an example because the name happens to be taken.
Google reCAPTCHA
Nidam supports Google reCAPTCHA v3 to help protect user registration from automated abuse.
Integrating reCAPTCHA requires two steps:
- Configure the reCAPTCHA secret key in Nidam.
- Update your frontend's signup page to obtain a reCAPTCHA token and send it to Nidam when registering a user.
The following example demonstrates how reCAPTCHA is implemented in Nidam SPA. You can adapt the same approach to your own frontend, regardless of the framework you use.
1. Configure Nidam
Configure your Google reCAPTCHA secret key in Nidam's configuration.yml:
recaptcha-secret: "your-secret-key-here"
2. Configure the Frontend
The frontend uses the reCAPTCHA site key, which is different from the secret key configured in Nidam.
In Nidam SPA, the site key is defined in the .env file:
REACT_APP_RECAPTCHA_KEY=your-site-key-here
The Nidam SPA reads this value through CONFIG.RECAPTCHA_KEY.
3. Load the reCAPTCHA Script
When the signup page loads, Nidam SPA loads Google's reCAPTCHA script if reCAPTCHA is enabled. It also handles script-loading failures, such as when the browser cannot reach Google's servers.
useEffect(() => {
const script = document.createElement('script');
script.src = `https://www.google.com/recaptcha/api.js?render=${CONFIG.RECAPTCHA_KEY}`;
script.class = "external-script"
script.async = true;
script.defer = true;
script.onerror = () => {
console.error("Failed to load reCaptcha");
setShowRecaptchaError(true);
};
document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, []);
4. Obtain a reCAPTCHA Token
When the user clicks the registration button, the frontend first requests a reCAPTCHA token. If the reCAPTCHA script has not loaded, registration is stopped and an error is displayed.
const executeReCaptcha = (e) => {
e.preventDefault();
if(window.grecaptcha === undefined ){
setShowRecaptchaError(true);
return;
}
window.grecaptcha.ready(function() {
window.grecaptcha.execute(CONFIG.RECAPTCHA_KEY, {action: 'submit'})
.then(token => register(token))
});
}
The token returned by grecaptcha.execute() is then passed to the register function.
5. Send the Token to Nidam
The register function includes the reCAPTCHA token in the registration request, under the recaptchaKey field:
const register = token => {
const user = {
email: email.value,
password: password.value,
recaptchaKey: token
}
dispatch(registerSagas.register(user));
}
The registration saga sends the user object to Nidam's /registerCaptcha endpoint:
const response = yield registerAxios.post('registerCaptcha', action.user);
6. Nidam Verifies the Token
After receiving the request, Nidam uses the configured secret key and the submitted reCAPTCHA token to verify the request with Google's reCAPTCHA service.
If Google's response contains success: true, Nidam proceeds with user registration. Otherwise, Nidam rejects the registration request with HTTP 400 Bad Request.
Registration Endpoints
The Nidam Registration Service exposes two registration endpoints, depending on whether Google reCAPTCHA is enabled for the request.
Without Google reCAPTCHA
Send a POST request to /register with the following JSON body:
const user = {
email: '',
password: ''
};
With Google reCAPTCHA
Send a POST request to /registerCaptcha with the following JSON body:
const user = {
email: '',
password: '',
recaptchaKey: ''
};
The recaptchaKey field must contain the token obtained from Google's reCAPTCHA client-side API, not the site key or secret key itself.
Custom Login Page
Nidam provides a default /login page, but you are not limited to its appearance. You can replace it with your own login.html and customize
its associated assets, including CSS, JavaScript, images, and fonts.
Your custom login page files belong in the token-generator-ui directory located in Nidam's root folder. However, the HTML
must follow a few requirements to work correctly with Nidam's authentication flow.
The easiest way to understand these requirements is to start with one of the examples provided by Nidam.
1. Download an Example
Head to the Nidam Login Page Examples repository directory. For this walkthrough, we will use variant-3.
Download the contents of the variant-3 directory.
The example contains a template directory, which holds login.html, and a static directory, which contains the page's assets.
2. Copy the Files into Nidam
Copy login.html into the following directory:
NIDAM_FOLDER/
└── token-generator-ui/
├── templates/
│ └── login.html
└── static/
├── css/
├── images/
└── js/
Copy the corresponding assets into their respective directories. For example, place login.css under static/css,
JavaScript files under static/js, and images under static/images.
You are not restricted to these directory names. You can create additional directories under static as needed,
provided that you reference their assets correctly in login.html.
Before copying the example's files, let's look at the requirements your custom login page must satisfy.
3. Use the Required HTML Namespaces
Your login.html must declare the following XML namespaces on its root <html> element:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
The th namespace enables Thymeleaf attributes, which Nidam uses to process the login page and resolve asset paths.
4. Reference Assets Using Thymeleaf
Because the login page is processed by Thymeleaf, you must use Thymeleaf expressions to reference static assets.
For example, reference a CSS file like this:
<link th:href="@{/css/login.css}" rel="stylesheet"/>
For an image used as the page's favicon:
<link th:href="@{/images/nidam-svg.svg}" rel="icon" type="image/svg+xml"/>
For a JavaScript file:
<script th:src="@{/js/login.js}"></script>
Notice the th: prefix and the @{...} expression surrounding each asset path. These tell Thymeleaf how to resolve the resource.
The paths above correspond to files stored under token-generator-ui/static. For example, /css/login.css resolves to token-generator-ui/static/css/login.css.
You can use the same format for assets in any additional directories you create under static.
5. Follow the Login Form Requirements
Your login form must follow Nidam's expected form structure so that the authentication process works correctly.
The form must submit a POST request to /login:
<form th:action="@{/login}" method="post">
The email input must use username as its name attribute:
<input type="email" name="username"/>
Although the input represents an email address, its name must be username because that is what Nidam's authentication process expects.
The password input must use password as its name attribute:
<input type="password" name="password"/>
The login button must have type="submit":
<button type="submit">Sign In</button>
These requirements are mandatory. You can customize the form's appearance and surrounding HTML, but you must preserve the form's submission method, action, input names, and submit button behavior.
6. Display Login Errors
You can display authentication errors by including the following Thymeleaf element in your page:
<div th:if="${LOGIN_ERROR}">
<span th:text="${LOGIN_ERROR}"></span>
</div>
The element is displayed only when LOGIN_ERROR contains a value. Nidam uses it to communicate login failures, such as invalid
credentials or reaching the maximum number of failed login attempts when rate limiting is enabled.
You can style this element to match the design of your login page.
7. Start Nidam
Once you have copied the files into the appropriate directories, start Nidam. If Nidam is already running, restart it so that the changes take effect.
Nidam will then use your custom login page instead of the default /login page.
My recommendation: Get the variant-3 example working first, then use it as a starting point for your own design.
This lets you verify that the template, static assets, form submission, and error handling all work correctly before introducing your own changes.
Login Rate Limiter
Nidam includes a built-in login rate limiter to help protect against brute-force attacks by limiting repeated failed login attempts.
Configuration
The rate limiter is enabled by default. You can customize its behavior in configuration.yml:
rate-limiter:
enabled: true
max-attempts: 5 # Allow 5 failed attempts
lockout-duration: 5 # Block for 5 minutes
cleanup-interval-ms: 60000 # Cleanup interval in milliseconds
The configuration properties control the following behavior:
enabled— Enables or disables the rate limiter. Set it tofalseto disable rate limiting.max-attempts— The maximum number of failed login attempts allowed before the user is blocked.lockout-duration— The number of minutes a user is blocked after reaching the maximum number of failed login attempts.cleanup-interval-ms— How often, in milliseconds, Nidam removes expired records from its tracking data. The default value,60000, corresponds to one minute.
How It Works
Nidam tracks failed login attempts using the combination of the submitted email and the client's IP address.
Each combination is treated as a separate identifier, formed as follows:
username + "|" + IP
Once the configured maximum number of failed attempts is reached, further login attempts for that username and IP address combination are blocked for the configured lockout duration.
The cleanup process periodically removes expired tracking records, preventing outdated entries from accumulating indefinitely.
You can adjust these settings to suit your application's security requirements or set enabled: false to disable the rate limiter entirely.