Based on some tests (no production usage), this how-to describes how to connect BigBlueButton (BBB) with its official frontend Greenlight v3 to Univention Nubus. Once it is set up:
- Single Sign-On: users sign in to BigBlueButton with their Nubus account, through OpenID Connect and the Keycloak included in Nubus.
- Single Logout: signing out of BigBlueButton also ends the Nubus session.
- User lifecycle: BigBlueButton accounts follow the Nubus user objects. Accounts are created at first login, keep a stable identifier (
univentionObjectIdentifier) and are updated from Nubus. Users who are disabled or deleted in Nubus can no longer sign in.
The how-to focuses on the configuration. For installing BigBlueButton, Greenlight and Nubus, follow the upstream documentation linked in Deployment.
Background: authentication in BigBlueButton
A BigBlueButton server (media server, HTML5 client, recordings) has no user management of its own. Users, rooms and recordings are managed by the frontend, which by default is “Greenlight”, which talks to the BBB server API. So identity integration happens in the frontend:
OIDC (SSO / logout) BBB API (shared secret)
Browser ───────────────────────► Greenlight ─────────────────────────► BigBlueButton server(s)
│ (or Scalelite load balancer)
▼
Nubus Keycloak ◄──── LDAP federation ──── Nubus directory (OpenLDAP)
Greenlight v3 has no LDAP support (it was removed in v3). The connection to Nubus runs only by Single Sign-On with Keycloak. All user data Greenlight gets from Nubus arrives as OIDC claims.
Following this Howto the result is:
| Greenlight v3 + Nubus | |
|---|---|
| Single Sign-On via OIDC | |
| Logout in Greenlight also signs out of Nubus (RP-initiated logout) | |
| Logout in Nubus or another application also signs out of Greenlight (back-channel logout) | |
| Accounts created at first login (just-in-time) | |
Stable account identifier across renames (univentionObjectIdentifier) |
|
| Name and email updated at each login | |
| Disabled or deleted Nubus users can no longer sign in | |
| Roles from Nubus groups | |
| Automatic removal of Greenlight accounts deleted in Nubus |
Deployment
Use the upstream documentation for installing the components:
- Nubus for Kubernetes: Operation Manual – Deployment. For a quick test environment see Install Nubus for Kubernetes on your notebook in 20 minutes.
- BigBlueButton server: BBB installation, with
bbb-install.shon a dedicated Ubuntu server.- BBB needs a large range of UDP ports for WebRTC and is usually not run inside Kubernetes.
- A community Docker setup exists at bigbluebutton/docker.
- Note the API URL and secret:
bbb-conf --secret.
- Greenlight v3: Greenlight installation.
- Container image
bigbluebutton/greenlight:v3, needs PostgreSQL and Redis. bbb-install.sh -gcan install Greenlight on the BBB server. The container also runs fine next to Nubus in Kubernetes; there is no official Helm chart.
- Container image
The Howto has been tested with Nubus on Kubernetes, but should also work with Nubus on UCS.
Placeholders used in this how-to
| Placeholder | Meaning |
|---|---|
id.example.org |
Hostname of the Nubus Keycloak (global.subDomains.keycloak.global.domain, default id.<domain>) |
nubus |
Keycloak realm of Nubus (default) |
bbb.example.org |
Hostname of Greenlight |
<release>, <nubus-namespace> |
Helm release name and namespace of Nubus for Kubernetes |
The OIDC issuer of Nubus is https://id.example.org/realms/nubus. You can check it at https://id.example.org/realms/nubus/.well-known/openid-configuration.
Prerequisite: users need an email address
Greenlight requires the claims name and email. The Nubus Keycloak takes email from the Nubus user property Primary e-mail address (mailPrimaryAddress). Users without it wil run into an error message during login: Greenlight shows You can’t be authenticated, and its log shows Error during authentication: undefined method 'downcase' for nil.
Step 1: Provide univentionObjectIdentifier in Keycloak
Greenlight identifies an account by a single claim (OPENID_CONNECT_UID_FIELD). Choose a claim that never changes for the lifetime of the Nubus user:
univentionObjectIdentifieris the permanent identifier Nubus assigns to every directory object. It survives renames, moves between containers, and re-imports into Keycloak.sub, the default, is the ID of Keycloak’s cached copy of the LDAP user, not an identifier from Nubus. If Keycloak ever re-imports the user,subchanges and Greenlight creates a second account.preferred_usernamechanges when the user is renamed.
Out of the box, the Nubus Keycloak doesn’t map univentionObjectIdentifier from LDAP (this will be provided in future Nubus versions). Add an attribute mapper to the LDAP user federation. Either option below works.
Option A: Helm value of Nubus for Kubernetes
Add the mapper to your custom_values.yaml and apply the configuration. The keycloak-bootstrap job then creates it; see Configure additional LDAP mappers in the Operation Manual.
nubusKeycloakBootstrap:
bootstrap:
ldapMappers:
univentionObjectIdentifier:
alwaysReadFromLdap: true
This keeps the mapper in your deployment configuration together with the rest of Nubus.
Option B: Keycloak Admin Console
- Sign in to the Keycloak Admin Console at
https://id.example.org/admin/. The Operation Manual section Keycloak Admin Console describes the admin user and its password. - In the realm selector at the top left, switch to the realm nubus.
- Open User federation → ldap-provider → tab Mappers → Add mapper.
- Fill in the mapper:
- Name:
univentionObjectIdentifier - Mapper type:
user-attribute-ldap-mapper - User Model Attribute:
univentionObjectIdentifier - LDAP Attribute:
univentionObjectIdentifier - Read Only: On
- Always Read Value From LDAP: On. With Off, users already imported into Keycloak wouldn’t get the attribute until they are re-imported.
- Is Mandatory In LDAP: Off
- Force a Default Value: Off
- Is Binary Attribute: Off
- Name:
- Click Save.
You check the result at the end of step 2, with the generated ID token.
Step 2: Create the OIDC client for Greenlight
In the Keycloak Admin Console, realm nubus, go to Clients → Create client. The wizard has three pages:
- General settings
- Client type:
OpenID Connect - Client ID:
bbb-greenlight - Name (optional):
BigBlueButton
- Client type:
- Capability config
- Client authentication: On (confidential client)
- Authorization: Off
- Authentication flow: only Standard flow checked. Uncheck Direct access grants.
- PKCE Method: leave empty. Greenlight doesn’t use PKCE.
- Login settings
- Root URL and Home URL:
https://bbb.example.org - Valid redirect URIs:
https://bbb.example.org/auth/openid_connect/callback - Valid post logout redirect URIs:
https://bbb.example.org/* - Web origins:
https://bbb.example.org
- Root URL and Home URL:
Click Save. Then complete the client:
-
Logout settings. On the Settings tab, scroll down to Logout settings, set Front channel logout to Off, and click Save. Leave Backchannel logout URL empty, because Greenlight has no endpoint for it.
-
Client secret. On the Credentials tab, copy the Client Secret. You need it in step 3.
-
Identifier claim. Open the tab Client scopes →
bbb-greenlight-dedicated, then Configure a new mapper (or Add mapper → By configuration) → User Attribute:- Name:
univentionObjectIdentifier - User Attribute:
univentionObjectIdentifier - Token Claim Name:
univentionObjectIdentifier - Claim JSON Type:
String - Add to ID token: On
- Add to access token: Off
- Add to userinfo: On
- Multivalued: Off
Click Save.
- Name:
The default client scopes profile and email of the Nubus realm provide the remaining claims Greenlight uses: name, email and locale.
Check the result. Open Clients → bbb-greenlight → Client scopes → Evaluate, select a Nubus user, and click Generated ID token. The token must contain univentionObjectIdentifier, name and email:
{
"iss": "https://id.example.org/realms/nubus",
"aud": "bbb-greenlight",
"univentionObjectIdentifier": "c0b35f7f-24c6-4098-988a-33df42ce6d07",
"name": "Jane Doe",
"given_name": "Jane",
"family_name": "Doe",
"preferred_username": "jdoe",
"email": "jane.doe@example.org"
}
Steps 1 (option B) and 2 with kcadm.sh (command line)
In Nubus for Kubernetes, kcadm.sh is available in the Keycloak pod:
kubectl -n <nubus-namespace> exec -it <release>-keycloak-0 -c main -- bash
K=/opt/keycloak/bin/kcadm.sh
$K config credentials --server http://localhost:8080 --realm master --user kcadmin # asks for the password
# Step 1: LDAP federation mapper
LID=$($K get components -r nubus -q name=ldap-provider --fields id --format csv --noquotes)
$K create components -r nubus -f - <<EOF
{
"name": "univentionObjectIdentifier",
"providerId": "user-attribute-ldap-mapper",
"providerType": "org.keycloak.storage.ldap.mappers.LDAPStorageMapper",
"parentId": "$LID",
"config": {
"ldap.attribute": ["univentionObjectIdentifier"],
"user.model.attribute": ["univentionObjectIdentifier"],
"read.only": ["true"],
"always.read.value.from.ldap": ["true"],
"is.mandatory.in.ldap": ["false"]
}
}
EOF
# Step 2: client
$K create clients -r nubus -f - <<'EOF'
{
"clientId": "bbb-greenlight",
"protocol": "openid-connect",
"publicClient": false,
"secret": "<generate-a-long-random-secret>",
"standardFlowEnabled": true,
"directAccessGrantsEnabled": false,
"rootUrl": "https://bbb.example.org",
"redirectUris": ["https://bbb.example.org/auth/openid_connect/callback"],
"webOrigins": ["https://bbb.example.org"],
"frontchannelLogout": false,
"attributes": { "post.logout.redirect.uris": "https://bbb.example.org/*" }
}
EOF
# Step 2: identifier claim
ID=$($K get clients -r nubus -q clientId=bbb-greenlight --fields id --format csv --noquotes)
$K create clients/$ID/protocol-mappers/models -r nubus -f - <<'EOF'
{
"name": "univentionObjectIdentifier",
"protocol": "openid-connect",
"protocolMapper": "oidc-usermodel-attribute-mapper",
"config": {
"user.attribute": "univentionObjectIdentifier",
"claim.name": "univentionObjectIdentifier",
"jsonType.label": "String",
"id.token.claim": "true",
"userinfo.token.claim": "true",
"access.token.claim": "false"
}
}
EOF
Step 3: Configure Greenlight
Add these variables to the Greenlight environment, in addition to the base settings from the Greenlight install guide: SECRET_KEY_BASE, DATABASE_URL, REDIS_URL, URL_HOST, BIGBLUEBUTTON_ENDPOINT and BIGBLUEBUTTON_SECRET.
OPENID_CONNECT_ISSUER=https://id.example.org/realms/nubus
OPENID_CONNECT_CLIENT_ID=bbb-greenlight
OPENID_CONNECT_CLIENT_SECRET=<client secret from Keycloak>
# Base URL of Greenlight; Greenlight appends "/auth/openid_connect/callback"
OPENID_CONNECT_REDIRECT=https://bbb.example.org/
# Stable account identifier (claim from step 2)
OPENID_CONNECT_UID_FIELD=univentionObjectIdentifier
# Enables logout towards Nubus (path relative to the issuer)
OPENID_CONNECT_LOGOUT_PATH=/protocol/openid-connect/logout
Restart Greenlight afterwards.
Notes:
- When
OPENID_CONNECT_ISSUERis set, Greenlight hides its local sign-up and sign-in forms and shows only the Sign in button, which leads to Nubus. - Greenlight must trust the TLS certificate of
id.example.org. With a private CA, add the CA to the container’s trust store, for example by mounting a CA bundle and settingSSL_CERT_FILE. - Greenlight stores the ID token in its session cookie, which makes response headers large. If the reverse proxy in front of Greenlight answers
502upstream sent too big header right after login, increase its buffers:- ingress-nginx: add the annotation
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"; - plain nginx: see greenlight#6065.
- ingress-nginx: add the annotation
BIGBLUEBUTTON_ENDPOINTmust end in/bigbluebutton/api/.
Existing Greenlight accounts
If Greenlight already has accounts, you must migrate them when you switch to OIDC or change OPENID_CONNECT_UID_FIELD. Those accounts don’t have univentionObjectIdentifier as their identifier yet, and a login of such a user fails with /?error=SignupError. The Greenlight log shows Validation failed: Email has already been taken.
For the migration period, set
USE_EMAIL_AS_EXTERNAL_ID_FALLBACK=true
Greenlight then matches the existing account by email address at the next login and stores the new identifier; rooms and recordings are kept. Remove the variable again after all users have signed in once, so that from then on only the permanent identifier is used.
Step 4: First administrator
With SSO enabled, the local administrator sign-in is no longer available, so promote a Nubus user instead. Let the user sign in once, then run:
# Docker Compose
docker exec -it greenlight-v3 bundle exec rake "user:set_admin_role[admin@example.org]"
# Kubernetes
kubectl exec -it deploy/greenlight -- bundle exec rake "user:set_admin_role[admin@example.org]"
Single Logout behaviour
- Sign out in Greenlight → signed out of Nubus.
- Greenlight redirects the browser to the Keycloak
end_session_endpoint, passingid_token_hint,client_idandpost_logout_redirect_uri=https://bbb.example.org/?success=LogoutSuccessful. - Keycloak ends the SSO session. This signs the user out of the Nubus Portal and of all other applications that support back-channel logout.
- Keycloak returns the user to Greenlight.
- Greenlight redirects the browser to the Keycloak
- Sign out in Nubus or another application → Greenlight session stays. Greenlight implements neither OIDC back-channel nor front-channel logout. Its session stays valid until the user signs out in Greenlight or the session expires. Keep the Greenlight session lifetime short: Administrator Panel → Site Settings → Session timeout.
User lifecycle
Greenlight has limited user lifecycle capabilities as described in the following table. There are alternate frontends with other capabilities (for example PILOS seems to support LDAP for user lifecycle).
| Event in Nubus | Effect in Greenlight |
|---|---|
| User created | No effect until the first sign-in. At first sign-in, Greenlight creates the account just-in-time, with a personal room and the Default role (Administrator Panel → Site Settings). |
| User renamed or moved | Same Greenlight account, because univentionObjectIdentifier doesn’t change. |
| Name or email changed | Updated at the next sign-in if Administrator Panel → Registration → Resync on login is enabled. |
| User disabled or deleted | The user can no longer sign in, because Keycloak rejects the login. An already open Greenlight session lasts until it expires. The Greenlight account, its rooms and its recordings stay until an administrator deletes them in Administrator Panel → Manage Users. |
| Group membership changed | No effect. Greenlight can’t map claims or groups to roles. |
Further options in Administrator Panel → Registration:
- Registration method:
- Approve/Decline: new users wait in Pending until an administrator approves them.
- Join by invitation: only Nubus users who received an invitation are admitted.
- Role mapping: assigns roles at account creation by email suffix, for example
Moderator=@staff.example.org. This is the only automatic role assignment in Greenlight v3. Requests for claim-based roles: greenlight#5994, greenlight#6141.
Verification
- Open
https://bbb.example.organd click Sign in. You are redirected to the Nubus login page, and back to Greenlight after login. - Open the Nubus Portal in the same browser. You are signed in without a second password prompt (SSO). The Keycloak Admin Console shows one session under Users → user → Sessions.
- Start a meeting in your Greenlight room. The BigBlueButton HTML5 client opens.
- Sign out in Greenlight. You land on
https://bbb.example.org/?success=LogoutSuccessful. Reload the Nubus Portal: you are signed out there, too, and the Keycloak session is gone. - Disable the user in Nubus and try to sign in again. Keycloak rejects the login.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
Greenlight shows You can’t be authenticated; the log shows Error during authentication: undefined method 'downcase' for nil |
The ID token has no email, because the Nubus user has no Primary e-mail address. Set it. If the user has signed in to Keycloak before, also run Sync changed users; see Prerequisite: users need an email address. |
Greenlight redirects to /?error=SignupError; the log shows Validation failed: Email has already been taken |
An existing Greenlight account was created with another identifier. See Existing Greenlight accounts. |
The ID token has no univentionObjectIdentifier |
Step 1 is missing, or Always Read Value From LDAP is off and the user was imported into Keycloak before the mapper existed. |
Greenlight: 502 upstream sent too big header |
Increase the proxy buffer size, see step 3. |
Greenlight log: SSL_connect … certificate verify failed |
The Greenlight container doesn’t trust the certificate of id.example.org. |
| Keycloak: Invalid redirect uri or Invalid post logout redirect uri | Compare the URIs in the client with step 2. Greenlight sends …/?success=LogoutSuccessful, which the wildcard https://bbb.example.org/* covers. |
| Meetings don’t start | BIGBLUEBUTTON_ENDPOINT must end in /bigbluebutton/api/. Check the secret with bbb-conf --secret. |
Tested with
- Nubus for Kubernetes 1.23.0 (Keycloak 26.7) on a local kind cluster, with the LDAP mapper created as in step 1 option B
- Greenlight v3.9.0.1: SSO, portal SSO, RP-initiated logout, migration with
USE_EMAIL_AS_EXTERNAL_ID_FALLBACK, disabled users, meeting start and join - BigBlueButton: public test server
test-install.blindsidenetworks.com
Links
- Greenlight v3: installation, external authentication, source
- BigBlueButton: server installation
- Nubus for Kubernetes: Operation Manual, Keycloak configuration, Architecture Manual
- Keycloak: OIDC logout