Skip to main content

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.

info

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.com resolves to 127.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.

warning

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:

  1. Configure the reCAPTCHA secret key in Nidam.
  2. 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:

Google reCAPTCHA Configuration
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:

.env
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.

Registration Request Formats

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:

Nidam Default Rate Limiter Configuration
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 to false to 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.