diff options
Diffstat (limited to 'src/main/java/org/traccar/database')
-rw-r--r-- | src/main/java/org/traccar/database/OpenIdProvider.java | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/src/main/java/org/traccar/database/OpenIdProvider.java b/src/main/java/org/traccar/database/OpenIdProvider.java index 537319b31..d0ec4e98d 100644 --- a/src/main/java/org/traccar/database/OpenIdProvider.java +++ b/src/main/java/org/traccar/database/OpenIdProvider.java @@ -22,16 +22,22 @@ import org.traccar.api.security.LoginService; import org.traccar.model.User; import org.traccar.storage.StorageException; import org.traccar.helper.LogAction; -import org.traccar.helper.ServletHelper; +import org.traccar.helper.WebHelper; import java.net.URI; import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse.BodyHandlers; import java.security.GeneralSecurityException; +import java.util.List; +import java.util.Map; import java.io.IOException; import javax.servlet.http.HttpServletRequest; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.nimbusds.oauth2.sdk.http.HTTPResponse; import com.nimbusds.oauth2.sdk.AuthorizationCode; @@ -54,12 +60,9 @@ import com.nimbusds.openid.connect.sdk.OIDCTokenResponseParser; import com.nimbusds.openid.connect.sdk.UserInfoResponse; import com.nimbusds.openid.connect.sdk.UserInfoRequest; import com.nimbusds.openid.connect.sdk.AuthenticationRequest; - import com.nimbusds.openid.connect.sdk.claims.UserInfo; public class OpenIdProvider { - private static final Logger LOGGER = LoggerFactory.getLogger(OpenIdProvider.class); - private final Boolean force; private final ClientID clientId; private final ClientAuthentication clientAuth; @@ -69,28 +72,45 @@ public class OpenIdProvider { private URI userInfoUrl; private URI baseUrl; private final String adminGroup; + private final String allowGroup; private LoginService loginService; @Inject - public OpenIdProvider(Config config, LoginService loginService) { + public OpenIdProvider( + Config config, LoginService loginService, HttpClient httpClient, ObjectMapper objectMapper + ) throws InterruptedException, IOException, URISyntaxException { this.loginService = loginService; force = config.getBoolean(Keys.OPENID_FORCE); - clientId = new ClientID(config.getString(Keys.OPENID_CLIENTID)); - clientAuth = new ClientSecretBasic(clientId, new Secret(config.getString(Keys.OPENID_CLIENTSECRET))); - - try { - callbackUrl = new URI(config.getString(Keys.WEB_URL, "") + "/api/session/openid/callback"); - authUrl = new URI(config.getString(Keys.OPENID_AUTHURL, "")); - tokenUrl = new URI(config.getString(Keys.OPENID_TOKENURL, "")); - userInfoUrl = new URI(config.getString(Keys.OPENID_USERINFOURL, "")); - baseUrl = new URI(config.getString(Keys.WEB_URL, "")); - } catch (URISyntaxException error) { - LOGGER.error("Invalid URIs provided in OpenID configuration"); + clientId = new ClientID(config.getString(Keys.OPENID_CLIENT_ID)); + clientAuth = new ClientSecretBasic(clientId, new Secret(config.getString(Keys.OPENID_CLIENT_SECRET))); + + 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(); + + String httpResponse = httpClient.send(httpRequest, BodyHandlers.ofString()).body(); + + Map<String, Object> discoveryMap = objectMapper.readValue( + httpResponse, new TypeReference<Map<String, Object>>() { }); + + authUrl = new URI((String) discoveryMap.get("authorization_endpoint")); + tokenUrl = new URI((String) discoveryMap.get("token_endpoint")); + userInfoUrl = new URI((String) discoveryMap.get("userinfo_endpoint")); + } else { + authUrl = new URI(config.getString(Keys.OPENID_AUTH_URL)); + tokenUrl = new URI(config.getString(Keys.OPENID_TOKEN_URL)); + userInfoUrl = new URI(config.getString(Keys.OPENID_USERINFO_URL)); } - adminGroup = config.getString(Keys.OPENID_ADMINGROUP); + adminGroup = config.getString(Keys.OPENID_ADMIN_GROUP); + allowGroup = config.getString(Keys.OPENID_ALLOW_GROUP); } public URI createAuthUri() { @@ -162,12 +182,17 @@ public class OpenIdProvider { UserInfo userInfo = getUserInfo(bearerToken); - Boolean administrator = adminGroup != null && userInfo.getStringListClaim("groups").contains(adminGroup); + List<String> userGroups = userInfo.getStringListClaim("groups"); + Boolean administrator = adminGroup != null && userGroups.contains(adminGroup); + + if (!(administrator || allowGroup == null || userGroups.contains(allowGroup))) { + throw new GeneralSecurityException("Your OpenID Groups do not permit access to Traccar."); + } User user = loginService.login(userInfo.getEmailAddress(), userInfo.getName(), administrator); request.getSession().setAttribute(SessionResource.USER_ID_KEY, user.getId()); - LogAction.login(user.getId(), ServletHelper.retrieveRemoteAddress(request)); + LogAction.login(user.getId(), WebHelper.retrieveRemoteAddress(request)); return baseUrl; } |