Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/management/web/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Documentation related to how to use the web management ui.
- [[site-scoping|Site Scoping]]
- [[ldap|LDAP Authentication]]
- [[oidc|OpenID Connect Sign-in]]
- [[local-login|The Local Login Page]]
- [[ad-integration|Active Directory Integration]]

**Imaging Objects**
Expand Down
179 changes: 179 additions & 0 deletions docs/management/web/local-login.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
---
title: The Local Login Page
aliases:
- Local Login
- login.php
- Break-glass Login
- Emergency Login
- Backdoor Login
- Bypass SSO Login
description: One URL that always shows FOG's own username and password form, whatever your identity provider is doing
context_id: local-login
tags:
- 1_6-changes
- management
- users
- security
- oidc
- ldap
- web-ui
- web-management
---

# The Local Login Page

## The URL

```
https://fog.example.com/fog/management/login.php
```

This page **always** shows FOG's own username and password form. It cannot
be redirected to an identity provider, it does not consult one, and no
plugin can change that.

>[!note] This page describes FOG 1.6
>`management/login.php` landed during 1.6 development. On 1.5 there is no
>equivalent, and no setting that would need one.

Bookmark it now, before you need it. Somebody locked out of a FOG server is
in no position to go looking for a URL, and this is not one you would guess.

## Why it exists

FOG can be configured to send everyone straight to an identity provider —
see [[oidc#Sending everyone straight to the provider|Sending everyone straight to the provider]].
On an install where every account lives at the provider, that is the right
setting: FOG's password box cannot accept those credentials, so all it does
is add a click.

It is also the setting that can lock every administrator out of a server at
once. If the provider becomes unreachable, its certificate expires, its
client secret is rotated, its discovery document breaks, or its issuer was
mistyped, then a login page that unconditionally redirects has no way back
— including for the local account that exists for exactly this situation.

`login.php` is the way back.

## What it does and does not do

| | |
|---|---|
| **Does** | Show FOG's normal login form and sign you in with a local username and password |
| **Does** | Keep working when your identity provider is down, misconfigured, or removed |
| **Does not** | Bypass any password check, permission, role, or site scope |
| **Does not** | Let an account owned by a provider sign in with a password — that account has no local password to use |
| **Does not** | Offer the provider buttons, because on a broken provider they are what you are escaping |

It is the **same** login. Same form, same session, same CSRF protection,
same audit trail, same [[roles|roles]]. The only difference is where the
page will and will not send you.

>[!warning] It is not a way around authentication
>The name "break-glass" describes when you reach for it, not what it
>relaxes. Everything still has to be a valid FOG account with a valid
>password, and everything it can do is still governed by its roles. There
>is nothing here to protect that the login form does not already protect.

## Who can actually use it

An account can sign in here if it has a **local password**. In practice:

- **Accounts an administrator created** — yes, always. Creating an account
in FOG sets a password, and signing into it through a provider later does
not take that password away.
- **Accounts FOG provisioned** (created on first sign-in by
[[oidc#Who is allowed in|Create Users On First Login]], or by
[[ldap|LDAP]]) — **no**. They are created with a random token nobody has
ever seen, so there is no password to type. They can only be reached
through the directory that made them.

That distinction is the whole of your break-glass plan, and it is worth
checking rather than assuming.

## Make sure at least one account can use it

FOG enforces a floor, and you will meet it as a refusal:

- You **cannot delete** the last administrator who can sign in with a local
password, even when other administrators exist through a directory.
- You **cannot convert** that account to an external identity either.

Both are refused with *"This would leave no account able to administer FOG
without its identity provider."* To get past either, give another
administrator account a local password first.

The floor preserves; it does not require. An install that has deliberately
moved every administrator to a directory has nothing left for this to
protect, and FOG will not start refusing that install's operations to
defend a property it already gave up. **If that is your install, this page
will not help you** — so decide on purpose rather than by drift.

>[!note] Check it before you need it
>Sign out, open `login.php`, and log in with a local administrator account.
>Do it once, now, and again whenever you change how people sign in. A
>break-glass plan nobody has tested is a plan you find out about during the
>outage.

## Why it is safe to leave reachable

An obvious worry: if this page ignores the redirect, is it a way around
single sign-on?

No. Removing the redirect does not remove a *check*. The redirect is a
convenience — it saves a click for people whose credentials live at the
provider. What decides whether somebody gets in is the password and the
roles, and those are identical on both pages. Somebody with no FOG account
and no FOG password gets nothing here, exactly as they get nothing on
`index.php`.

If you need people to be *unable* to sign in with a password, that is a
different control: give those accounts an external identity, which removes
their local password. Do that per account. Do not rely on the login page
being hard to reach.

## How the guarantee is built

Worth knowing, because it explains why this page keeps working when the
thing that broke is the plugin itself.

FOG's login page offers plugins one opportunity to redirect an anonymous
visitor somewhere else. `login.php` marks the request as a local login
before FOG's login page runs, and the login page only offers that
opportunity when the mark is **absent**.

So on this URL a plugin is not asked and then overruled — **it is never
asked at all**. A plugin that is misconfigured, half-installed, throwing
errors, or in the middle of failing to reach a provider cannot take this
page down with it, because nothing on this page calls into it.

It is also not a second copy of the login form. `login.php` reuses the real
one, so it cannot drift from it and a fix to one is a fix to both.

## When FOG sends you here by itself

You will also arrive here without asking, in two situations. Both are cases
where returning to the normal login page would bounce you back out to a
provider that cannot help:

- **A sign-in was refused.** The reason is shown on this page. Returning to
a provider that just said no would be a loop.
- **You logged out on an install that redirects to a provider, with
[[oidc#Signing out|Single Logout]] off.** Your provider session is still
alive, so the normal login page would sign you straight back in. You are
signed out of FOG; you are still signed in at the provider.

With Single Logout **on**, logging out does not land you here — the
provider session is genuinely ended, so FOG returns you to the normal login
page and the provider asks for credentials.

## Related

- [[oidc|OpenID Connect Sign-in]] — the redirect setting this page exists
to survive, and where to turn it on
- [[oidc#Break-glass|OIDC break-glass rules]] — which accounts keep a local
password
- [[ldap|LDAP Authentication]] — the other directory FOG can provision
accounts from
- [[users|User Management]] — where to give an administrator a local
password
130 changes: 130 additions & 0 deletions docs/management/web/oidc.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ aliases:
- Entra ID Login
- Keycloak Login
- Google Workspace Login
- Single Logout
- Forced SSO
description: How the OpenID Connect plugin lets people sign in to FOG with an identity provider, and which role each one receives
context_id: oidc
tags:
Expand Down Expand Up @@ -58,6 +60,8 @@ turn off — see [[#Break-glass]].
| **Username Claim** | Which claim names the FOG account. Defaults to `preferred_username` |
| **Group Claim** | Which claim carries group membership. Defaults to `groups` |
| **Enabled** | Off until you switch it on |
| **Single Logout** | Signing out of FOG also ends the session at the provider. Off by default — see [[#Signing out]] |
| **Redirect Login To This Provider** | Send everyone straight to the provider instead of showing FOG's login form. Off by default — read [[#Sending everyone straight to the provider]] before ticking it |

You do not enter the authorization, token or key endpoints. FOG reads
them from `<issuer>/.well-known/openid-configuration` on every sign-in,
Expand Down Expand Up @@ -322,13 +326,134 @@ Deleting a mapping revokes it too, at everyone's next sign-in. FOG keeps
a record of what it granted each person precisely so that removing a
mapping does what it looks like it does.

## Signing out

By default, **Log out** ends FOG's session and nothing else. Your provider's
own session is untouched, so clicking the provider button again signs the
same person straight back in with no prompt. That is the standard behaviour
of single sign-on and is often what people expect.

It is a problem in one case: an account owned by a provider cannot sign in
with a local password, so on a shared computer there is no way to hand over
to somebody else short of clearing cookies.

Tick **Single Logout** on the provider to end the provider's session too.
It ships **off**, deliberately: it is only the right answer where FOG is
the only application behind that provider. If you share an identity
provider with your mail, your ticket system and your VPN, then signing out
of FOG signing people out of all of them is a surprise reaching
applications FOG has nothing to do with.

### Register the post-logout redirect URI

The provider needs to know where to send people after it ends their
session, and — like the sign-in redirect URI — it will only accept a value
you have registered in advance. Most providers refuse an unregistered one
and show their own error page instead of coming back, which looks exactly
like FOG being broken.

FOG shows the exact value on the provider's page, next to the setting.
Copy it from there. It looks like:

```
https://fog.example.com/fog/management/index.php
```

Where to put it: **Keycloak** — the client's *Valid post logout redirect
URIs*. **Entra ID** — the app registration's *Front-channel logout URL*.
**Okta** — the application's *Sign-out redirect URIs*.

>[!warning] This value changed in plugin v1.6.10
>On v1.6.9 it was `…/management/login.php`. If you turned Single Logout on
>at that version, re-register the new value — providers that follow the
>spec refuse an unregistered one and show their own error page instead of
>coming back to FOG.

That is FOG's ordinary login page, and on an install that also has the
redirect below turned on it sends you back to the provider. That is the
point: the provider session was just ended, so it asks who you are instead
of waving you through. Signing out and signing in as somebody else is one
journey.

If the provider publishes no `end_session_endpoint`, FOG cannot do this at
all. It logs that to the web server's error log and signs you out of FOG
only, which is otherwise indistinguishable from the setting being off.

## Sending everyone straight to the provider

On an install where every account lives at your provider, FOG's username
and password box is a dead end — it cannot accept those credentials, so all
it does is add a click. Tick **Redirect Login To This Provider** and an
anonymous visitor goes straight to the provider instead.

>[!warning] Read this before you tick it
>This setting can lock every administrator out of your server. If the
>provider becomes unreachable, its certificate expires, its client secret
>is rotated, or its issuer was mistyped, a login page that unconditionally
>redirects has no way back through a browser.
>
>**The way back is [[local-login|The Local Login Page]]:**
>`https://fog.example.com/fog/management/login.php`, which always shows
>FOG's own form and can never be redirected. FOG prints that URL next to
>the checkbox. Bookmark it, and confirm a local administrator can sign in
>there, before you turn this on.

It ships **off**, and a newly created provider always has it off.

Three things it deliberately does not do:

- **It does not affect anyone already signed in.** The redirect happens
only when an anonymous visitor is about to be shown the login form.
- **It does not interfere with the sign-in coming back.** The callback is a
different route and is never redirected.
- **It does not trap you in a loop when the provider refuses.** A failed
sign-in lands on the local login page with the reason attached, rather
than bouncing straight back out to the provider that just said no.

### Two providers cannot both do it

If more than one enabled provider has this ticked, FOG **refuses to
redirect at all** and shows its normal login form, naming the providers
involved in the web server's error log.

That is on purpose. The login page cannot redirect to two places, and
silently picking one would send everybody to a provider that was never
chosen — on the one page you are least able to debug. Showing the form is a
working login for everybody and visibly not what you asked for.

If you want this behaviour, pick one provider and untick the others.

### Logging out with this on

**Turn [[#Signing out|Single Logout]] on as well.** With both on, signing
out ends the provider session and returns you here, which sends you back to
the provider — and because its session is genuinely gone, it asks for
credentials. That is the behaviour people expect from "log out".

If Single Logout is **off**, that same journey would sign you straight back
in: your provider session is untouched, so the redirect is answered
silently. FOG avoids that by sending you to
[[local-login|the local login page]] instead. You are signed out of FOG,
still signed in at the provider, and looking at a form rather than back
where you started — correct, but a little surprising, and the reason to
turn Single Logout on.

A **failed** sign-in always lands on the local login page too, whatever
these settings say. Bouncing back to a provider that just refused you is a
loop.

## Break-glass

**Local password login can never be turned off.** There is no setting
for it. That is deliberate: an expired client secret, a mistyped issuer
or a provider outage must not be able to lock you out of your own
server.

It has its own page, because it is the thing to reach for when everything
here has gone wrong: [[local-login|The Local Login Page]], at
`https://fog.example.com/fog/management/login.php`. That URL always shows
FOG's own form and can never be redirected to a provider.

Two rules back it up, and you will meet them as refusals:

- **You cannot delete the last administrator who can sign in with a
Expand Down Expand Up @@ -387,6 +512,11 @@ administrator made keeps whatever API setting it already had.
| *Unknown identity provider*, on a provider that is configured and enabled | The provider row failed validation, or the sign-in URL arrived without its `?provider=` parameter. Both were fixed during 1.6 development; update the server and the bundled plugins. |
| *That identity provider is not enabled* | Checked on the way back as well as on the way out, so disabling a provider ends sign-ins already in progress. |
| Signs in fine but sees nothing | No mapped group, or the group value does not match what the provider sends. See [[#Getting the group values right]]. |
| The login page never appears — it always goes to the provider | **Redirect Login To This Provider** is on. Use [[local-login\|the local login page]] to get in and untick it. |
| The login page still appears although the redirect is ticked | More than one enabled provider has it ticked, so FOG refused to choose. Check the web server's error log; untick all but one. |
| Logging out leaves you signed in — the provider button lets you straight back | **Single Logout** is off. That is the default. |
| Log out ends at the provider's error page instead of returning to FOG | The post-logout redirect URI is not registered at the provider. See [[#Register the post-logout redirect URI]]. |
| Log out signs you out but does not end the provider session, with **Single Logout** on | The provider publishes no `end_session_endpoint`. FOG logs this to the web server's error log. |

Anything the person in the browser should not see — a signature failure,
an unreachable endpoint, a refused subject — is written to the web
Expand Down