Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

Forgejo : brancher un fournisseur OIDC et imposer le 2FA

Par mis à jour le

Améliorer cette page

Pour que les utilisateurs se connectent à Forgejo 15 avec leur compte du fournisseur d'identité, on déclare Keycloak comme source d'authentification OpenID Connect (OIDC) avec forgejo admin auth add-oauth, on règle ce qui arrive à un premier visiteur, puis on exige un second facteur. OIDC est le protocole qui laisse un service tiers, ici Forgejo, déléguer la vérification du mot de passe à un fournisseur d'identité, ce qu'on appelle l'authentification unique (SSO, Single Sign-On). Cette leçon s'adresse à l'administrateur dont la forge tourne déjà et qui gouverne ses comptes depuis un annuaire central.

Vous repartez avec quatre preuves : une source listée par admin auth list, un utilisateur rangé dans l'équipe acme/devops par son groupe Keycloak, une redirect URI que Keycloak refuse dès qu'elle diffère d'un caractère, et un compte sans second facteur bloqué par GLOBAL_TWO_FACTOR_REQUIREMENT. Les commandes ont été exécutées sur Forgejo 15.0.10 et Keycloak 26.7.0, AlmaLinux 10, avec la pile de la leçon Installer Forgejo LTS.

  • Placer Keycloak derrière le même proxy que Forgejo et faire confiance à son autorité de certification.
  • Déclarer une source OIDC en ligne de commande, avec découverte automatique.
  • Choisir le comportement de la première connexion : lier, refuser ou créer le compte.
  • Mapper un groupe du fournisseur d'identité sur une équipe d'organisation.
  • Imposer le second facteur à tous, ou aux seuls administrateurs.
  • Diagnostiquer les trois pannes classiques : redirect URI, liaison de compte, découverte.

Il vous faut la forge des leçons précédentes : Forgejo 15 LTS derrière Caddy dans /opt/forgejo-lab, le nom forge.lab.test, le compte administrateur fjadmin (installation), les réglages d'instance (configuration initiale) et l'organisation acme (organisations, équipes et droits). Cette dernière annonçait que les équipes alimentées par un fournisseur d'identité demandaient une autre procédure : la voici.

Côté fournisseur d'identité, vous devez savoir ce qu'est un realm, un client et une redirect URI : la leçon Sécuriser une application avec Keycloak les explique, et Installer Keycloak donne l'installation de référence. Pour le protocole lui-même, voir OpenID Connect. Cette leçon ne refait pas la création d'un client ; elle donne les valeurs que Forgejo exige.

Deux précautions de lab. Les comptes alice, bob et carol de la leçon précédente portent les noms des identités Keycloak utilisées ici : supprimez alice et bob avec sudo docker exec -u git forgejo forgejo admin user delete --username alice --purge (puis bob), et gardez carol, qui jouera le compte local déjà existant. L'option --purge est nécessaire : sans elle, la commande répond Command error: user still has membership of organizations, car la leçon précédente a placé ces deux comptes dans des équipes de acme. Ils ne possèdent aucun dépôt, la purge ne détruit donc rien d'autre. La suppression de comptes est détaillée dans Assister les utilisateurs en ligne de commande. Enfin, aucun secret ne s'écrit en clair dans les commandes : ils vivent dans le fichier .env et dans des variables du shell.

Comment Forgejo et Keycloak échangent-ils pendant une connexion ?

Section intitulée « Comment Forgejo et Keycloak échangent-ils pendant une connexion ? »

Le navigateur fait l'aller-retour : Forgejo l'envoie vers Keycloak avec une redirect URI, Keycloak l'authentifie et le renvoie vers cette URI avec un code, que Forgejo échange ensuite contre un jeton. Le mot de passe de l'utilisateur n'est saisi que sur Keycloak ; Forgejo ne le voit jamais. Tout se joue sur la redirect URI : l'adresse de retour que Forgejo annonce doit être celle que le client Keycloak autorise.

Le schéma se lit de haut en bas. Les trois premiers échanges sont la redirection vers Keycloak et la saisie du mot de passe chez lui ; la branche du haut est le cas nominal, où l'URI correspond, et celle du bas le cas où elle diffère, que Keycloak coupe avec un HTTP 400. Dans le cas nominal, le jeton porte l'e-mail, le nom et la liste des groupes, dont Forgejo se sert pour lier ou créer le compte puis mettre l'équipe à jour.

Connexion OIDC : le navigateur appelle Forgejo, qui le redirige vers Keycloak avec une redirect URI. Si l'URI est identique à celle du client Keycloak, Keycloak renvoie le navigateur vers le callback de Forgejo avec un code, Forgejo échange ce code et le secret du client contre un jeton portant e-mail, nom et groupes, puis lie ou crée le compte et met l'équipe à jour. Si l'URI diffère, Keycloak répond HTTP 400, Invalid parameter redirect_uri.Keycloak(sso.lab.test)Forgejo(forge.lab.test-)Navigateuralt[redirect_uri identique à celledu client Keycloak][redirect_uri différente]GET/user/oauth2/keycloak307 vers Keycloak, avecredirect_uriformulaire de connexion (identifiantssaisis ici)redirection vers le callback avec un codeGET/user/oauth2/keycloak-/callback?code=…échange du code etdu secret du clientjeton avec e-mail,nom et claim groupscompte lié ou créé,équipe mise à jour,tableau de bordHTTP 400, Invalid parameter redirect_uri
Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

Deux canaux existent donc : celui du navigateur, qui doit résoudre sso.lab.test, et celui de Forgejo vers Keycloak, qui doit le résoudre aussi et faire confiance à son certificat. La section suivante règle les deux avec un seul nom, un seul proxy et une seule autorité locale.

Comment placer Keycloak derrière le même Caddy ?

Section intitulée « Comment placer Keycloak derrière le même Caddy ? »

On ajoute un second nom, sso.lab.test, au Caddyfile existant, et on démarre Keycloak 26.7.0 sur le même réseau Docker. Ainsi le navigateur et Forgejo voient le même émetteur (issuer), https://sso.lab.test/realms/lab, signé par la même autorité que Caddy utilise déjà pour forge.lab.test. Un émetteur qui change selon le point de vue est la première cause d'échec OIDC.

Ajoutez ce bloc à la fin du Caddyfile de /opt/forgejo-lab, sous celui de forge.lab.test. Il redirige le nouveau nom vers le conteneur Keycloak.

sso.lab.test {
tls internal
reverse_proxy keycloak:8080
}

Créez ensuite /opt/forgejo-lab/keycloak.yaml. Ce fichier Compose de surcharge démarre Keycloak, donne à Caddy l'alias réseau sso.lab.test (pour que Forgejo résolve le nom), monte la racine de l'autorité de Caddy dans Forgejo et pose les réglages OIDC sous forme de variables, avec leurs valeurs par défaut. La variable SSL_CERT_FILE indique à Forgejo quelles autorités croire.

services:
keycloak:
image: quay.io/keycloak/keycloak:26.7.0@sha256:0f198be292568439d700cdbfb893e69a6009bb43a94a06a945b1d3d506c76b13
container_name: forgejo-keycloak
restart: always
command: start-dev
environment:
KC_HTTP_ENABLED: "true"
KC_HOSTNAME: https://sso.lab.test
KC_PROXY_HEADERS: xforwarded
KC_BOOTSTRAP_ADMIN_USERNAME: admin
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KC_ADMIN_PASSWORD}
networks:
- forgejo
proxy:
networks:
forgejo:
ipv4_address: 172.30.0.10
aliases:
- sso.lab.test
server:
volumes:
- ./caddy-root.crt:/etc/ssl/lab-root.crt:ro
environment:
SSL_CERT_FILE: /etc/ssl/lab-root.crt
FORGEJO__oauth2_client__ENABLE_AUTO_REGISTRATION: ${OA_AUTO:-false}
FORGEJO__oauth2_client__ACCOUNT_LINKING: ${OA_LINK:-login}
FORGEJO__oauth2_client__USERNAME: ${OA_USER:-nickname}
FORGEJO__security__GLOBAL_TWO_FACTOR_REQUIREMENT: ${TWOFA:-none}

La commande start-dev démarre Keycloak avec sa base H2 intégrée : elle convient à un lab jetable et jamais à la production, que la leçon Mettre Keycloak en production détaille. Les réglages KC_HOSTNAME et KC_PROXY_HEADERS font annoncer à Keycloak l'adresse publique en HTTPS malgré le HTTP interne.

Il reste à copier la racine de l'autorité de Caddy, à résoudre le nom et à redémarrer la pile. L'attente de Keycloak tient dans une boucle qui interroge son document de découverte.

Fenêtre de terminal
cd /opt/forgejo-lab
sudo docker cp forgejo-proxy:/data/caddy/pki/authorities/local/root.crt caddy-root.crt
sudo chmod 644 caddy-root.crt
grep -q sso.lab.test /etc/hosts || echo "127.0.0.1 sso.lab.test" | sudo tee -a /etc/hosts >/dev/null
echo "KC_ADMIN_PASSWORD=$(openssl rand -hex 12)" | sudo tee -a .env >/dev/null
sudo sed -i 's#^COMPOSE_FILE=.*#&:keycloak.yaml#' .env
sudo docker compose up -d --force-recreate
CA=/opt/forgejo-lab/caddy-root.crt
for i in $(seq 1 90); do c=$(curl -s --cacert $CA -o /dev/null -w '%{http_code}' https://sso.lab.test/realms/master/.well-known/openid-configuration || true); [ "$c" = 200 ] && break; sleep 3; done; echo "code=$c"
curl -s --cacert $CA https://sso.lab.test/realms/master/.well-known/openid-configuration | python3 -c 'import sys,json;print("issuer:",json.load(sys.stdin)["issuer"])'

La sortie attendue est code=200 puis issuer: https://sso.lab.test/realms/master. Le piège est le droit de lecture : sans chmod 644, le fichier copié par docker cp reste en droits 600, propriété de root, donc illisible pour Forgejo et pour curl. La boucle d'attente affiche alors code=000, et un curl lancé sans -s se termine en erreur 77, error setting certificate file. Autre piège : l'administrateur de Keycloak est admin, son mot de passe est KC_ADMIN_PASSWORD dans le .env.

Un client confidentiel, en flux standard seul, dont la redirect URI est exactement https://forge.lab.test/user/oauth2/keycloak/callback, et qui ajoute la liste des groupes au jeton. Créez-le dans un realm lab avec la méthode de la leçon Sécuriser une application avec Keycloak ; le tableau donne les valeurs qui comptent pour Forgejo. Un claim est une information portée par le jeton (l'e-mail, le nom, les groupes) ; un mapper est la règle Keycloak qui ajoute un claim au jeton.

ÉlémentValeurPourquoi
Realmlabjamais master, réservé à l'administration de Keycloak
Client IDforgejorepris par --key dans la commande Forgejo
Typeconfidentiel (publicClient à false)Forgejo est un serveur : il garde un secret
Fluxstandard seul, accès direct par mot de passe désactivéle flux Authorization Code suffit
Redirect URIhttps://forge.lab.test/user/oauth2/keycloak/callbackle dernier segment, keycloak, est le nom de la source Forgejo
Mapper de groupesoidc-group-membership-mapper, claim groups, chemin complet désactivéForgejo lit les noms de groupes, sans / devant
Groupe et utilisateursgroupe devops ; alice dedans, carol dehorsde quoi tester le mappage

Le point qui piège le plus : le nom de la source que vous donnerez à Forgejo fait partie de l'URL de retour. Une source nommée keycloak écoute sur /user/oauth2/keycloak/callback ; nommez-la autrement et la redirect URI du client ne correspond plus. Une fois le client créé, relevez son secret dans l'onglet des identifiants et rangez-le dans le .env, sans l'afficher.

Fenêtre de terminal
read -rs -p "Secret du client : " S; echo
echo "OIDC_CLIENT_SECRET=$S" | sudo tee -a /opt/forgejo-lab/.env >/dev/null; unset S
sudo chmod 600 /opt/forgejo-lab/.env

L'option -s de read masque la saisie. Les utilisateurs de Keycloak doivent avoir une adresse e-mail et, idéalement, un e-mail vérifié : Forgejo s'en sert pour le compte.

Parce que Keycloak n'envoie le code d'autorisation qu'aux adresses que le client déclare : une URI exacte limite ce code à un seul chemin, alors qu'un joker * l'enverrait n'importe où sur le site. Le contrôle se fait sans Forgejo, en appelant directement le point d'entrée d'autorisation de Keycloak avec deux adresses de retour.

Fenêtre de terminal
for p in user/oauth2/keycloak/callback autre/chemin; do
echo -n "/$p -> "
curl -s --cacert $CA -o /dev/null -w '%{http_code}\n' "https://sso.lab.test/realms/lab/protocol/openid-connect/auth?client_id=forgejo&response_type=code&scope=openid&redirect_uri=https://forge.lab.test/$p"
done

La première ligne affiche 200 (la page de connexion), la seconde 400. Dans un navigateur, ce 400 est une page Keycloak qui dit Invalid parameter: redirect_uri. Le danger se mesure en remplaçant l'URI du client par https://forge.lab.test/* : le même appel pour /autre/chemin/quelconque répond alors 200. Quiconque contrôle une page de ce site, un dépôt public mal protégé par exemple, pourrait y recevoir le code. Rétablissez l'URI exacte : le chemin quelconque redonne 400.

Comment déclarer Keycloak comme source d'authentification ?

Section intitulée « Comment déclarer Keycloak comme source d'authentification ? »

La commande forgejo admin auth add-oauth enregistre la source ; avec --auto-discover-url, Forgejo lit lui-même les adresses du fournisseur dans son document de découverte. Elle ajoute aussi le client, son secret et le mappage des groupes. Commencez par préparer le shell et l'équipe cible dans acme.

Fenêtre de terminal
D=forge.lab.test
attendre() { for i in $(seq 1 60); do c=$(curl -sk -o /dev/null -w '%{http_code}' https://$D/user/login); [ "$c" = 200 ] && { echo "prêt"; return; }; sleep 2; done; echo "pas prêt (code $c)"; }
ATK=$(sudo docker exec -u git forgejo forgejo admin user generate-access-token --username fjadmin --token-name "auth-$$" --scopes all --raw)
api() { curl -sk -H "Authorization: token $ATK" -H 'Content-Type: application/json' "$@"; }
api -X POST https://$D/api/v1/orgs/acme/teams -d '{"name":"devops","permission":"write","includes_all_repositories":true,"units":["repo.code","repo.issues","repo.pulls"]}' | python3 -c 'import sys,json;d=json.load(sys.stdin);print("team",d["name"],d["id"])'

La sortie est team devops 5 après la leçon précédente ; le numéro dépend des équipes déjà créées. L'option includes_all_repositories à true sert la seule démonstration du mappage : pour une vraie équipe, rattachez les dépôts un par un, comme dans la leçon sur les organisations. Déclarez maintenant la source. Le secret est lu dans le .env ; le mappage {"devops":{"acme":["devops"]}} se lit « le groupe devops du fournisseur donne l'équipe devops de l'organisation acme ».

Fenêtre de terminal
SECRET=$(sudo grep '^OIDC_CLIENT_SECRET=' /opt/forgejo-lab/.env | cut -d= -f2-)
sudo docker exec -u git forgejo forgejo admin auth add-oauth --name keycloak --provider openidConnect \
--key forgejo --secret "$SECRET" \
--auto-discover-url https://sso.lab.test/realms/lab/.well-known/openid-configuration \
--scopes openid --scopes email --scopes profile \
--group-claim-name groups --group-team-map '{"devops":{"acme":["devops"]}}' --group-team-map-removal
sudo docker exec -u git forgejo forgejo admin auth list

La liste affiche 1 keycloak OAuth2 true, sous les colonnes ID, Name, Type et Enabled. Le secret passe en argument de la commande : pendant son exécution, tout utilisateur de la machine le voit avec ps. Sur un serveur partagé, c'est une fuite ; limitez l'accès à la machine et renouvelez le secret après un incident. Autre piège : ne lancez jamais un script qui contient cette commande avec bash -x, qui affiche les secrets. Seule la ligne de commande est détaillée ici.

Que se passe-t-il à la première connexion d'un compte ?

Section intitulée « Que se passe-t-il à la première connexion d'un compte ? »

Par défaut, Forgejo ne crée rien : il propose de lier l'identité à un compte existant. Pour créer le compte automatiquement, il faut activer ENABLE_AUTO_REGISTRATION. C'est la section [oauth2_client] de la configuration qui décide, et elle se règle comme à la leçon de configuration, par une variable FORGEJO__oauth2_client__…. Le fichier de surcharge porte déjà ces variables ; il suffit de changer leur valeur dans le .env et de recréer le conteneur.

Définissez une petite fonction qui fait les trois gestes, ainsi que celle qui affiche les comptes avec leur origine.

Fenêtre de terminal
reglage() { cd /opt/forgejo-lab && sudo sed -i "/^$1=/d" .env && echo "$1=$2" | sudo tee -a .env >/dev/null && sudo docker compose up -d server >/dev/null 2>&1 && attendre; }
users() { api "https://$D/api/v1/admin/users?limit=50" | python3 -c 'import sys,json
for u in json.load(sys.stdin): print(" ",u["login"],"| login_name=",u.get("login_name"),"| source_id=",u.get("source_id"))'; }

Un compte créé par OIDC a un source_id égal à celui de la source (ici

  1. et un login_name égal à l'identifiant de l'utilisateur chez Keycloak ; un compte local a source_id à 0. C'est la façon de distinguer les deux dans l'API.

Avec ENABLE_AUTO_REGISTRATION=false et ACCOUNT_LINKING=login, un premier visiteur arrive sur une page « Link account » et aucun compte n'est créé. Ouvrez https://forge.lab.test/user/oauth2/keycloak dans un navigateur qui résout les deux noms de domaine et connaît l'autorité de Caddy, puis identifiez-vous sur Keycloak comme alice.

L'onglet affiche Link account : Forgejo demande d'associer l'identité à un compte existant ou d'en créer un. Vérifiez qu'aucun compte alice n'est apparu.

Fenêtre de terminal
users

La liste ne contient pas alice. Le piège : on croit parfois que DISABLE_REGISTRATION règle aussi cette création. Ce n'est pas le cas, comme la section suivante le montre.

Avec ENABLE_AUTO_REGISTRATION=true, le compte est créé à la première connexion, même si l'inscription ouverte est désactivée. Les deux réglages sont indépendants : DISABLE_REGISTRATION=true, conservé pendant ce lab, ferme le formulaire d'inscription, pas l'entrée par le fournisseur d'identité.

Fenêtre de terminal
reglage OA_AUTO true
users

Reconnectez-vous comme alice sur https://forge.lab.test/user/oauth2/keycloak. Le navigateur arrive sur le tableau de bord et users affiche alice | login_name= <identifiant Keycloak> | source_id= 1. Le nom d'utilisateur vient de preferred_username, car USERNAME vaut nickname par défaut. Le piège : tout compte du realm qui franchit l'authentification obtient un compte Forgejo. Réservez le client à un realm dont vous maîtrisez les inscriptions, ou restreignez les groupes admis (voir plus bas).

Comment faire entrer l'utilisateur dans la bonne équipe ?

Section intitulée « Comment faire entrer l'utilisateur dans la bonne équipe ? »

Le mappage se fait à la connexion : Forgejo lit le claim groups du jeton et ajoute l'utilisateur aux équipes que --group-team-map associe à ses groupes. alice appartient au groupe devops de Keycloak ; sa connexion de la section précédente a donc dû la placer dans acme/devops. Relevez les membres de l'équipe par l'API.

Fenêtre de terminal
TID=$(api https://$D/api/v1/orgs/acme/teams | python3 -c 'import sys,json;print([t["id"] for t in json.load(sys.stdin) if t["name"]=="devops"][0])')
api https://$D/api/v1/teams/$TID/members | python3 -c 'import sys,json;print([u["login"] for u in json.load(sys.stdin)])'

La sortie est ['alice']. L'option --group-team-map-removal demande à Forgejo de retirer l'utilisateur de l'équipe quand il quitte le groupe ; nous ne l'avons pas rejouée en retirant alice de devops, vérifiez-la dans votre lab avant de compter dessus pour un départ.

La documentation de la commande dans la référence de la ligne de commande Forgejo 15 liste d'autres options que ce lab n'a pas jouées : --admin-group et --restricted-group (un groupe donne le rôle d'administrateur ou le compte restreint), --required-claim-name et --required-claim-value (refuser tout utilisateur dont le jeton n'a pas ce claim avec cette valeur). Une option qui accorde le rôle administrateur à partir d'un groupe déplace la confiance : quiconque peut modifier ce groupe chez le fournisseur devient administrateur de la forge. Testez chacune sur une instance jetable avant de l'activer.

Que faire quand un compte local porte déjà la même adresse e-mail ?

Section intitulée « Que faire quand un compte local porte déjà la même adresse e-mail ? »

Le réglage ACCOUNT_LINKING tranche : login demande le mot de passe du compte local, disabled refuse avec une erreur 500, auto relie sans rien demander. Le cas se présente quand une personne avait un compte local avant l'arrivée du SSO : carol, de la leçon précédente, a la même adresse e-mail que la carol de Keycloak.

Commencez par disabled, qui interdit toute liaison, avec la création automatique encore active.

Fenêtre de terminal
reglage OA_LINK disabled

Connectez-vous comme carol via Keycloak : le navigateur affiche 500 Internal server error, un message qui n'aide pas l'utilisateur. La cause est dans le journal de Forgejo.

Fenêtre de terminal
sudo docker logs --since 5m forgejo 2>&1 | grep 'user already exists'

La ligne se termine par CreateUser: user already exists [name: carol] : Forgejo a voulu créer un compte et le nom était pris. Ici, le nom et l'adresse e-mail de carol coïncident avec ceux du compte local, et disabled refuse la liaison. Passez à auto.

Fenêtre de terminal
reglage OA_LINK auto
sudo docker exec forgejo-db psql -U forgejo -d forgejo -c "select u.name, e.login_source_id, left(e.external_id,8) as ext, e.email from external_login_user e join \"user\" u on u.id=e.user_id order by 1"

Après une nouvelle connexion de carol, le navigateur arrive directement sur son tableau de bord, et la table external_login_user contient une ligne carol | 1 | … | carol@example.test. Le compte reste local (source_id à 0) : la liaison n'ajoute qu'une porte d'entrée. Le piège est la confiance dans l'adresse e-mail : auto rattache l'identité à un compte local sur une simple coïncidence, ici le même nom et la même adresse e-mail (nous n'avons pas isolé lequel des deux suffit), ce qui n'est sûr que si le fournisseur n'accepte que des adresses vérifiées. Le risque de prise de compte est détaillé dans Fédération entrante. Pour la production, revenez à la valeur prudente.

Fenêtre de terminal
reglage OA_LINK login

Le réglage GLOBAL_TWO_FACTOR_REQUIREMENT de la section [security] prend trois valeurs : none (défaut), all (tous les comptes) et admin (les administrateurs). Il impose l'enrôlement d'un second facteur (un code à usage unique de type TOTP, ou une clé de sécurité WebAuthn) avant tout usage de la forge. Il s'applique au redémarrage, parce qu'il vient de la variable d'environnement posée dans le fichier de surcharge.

Créez un compte local sans second facteur, puis relevez le comportement actuel de l'API en authentification Basic (identifiant et mot de passe).

Fenêtre de terminal
P=$(openssl rand -hex 10)
api -X POST https://$D/api/v1/admin/users -d "{\"username\":\"dave\",\"email\":\"dave@example.test\",\"password\":\"$P\",\"must_change_password\":false}" | python3 -c 'import sys,json;print("local",json.load(sys.stdin)["login"])'
curl -sk -o /dev/null -w 'API Basic dave: %{http_code}\n' -u "dave:$P" https://$D/api/v1/user
reglage TWOFA all
curl -sk -w '\nAPI Basic dave: %{http_code}\n' -u "dave:$P" https://$D/api/v1/user

La première requête répond 200, la seconde 403 avec le message This Forgejo instance requires users to enable two-factor authentication before they can access their accounts. Enable it at: https://forge.lab.test/user/settings/security, dans un corps JSON {"message": …}. Dans un navigateur, la connexion de dave aboutit sur /user/settings/security, et toute autre page (/, /explore/repos) redirige vers elle tant que le second facteur n'est pas enrôlé. L'enrôlement se fait depuis cette page, qui mène à /user/settings/security/two_factor/enroll.

Avec la valeur admin, la contrainte ne vise que les administrateurs.

Fenêtre de terminal
reglage TWOFA admin

fjadmin, administrateur sans second facteur, est alors redirigé vers la page de sécurité, alors que dave, non administrateur, accède au tableau de bord. Remettez ensuite none avec reglage TWOFA none.

Deux observations comptent pour un compte venu du SSO. Avec all, alice, compte OIDC, est elle aussi redirigée vers sa page de sécurité : Forgejo exige son propre second facteur, même quand Keycloak a déjà authentifié l'utilisateur. L'option --skip-local-2fa de update-oauth est décrite par la documentation comme « skip local 2fa for users authenticated by this source ». Nos essais l'ont acceptée (code retour 0) sans qu'alice cesse d'être redirigée, et rien n'apparaît dans la configuration de la source : son effet n'est pas démontré, ne comptez pas dessus. Pour imposer un second facteur au niveau du fournisseur d'identité, voir MFA, passkeys et flows dans Keycloak. Deuxième précaution : le 403 ne vise pas que l'authentification Basic. Un jeton d'accès créé pour dave avant le passage à all répond lui aussi 403, avec le même message, sur GET /api/v1/user comme sur POST /api/v1/user/repos, et le jeton de fjadmin, administrateur sans second facteur, subit le même sort. Tout script d'un compte sans second facteur casse, mot de passe ou jeton. Nous n'avons pas rejoué l'appel d'un jeton après l'enrôlement d'un second facteur : vérifiez-le avant de passer à all sur une vraie forge.

Forgejo sait interroger un annuaire LDAP directement, mais cette leçon ne l'a pas rejoué. La référence de la ligne de commande liste les sous-commandes forgejo admin auth add-ldap et add-ldap-simple. Si votre annuaire est déjà fédéré dans Keycloak, le plus simple est de ne déclarer qu'une seule source côté Forgejo, OIDC, et de laisser Keycloak parler à l'annuaire : la leçon Fédérer un annuaire LDAP ou AD avec Keycloak détaille ce montage, et LDAP et annuaires rappelle le modèle. Une source de moins à gouverner, c'est un seul endroit où retirer un départ.

Trois symptômes couvrent l'essentiel des échecs : une page Keycloak en 400, une erreur 500 sur le callback de Forgejo, et un refus de add-oauth à la déclaration. Le tableau relie chacun à sa cause et à sa correction, et ajoute quatre pannes voisines.

SymptômeCauseCorrection
Page Keycloak HTTP 400, Invalid parameter: redirect_uril'URI du client diffère de l'adresse de retour de Forgejo (ici une URI en callback-faux)corriger l'URI du client en https://forge.lab.test/user/oauth2/<nom-de-la-source>/callback, sans joker
500 Internal server error sur /user/oauth2/keycloak/callbackACCOUNT_LINKING=disabled et compte local de même nom ; journal : user already existspasser à login (mot de passe du compte local) ou, à vos risques, à auto
add-oauth répond Command error: Failed to initialize OpenID Connect Provider … Non-success code for Discovery URL: 404 (code retour 1)l'adresse de découverte est fausse, ici un realm nope inexistantcorriger l'URL …/realms/<realm>/.well-known/openid-configuration
error setting certificate file, ou Forgejo qui ne joint pas Keycloakracine de l'autorité de Caddy illisible ou non montée dans Forgejochmod 644 caddy-root.crt, vérifier SSL_CERT_FILE, recréer le conteneur
La page « Link account » apparaît au lieu d'un tableau de bordENABLE_AUTO_REGISTRATION vaut false (défaut)régler OA_AUTO à true, ou lier le compte à la main
Tout le monde est renvoyé vers /user/settings/securityGLOBAL_TWO_FACTOR_REQUIREMENT vaut allenrôler le second facteur, ou revenir à none ou admin
Un script répond 403 sur l'API, en Basic comme avec un jetonle compte du script n'a pas de second facteur alors que GLOBAL_TWO_FACTOR_REQUIREMENT vaut allenrôler un second facteur pour ce compte, ou revenir à admin si seuls les administrateurs doivent l'avoir

L'échec de découverte garde une particularité : la tentative consomme tout de même un identifiant de source (le suivant porte le numéro 3 au lieu de 2). Autre cas, une source déclarée avec une adresse interne en HTTP, http://keycloak:8080/…, est acceptée sans erreur (code retour 0) ; la connexion complète n'a pas été jouée. Fiez-vous à l'émetteur public en HTTPS, le seul vérifié.

On supprime d'abord les comptes qui dépendent de la source, puis la source, puis on remet les variables à leurs valeurs par défaut. Une source encore utilisée ne se supprime pas : la commande répond Command error: login source is still used by some users [id: 1]. Deux sortes de comptes la retiennent, les comptes créés par OIDC comme alice, et les comptes locaux liés comme carol.

Fenêtre de terminal
sudo docker exec -u git forgejo forgejo admin user delete --username alice --purge

Pour carol, qui doit rester, détachez la liaison dans le navigateur : connectez-vous avec ce compte, ouvrez /user/settings/security et cliquez sur le bouton Remove de la ligne keycloak, dans la liste des comptes liés. Si vous ne connaissez plus son mot de passe, posez-en un avec change-password --must-change-password=false, comme à la leçon d'assistance. La suppression de la source se fait ensuite par identifiant, relevé avec admin auth list.

Fenêtre de terminal
sudo docker exec -u git forgejo forgejo admin auth delete --id 1
reglage OA_AUTO false; reglage OA_LINK login; reglage TWOFA none

La commande auth delete rend la main sans sortie ; admin auth list n'affiche plus que l'en-tête. La suppression de comptes est le sujet de la leçon Assister les utilisateurs en ligne de commande. Le compte local dave, créé pour la double authentification, reste en place : la leçon d'assistance le réutilise puis le supprime. Pour supprimer toute la pile, y compris Keycloak, suivez le nettoyage de la leçon d'installation et retirez la ligne sso.lab.test de /etc/hosts.

  • Une source OIDC se déclare par forgejo admin auth add-oauth --provider openidConnect --auto-discover-url …/.well-known/openid-configuration ; admin auth list la liste.
  • La redirect URI du client Keycloak doit être exactement https://forge.lab.test/user/oauth2/<nom-de-la-source>/callback ; un joker * laisse recevoir le code sur n'importe quel chemin du site.
  • Forgejo doit faire confiance à l'autorité de certification du proxy (SSL_CERT_FILE, racine lisible en 644) et voir le même émetteur que le navigateur.
  • ENABLE_AUTO_REGISTRATION décide si le premier visiteur obtient un compte ; DISABLE_REGISTRATION ne l'en empêche pas.
  • ACCOUNT_LINKING vaut login (mot de passe local demandé), disabled (erreur 500, cause dans le journal) ou auto (liaison automatique sur la coïncidence du compte).
  • --group-claim-name et --group-team-map rangent un utilisateur dans une équipe à la connexion ; --group-team-map-removal doit être éprouvé avant de servir pour un départ.
  • GLOBAL_TWO_FACTOR_REQUIREMENT (none, all, admin) redirige les comptes sans second facteur vers /user/settings/security et répond 403 à l'API, en Basic comme avec un jeton ; il touche aussi les comptes OIDC.
  • L'effet de --skip-local-2fa n'est pas démontré, et le secret du client passé en argument est visible avec ps pendant la commande.

Six questions tirées sur huit : la redirect URI exacte, le premier passage d'un compte OIDC, la liaison avec un compte local, l'erreur de découverte et le second facteur imposé à tous.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn