Add custom groups scope claim name

This commit is contained in:
Alexey Klyucherev 2024-08-13 12:39:50 +07:00
parent 237cd5d45f
commit f2573b4485
2 changed files with 22 additions and 7 deletions

View File

@ -698,6 +698,14 @@ public final class Keys {
"openid.userInfoUrl",
List.of(KeyType.CONFIG));
/**
* OpenID Connect group scope claim name.
* If this is not provided, Traccar will use name "groups" scope.
*/
public static final ConfigKey<String> OPENID_GROUPS_CLAIM_NAME = new StringConfigKey(
"openid.groupsClaimName",
List.of(KeyType.CONFIG));
/**
* OpenID Connect group to restrict access to.
* If this is not provided, all OpenID users will have access to Traccar.

View File

@ -33,6 +33,8 @@ import java.security.GeneralSecurityException;
import java.util.List;
import java.util.Map;
import java.io.IOException;
import java.util.Objects;
import jakarta.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.core.type.TypeReference;
@ -73,12 +75,13 @@ public class OpenIdProvider {
private final URI baseUrl;
private final String adminGroup;
private final String allowGroup;
private final String groupsClaimName;
private final LoginService loginService;
@Inject
public OpenIdProvider(Config config, LoginService loginService, HttpClient httpClient, ObjectMapper objectMapper)
throws InterruptedException, IOException, URISyntaxException {
throws InterruptedException, IOException, URISyntaxException {
this.loginService = loginService;
@ -89,11 +92,12 @@ public class OpenIdProvider {
baseUrl = new URI(WebHelper.retrieveWebUrl(config));
callbackUrl = new URI(WebHelper.retrieveWebUrl(config) + "/api/session/openid/callback");
if (config.hasKey(Keys.OPENID_ISSUER_URL)) {
HttpRequest httpRequest = HttpRequest.newBuilder(
URI.create(config.getString(Keys.OPENID_ISSUER_URL) + "/.well-known/openid-configuration"))
.header("Accept", "application/json")
.build();
URI.create(config.getString(Keys.OPENID_ISSUER_URL) + "/.well-known/openid-configuration"))
.header("Accept", "application/json")
.build();
String httpResponse = httpClient.send(httpRequest, BodyHandlers.ofString()).body();
@ -111,13 +115,14 @@ public class OpenIdProvider {
adminGroup = config.getString(Keys.OPENID_ADMIN_GROUP);
allowGroup = config.getString(Keys.OPENID_ALLOW_GROUP);
groupsClaimName = config.getString(Keys.OPENID_GROUPS_CLAIM_NAME);
}
public URI createAuthUri() {
Scope scope = new Scope("openid", "profile", "email");
if (adminGroup != null) {
scope.add("groups");
scope.add(Objects.requireNonNullElse(groupsClaimName, "groups"));
}
AuthenticationRequest.Builder request = new AuthenticationRequest.Builder(
@ -155,7 +160,7 @@ public class OpenIdProvider {
if (!userInfoResponse.indicatesSuccess()) {
throw new GeneralSecurityException(
"Failed to access OpenID Connect user info endpoint. Please contact your administrator.");
"Failed to access OpenID Connect user info endpoint. Please contact your administrator.");
}
return userInfoResponse.toSuccessResponse().getUserInfo();
@ -182,7 +187,9 @@ public class OpenIdProvider {
UserInfo userInfo = getUserInfo(bearerToken);
List<String> userGroups = userInfo.getStringListClaim("groups");
List<String> userGroups = groupsClaimName != null
? userInfo.getStringListClaim(groupsClaimName)
: userInfo.getStringListClaim("groups");
boolean administrator = adminGroup != null && userGroups.contains(adminGroup);
if (!(administrator || allowGroup == null || userGroups.contains(allowGroup))) {