HowTo: SSO Forgejo with keycloak

Keycloak OpenID connect authentication allows users to log in to Forgejo using their Keycloak credentials. This article explains how to set up Keycloak as an authentication provider in Forgejo.

Authentication

First use case to integrate is authentication. Authentication tells the integrated Forgejo who the user is. Under the hood this will login existing users and in addition register unknown ones.

Keycloak: Setup Client

We will setup the keycloak client Forgejo will connect to.

  1. login as realm admin (for keycloak newbies https://[your.keycloak.server]/admin/[your-realm]/console is a good guess)
  2. create forgejo-client
    1. Client ID: repo
    2. Client authentication: on
    3. Root URL: [https://your.forgejo.server]
    4. Home URL: [https://your.forgejo.server]
    5. Valid Redirect URLs: [https://your.forgejo.server]*

Forgejo: Setup Authentication Source

In Forgejo we now can setup an authentication source and connect to the keycloak client.

  1. login as Forgejo admin
  2. navigate to Site administration -> Identity & access -> Authentication sources
  3. Add authentication source
  4. for Authentication type choose OAuth2
  5. for OAuth2 provider choose OpenID connect
  6. Client ID: repo
  7. copy Client secret from keycloak to Forgejo
  8. enter the OpenID Connect Auto Discovery URL: https://[your.keycloak.server]/realms/[your-realm]/.well-known/openid-configuration
  9. Skip local 2FA: on

Authorization by Role

You can define a role to decide whether users are denied / allowed to access Forgejo.

Keycloak: Configure Client Role

For authorization we will now setup a client role in keycloak.

  1. navigate to your forgejo-client -> Roles
  2. Create role lets call it repo
  3. navigate Client Scopes -> repo-dedicated
  4. Add mapper -> Add predefined mapper -> choose client roles to add.
  5. enter
    1. Name: on your choice
    2. Token Claim Name: roles
    3. Add this informations to tokens: (see image)

Forgejo: Authorize Access by Role

On Forgejo side we allow access only if the user authenticated has the client role assigned.

  1. navigate to Authentication source created above.
    1. set Required claim name: roles
    2. set Required claim value: repo

Sync org & team

You can also sync organization and team memberships. In our example this is based on group membership in keycloak.

Keycloak: Setup Group Mapping

  1. navigate to Client scopes

  2. create a new client scope

    1. set Name to e.g. groups
    2. leave Type at None
    3. Save
  3. click Mappers

    1. click Configure a new mapper
    2. click Group Membership
    3. set Name to e.g. groups
    4. set Token Claim Name to e.g. groups. This is a value, that needs to be set in Forgejo.
    5. unset Full group path. For our example we use the plain group names.
    6. make sure Add to ID token, Add to access token, Add to userinfo are set.
    7. Save
  4. go to Groups

    1. sreate groups and respective sub-groups. The group names need to be set in Forgejo
    2. add users to their respective group/sub-groups. The users will be added to teams of the same name in existing organizations in Forgejo.
  5. go to Clients

    1. select the client created above.
    2. select Client scopes
      1. click Add client scope
      2. select the client scope you created e.g. groups
      3. click Add & select Default. Default will add the mapped information in the default token.

Forgejo: Configure Group to Organization Mapping

In Forgejo we now will define a mapping from keycloak group to Forgejo organization.

  1. navigate to Authentication source created above.
    1. set Claim name providing group names for this source. (Optional). Must be the same as Token Claim Name
    2. set Group claim value for administrator users. if desired. Must be the name of the keycloak group you defined to be administrator group.
    3. set Group claim value for restricted users if desired. Must be the name you chose for the restricted access in keycloak.
    4. add the mapping in Map claimed groups to organization teams.. The mapping might look like
      {"staff": {"internal-org": ["Staff"],
                 "public-org": ["Staff"]},
       "external": {"internal-org": ["Contributor"],
                    "public-org": ["Contributor"]},
       "your-customer1": {"customer-org": ["Staff"]}}
      
    5. optional: Check the Remove users from synchronized teams if user does not belong to corresponding group. box for synchronized teams. This will remove users from a role / team if they are removed on keycloak side. Be careful! If you screw up your mapping, the role- and team-membership will also be removed.

The sync is done on next user login or session renew.

Logout Integration

At the moment there is no Single Logout implemented. That means

  • if a logged in user presses logout in Forgejo, Forgejo will not inform keycloak about the logout.
  • if user logs out in an other application keycloak can not signal Forgejo user has logged out. To reduce the impact you may configure a short session timeout:
    [session]
    SESSION_LIFE_TIME = 3600