iRonShore Technologies / Lighthouse docs Version 0.37.0

Setting up a sign-in provider

Settings, Sign-in in the console does all of this except the provider's own side: add the provider, paste its address, client ID and secret, map groups, and test it. The steps below say what to do at each provider, and what the page's fields mean if you set it up in lighthouse.json instead.

Lighthouse signs people in with Windows, with any OpenID Connect provider, or both. The settings are described in Running the server; this page is the step-by-step for the providers people ask about most. Each one ends with the part to paste into signInProviders in %ProgramData%\Lighthouse\lighthouse.json and the secret to store.

Every provider needs the same three things from you:

  1. Redirect URI: https://<lighthouse host>/signin-oidc/<id>, where <id> is the provider's id in Lighthouse (adfs, entra, okta). Settings > Application lists it once the provider is configured.
  2. Who may sign in: a group mapped to the operators or viewers group, or groups that teams list as members. Signing in alone gives no access.
  3. The server must reach the provider over HTTPS to read its metadata and exchange the code. The browser goes to the provider too, but the server-to-provider call is the one firewalls usually block.

After editing lighthouse.json, store the client secret and restart the IIS site or service:

lh secret set signin-<id>

If sign-in cannot start (a wrong secret, an unreachable provider), the sign-in page says which and why.

One main sign-in. Opening Lighthouse goes straight to the main sign-in (primarySignIn), so nobody chooses. A new install sets it on the setup screen Main sign-in: pick the provider and enter its address, client ID and client secret, and setup writes the provider and stores the secret for you. Windows sign-in stays as another way in, under Other ways to sign in or at /signin?other=true. See Running the server.

Signing back in after a timeout. A session ends after 30 minutes without use, and after 12 hours however much it is used; administrators change both on Settings, Sign-in, Sessions (see docs/server.md, Sessions). After a timeout the sign-in page says why and waits for a click, so nobody is signed straight back in. Turn on ask for the password again there to have AD FS, Okta, Entra ID and other providers ask for the password then (prompt=login) even while their own session is alive. Lighthouse remembers in the browser the way someone last signed in (the cookie lighthouse-signin holds only windows or the provider's id, nothing secret, for 400 days), and signing in again goes straight back to it instead of to the main sign-in. With AD FS, Okta or another provider whose own session is still alive, the browser goes there and back without a prompt; otherwise the provider's own sign-in page shows. With Windows sign-in the browser answers by itself where it trusts the site for Windows sign-in. A remembered way that has been turned off or removed falls back to the main sign-in. When the session ends while the console is open, the console's requests get 440 instead of 401, so IIS does not add its Windows challenge and the browser does not open its own user name and password box.

AD FS (on-premises Active Directory)

The quickest real test when AD FS is already running, and the best fit for shops that stay on AD. With windowsNames, people who sign in through AD FS get the same names and groups as with Windows sign-in (EXAMPLE\alice, EXAMPLE\Lighthouse Operators), so every grant and team keeps working. Needs AD FS on Windows Server 2016 or later.

In AD FS Management:

  1. Application Groups > Add Application Group, name it Lighthouse, template Server application accessing a web API.
  2. Server application: copy the Client Identifier. Add the redirect URI https://<lighthouse host>/signin-oidc/adfs.
  3. Configure Application Credentials: tick Generate a shared secret and copy it.
  4. Configure Web API: add the Client Identifier from step 2 as the identifier, so the claims below go into the ID token.
  5. Access control policy: Permit specific group with the group of people who use Lighthouse, or Permit everyone.
  6. Configure Application Permissions: tick openid, profile, email and allatclaims.
  7. Open the Web API's Issuance Transform Rules and add:
    • Send LDAP Attributes as Claims, store Active Directory: User-Principal-Name to UPN, Token-Groups - Qualified by Domain Name to Group.
    • Pass Through or Filter an Incoming Claim: Windows account name, pass through all values.

In Lighthouse:

{
  "id": "adfs",
  "name": "AD FS",
  "authority": "https://<ad fs host>/adfs",
  "clientId": "<client identifier>",
  "scopes": ["allatclaims"],
  "windowsNames": true
}

With windowsNames on, Lighthouse asks AD FS for the client identifier as the resource, so AD FS applies the Web API's rules from step 7. Without a resource AD FS sends only its default claims: the user arrives with a name but no groups, and the sign-in page says they have no access. If your Web API's identifier is not the client identifier, give it as "resource".

lh secret set signin-adfs with the shared secret. The Lighthouse server must trust the AD FS server's HTTPS certificate (it normally does when both are domain-joined and the certificate comes from the domain's CA).

Leave windowsNames out for any provider that is not the authority on your domains: with it on, a provider can sign someone in as any DOMAIN\name it sends.

Microsoft Entra ID

For shops on Microsoft 365. A free Entra tenant is enough to test: any Azure account has one (portal.azure.com > Microsoft Entra ID).

In the Microsoft Entra admin center (entra.microsoft.com):

  1. App registrations > New registration. Name Lighthouse, Accounts in this organizational directory only, redirect URI platform Web, https://<lighthouse host>/signin-oidc/entra.
  2. From Overview, copy the Application (client) ID and Directory (tenant) ID.
  3. Certificates & secrets > New client secret. Copy the value (not the ID). Note when it expires.
  4. Token configuration > Add groups claim > Security groups, ID token Group ID.
  5. Create a security group such as Lighthouse Operators, add yourself, and copy its Object ID.

In Lighthouse:

{
  "id": "entra",
  "name": "Microsoft Entra ID",
  "authority": "https://login.microsoftonline.com/<tenant id>/v2.0",
  "clientId": "<application (client) id>",
  "groups": { "<object id of Lighthouse Operators>": "EXAMPLE\\Lighthouse Operators" }
}

lh secret set signin-entra with the secret value. The server needs outbound HTTPS to login.microsoftonline.com. People appear as ENTRA\[email protected]; a team can list them that way or list an Entra group as ENTRA\<object id>. Someone in more than 200 groups gets no groups claim; for them, use app roles (App roles, assigned under Enterprise applications), which arrive as roles.

Okta

Tested against a real Okta Workforce org (2026-10-20). A free Okta Integrator (developer) account works for testing (developer.okta.com). Okta's screens change often; these steps match the Admin Console as of October 2026.

In the Okta Admin Console:

  1. Directory > Groups > Add group: Lighthouse Operators (and Lighthouse Viewers if you want one). Add the people who use Lighthouse.
  2. Applications > Applications > Create App Integration: OIDC - OpenID Connect, then Web Application.
    • Client definition: Use Okta-generated client ID.
    • Grant type: Authorization Code only.
    • Sign-in redirect URI: https://<lighthouse host>/signin-oidc/okta. Delete the sign-out redirect URI Okta fills in.
    • Controlled access: Limit access to selected groups, with the groups from step 1. Not "Skip group assignment".
  3. From the app's General tab, copy the Client ID and Client secret.
  4. Security > API > Authorization Servers > default > Claims > Add Claim: name groups, include in ID Token, Always; value type Groups; filter Starts with Lighthouse (use Matches regex .* only in a small org: Okta sends no groups to someone in more than 100); include in Any scope.
  5. Same server, Access Policies > Add New Access Policy: name Lighthouse, assigned to The following clients: the Lighthouse app. Then Add Rule: grant type Authorization Code, Any user assigned the app, Any scopes. Without this policy Okta shows "You are not allowed to access this app" after the password and MFA, and its System Log shows no_matching_policy.

In Lighthouse (Settings, Sign-in, add Okta), or in lighthouse.json:

{
  "id": "okta",
  "name": "Okta",
  "authority": "https://<your org>.okta.com/oauth2/default",
  "clientId": "<client id>",
  "groups": { "Lighthouse Operators": "EXAMPLE\\Lighthouse Operators" }
}

Leave Extra scopes empty: the default authorization server has no groups scope and refuses a request for one. Store the secret (lh secret set signin-okta, or the page's Client secret field). The server needs outbound HTTPS to your Okta org.

A successful test lists the user as OKTA\[email protected] with OKTA\<group> for each Okta group, plus the Lighthouse group each mapped one stands for. If the mapped group is missing from that list, the Groups line was not saved. Give access through groups rather than by adding people one by one: an Okta login can change when someone's email does. Sign out ends the Lighthouse session only; the person stays signed in to Okta, so the next sign-in goes straight through.

Trying it without a provider of your own (Keycloak)

Keycloak is free and runs on any PC with Java 21: download it from keycloak.org, run bin/kc.sh start-dev --http-port 8080 (bin\kc.bat on Windows) and create a realm, a confidential client with the redirect URI, users, groups and a Group Membership mapper named groups (full group path off). Lighthouse accepts an http://localhost authority for this, and nothing else over plain HTTP. Lighthouse itself must run over HTTPS for the sign-in cookies to work in a browser.

{ "id": "keycloak", "name": "Keycloak", "authority": "http://localhost:8080/realms/lab", "clientId": "lighthouse",
  "groups": { "lighthouse-operators": "EXAMPLE\\Lighthouse Operators" } }