Make preferred_username optional for Keycloak
This commit adds a new config option 'use-preferred-username' which
can be used with the Keycloak provider to make it optional to use
the preferred_username delivered by Keycloak.
This is useful in situations where the preferred_username is set
as an email address, which don't work as a gerrit username.
Leaving the username unset also allows the user to choose their
own username.
Change-Id: Iff114537527c672190c6a1a41726d2c32bb97810
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/InitOAuth.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/InitOAuth.java
index 3fbb2ca..c46d088 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/InitOAuth.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/InitOAuth.java
@@ -32,6 +32,7 @@
static final String FIX_LEGACY_USER_ID = "fix-legacy-user-id";
static final String DOMAIN = "domain";
static final String USE_EMAIL_AS_USERNAME = "use-email-as-username";
+ static final String USE_PREFERRED_USERNAME = "use-preferred-username";
static final String ROOT_URL = "root-url";
static final String REALM = "realm";
static final String TENANT = "tenant";
diff --git a/src/main/java/com/googlesource/gerrit/plugins/oauth/KeycloakOAuthService.java b/src/main/java/com/googlesource/gerrit/plugins/oauth/KeycloakOAuthService.java
index 42ff7c4..228dff3 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/oauth/KeycloakOAuthService.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/oauth/KeycloakOAuthService.java
@@ -51,6 +51,7 @@
private static final String KEYCLOAK_PROVIDER_PREFIX = "keycloak-oauth:";
private final OAuth20Service service;
private final String serviceName;
+ private final boolean usePreferredUsername;
@Inject
KeycloakOAuthService(
@@ -66,6 +67,7 @@
}
String realm = cfg.getString(InitOAuth.REALM);
serviceName = cfg.getString(InitOAuth.SERVICE_NAME, "Keycloak OAuth2");
+ usePreferredUsername = cfg.getBoolean(InitOAuth.USE_PREFERRED_USERNAME, true);
service =
new ServiceBuilder(cfg.getString(InitOAuth.CLIENT_ID))
@@ -115,12 +117,17 @@
if (nameElement == null || nameElement.isJsonNull()) {
throw new IOException("Response doesn't contain name field");
}
- String username = usernameElement.getAsString();
+ String usernameAsString = usernameElement.getAsString();
+ String username = null;
+ if (usePreferredUsername) {
+ username = usernameAsString;
+ }
+ String externalId = KEYCLOAK_PROVIDER_PREFIX + usernameAsString;
String email = emailElement.getAsString();
String name = nameElement.getAsString();
return new OAuthUserInfo(
- KEYCLOAK_PROVIDER_PREFIX + username /*externalId*/,
+ externalId /*externalId*/,
username /*username*/,
email /*email*/,
name /*displayName*/,
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 78eb908..91d7288 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -61,6 +61,13 @@
tenant = "<tenant (optional defaults to organizations if not set)>"
link-to-existing-office365-accounts = true #Optional, if set will try to link old account with the @PLUGIN@-office365-oauth naming
+ [plugin "@PLUGIN@-keycloak-oauth"]
+ root-url = "<root url>" # for example, https://signon.example.com
+ realm = "<realm>"
+ client-id = "<client-id>"
+ client-secret = "<client-secret>"
+ use-preferred-username = true # Optional, if false will not send preferred_username from Keycloak to leave username unset
+
```
When one from the sections above is omitted, OAuth SSO is used.
@@ -274,3 +281,14 @@
This will try to link the old `office365-oauth` external id to the new `azure-oauth` external id automatically.
Another option is to migrate these manually offline, see [External IDs](https://gerrit-review.googlesource.com/Documentation/config-accounts.html#external-ids)
for more information.
+
+### Keycloak
+
+When setting up a client in Keycloak for Gerrit, enter a value for the *Client ID* and ensure you choose the `openid-connect`
+protocol and select the `confidential` access type. Once you click save, a *Credentials* tab will appear where you will find
+the Secret.
+
+The root URL will the protocol and hostname of your Keycloak instance (for example, https://signon.example.com).
+
+You can optionally set `use-preferred-username = false` if you would prefer to not have the `preferred_username`
+token be automatically set as the users username, and instead let users choose their own usernames.