diff --git a/backend/src/main/java/com/bakdata/conquery/apiv1/RequestHelper.java b/backend/src/main/java/com/bakdata/conquery/apiv1/RequestHelper.java index 6ce8182ebf..8e5aba7332 100644 --- a/backend/src/main/java/com/bakdata/conquery/apiv1/RequestHelper.java +++ b/backend/src/main/java/com/bakdata/conquery/apiv1/RequestHelper.java @@ -1,8 +1,12 @@ package com.bakdata.conquery.apiv1; +import java.net.URI; import java.net.URL; import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -28,4 +32,25 @@ public static String getRequestURL(HttpServletRequest req) { return StringUtils.removeEnd(host, req.getServletPath()); //remove prefix path } + /** + * Resolves proxied paths to the requested original URI if necessary. + */ + public static URI getRequestURL(ContainerRequestContext req) { + final MultivaluedMap headers = req.getHeaders(); + if (headers.getFirst(AdditionalHeaders.HTTP_HEADER_REAL_HOST) != null) { + try { + return new URL( + headers.getFirst(AdditionalHeaders.HTTP_HEADER_REAL_PROTO), + headers.getFirst(AdditionalHeaders.HTTP_HEADER_REAL_HOST), + "" + ).toURI(); + } catch (Exception e) { + log.warn("Failed to build response URL from X-Forward headers", e); + } + } + + // Fallback: drop path and query, use only schema, authority and port + return req.getUriInfo().getRequestUriBuilder().replacePath(null).replaceQuery(null).build(); + } + } diff --git a/backend/src/main/java/com/bakdata/conquery/models/auth/basic/JWTokenHandler.java b/backend/src/main/java/com/bakdata/conquery/models/auth/basic/JWTokenHandler.java index e967e8fbe4..1e156b883d 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/auth/basic/JWTokenHandler.java +++ b/backend/src/main/java/com/bakdata/conquery/models/auth/basic/JWTokenHandler.java @@ -94,7 +94,7 @@ else if (tokenHeader != null) { * @return a token */ @Nullable - private static String extractTokenFromHeader(ContainerRequestContext request) { + public static String extractTokenFromHeader(ContainerRequestContext request) { final String header = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION); diff --git a/backend/src/main/java/com/bakdata/conquery/models/auth/web/AuthCookieFilter.java b/backend/src/main/java/com/bakdata/conquery/models/auth/web/AuthCookieFilter.java index 7ea128d265..dcd8e2eeb7 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/auth/web/AuthCookieFilter.java +++ b/backend/src/main/java/com/bakdata/conquery/models/auth/web/AuthCookieFilter.java @@ -76,7 +76,7 @@ public void filter(ContainerRequestContext requestContext) throws IOException { @Override public void filter(ContainerRequestContext request, ContainerResponseContext response) throws IOException { Cookie cookie = request.getCookies().get(ACCESS_TOKEN); - String token = request.getUriInfo().getQueryParameters().getFirst(ACCESS_TOKEN); + String token = request.getHeaderString(ACCESS_TOKEN); // Set cookie only if a token is present if (!Strings.isNullOrEmpty(token)) { diff --git a/backend/src/main/java/com/bakdata/conquery/models/auth/web/RedirectingAuthFilter.java b/backend/src/main/java/com/bakdata/conquery/models/auth/web/RedirectingAuthFilter.java index 7ff676d4f7..4fe56294ee 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/auth/web/RedirectingAuthFilter.java +++ b/backend/src/main/java/com/bakdata/conquery/models/auth/web/RedirectingAuthFilter.java @@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authc.AuthenticationToken; +import javax.annotation.Priority; import javax.ws.rs.*; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.core.Response; @@ -30,6 +31,7 @@ */ @RequiredArgsConstructor @Slf4j +@Priority(Priorities.AUTHENTICATION) public class RedirectingAuthFilter extends AuthFilter { /** @@ -74,7 +76,7 @@ public void filter(ContainerRequestContext request) throws IOException { } else if (authenticatedRedirects.size() > 1) { log.error("Multiple authenticated redirects generated. Only one should be possible"); - throw new BadRequestException("The request triggered more than multi-step authentication schemas, which is not allowed."); + throw new BadRequestException("The request triggered more than one multi-step authentication schema, which is not allowed."); } // The request was not authenticated, nor was it a step towards an authentication, so we redirect the user to a login. @@ -95,12 +97,8 @@ else if (authenticatedRedirects.size() > 1) { throw new ServiceUnavailableException("No login schema configured"); } - if (loginRedirects.size() == 1) { - // There is only one login schema, redirect the user there - throw new RedirectionException(Response.seeOther(loginRedirects.get(0)).build()); - } - - // There are multiple login schemas, give the user a choice to choose between them + // Give the user a choice to choose between them. (If there is only one schema, still redirect the user there) + // to prevent too many redirects if there was a problem wit the authentication throw new WebApplicationException(Response.ok(new UIView<>("logins.html.ftl", null, loginRedirects)).build()); } } diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/auth/AuthenticationConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/auth/AuthenticationConfig.java index b51dfe6fd0..dc279c1243 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/config/auth/AuthenticationConfig.java +++ b/backend/src/main/java/com/bakdata/conquery/models/config/auth/AuthenticationConfig.java @@ -26,7 +26,7 @@ public class AuthenticationConfig { - public Cookie createAuthCookie(ContainerRequestContext request, String token) { + public NewCookie createAuthCookie(ContainerRequestContext request, String token) { return new NewCookie( AuthCookieFilter.ACCESS_TOKEN, token, @@ -41,6 +41,17 @@ public Cookie createAuthCookie(ContainerRequestContext request, String token) { ); } + public static NewCookie expireAuthCookie() { + return new NewCookie( + AuthCookieFilter.ACCESS_TOKEN, + null, + "/", + null, + null, + 0, + false); + } + @JsonIgnore public AuthCookieFilter getAuthCookieFilter() { return authCookieFilter.updateAndGet( diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java b/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java index c62bf91680..bee37eb592 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java +++ b/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java @@ -1,11 +1,13 @@ package com.bakdata.conquery.models.config.auth; +import com.bakdata.conquery.apiv1.RequestHelper; import com.bakdata.conquery.commands.ManagerNode; import com.bakdata.conquery.io.cps.CPSType; import com.bakdata.conquery.io.jackson.Jackson; import com.bakdata.conquery.models.auth.ConqueryAuthenticationRealm; import com.bakdata.conquery.models.auth.oidc.JwtPkceVerifyingRealm; import com.bakdata.conquery.models.auth.web.RedirectingAuthFilter; +import com.bakdata.conquery.resources.admin.AdminServlet; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; @@ -263,7 +265,7 @@ private URI initiateLogin(ContainerRequestContext request) { URI uri = UriBuilder.fromUri(idpConfiguration.getAuthorizationEndpoint()) .queryParam("response_type","code") .queryParam("client_id", client) - .queryParam("redirect_uri", request.getUriInfo().getRequestUriBuilder().replaceQuery("").build()) + .queryParam("redirect_uri", UriBuilder.fromUri(RequestHelper.getRequestURL(request)).path(AdminServlet.ADMIN_UI).build()) .queryParam("scope","openid") .queryParam("state", UUID.randomUUID()).build(); return uri; @@ -287,7 +289,8 @@ private Response checkForAuthCallback(ContainerRequestContext request) { return null; } - final URI requestUri = request.getUriInfo().getAbsolutePath(); + // Build the original redirect uri + final URI requestUri = UriBuilder.fromUri(RequestHelper.getRequestURL(request)).path(AdminServlet.ADMIN_UI).build(); log.info("Request URI: {}", requestUri); final TokenRequest tokenRequest = new TokenRequest( UriBuilder.fromUri(idpConfiguration.getTokenEndpoint()).build(), diff --git a/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java b/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java index 396a71fc8b..6bac536740 100644 --- a/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java +++ b/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java @@ -10,6 +10,7 @@ import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.core.UriBuilder; +import com.bakdata.conquery.apiv1.RequestHelper; import com.bakdata.conquery.commands.ManagerNode; import com.bakdata.conquery.io.cps.CPSType; import com.bakdata.conquery.models.auth.ConqueryAuthenticationRealm; @@ -18,6 +19,7 @@ import com.bakdata.conquery.models.auth.basic.UserAuthenticationManagementProcessor; import com.bakdata.conquery.models.auth.web.RedirectingAuthFilter; import com.bakdata.conquery.models.config.XodusConfig; +import com.bakdata.conquery.resources.admin.AdminServlet; import com.bakdata.conquery.resources.admin.rest.UserAuthenticationManagementResource; import com.bakdata.conquery.resources.unprotected.LoginResource; import com.bakdata.conquery.resources.unprotected.TokenResource; @@ -98,7 +100,7 @@ private Function loginProvider(DropwizardResourceCo return (ContainerRequestContext request) -> { URI uri = UriBuilder.fromPath(unprotectedAuthAdmin.getUrlPattern()) .path(LoginResource.class) - .queryParam(REDIRECT_URI, request.getUriInfo().getRequestUriBuilder().replaceQuery("").build()) + .queryParam(REDIRECT_URI, UriBuilder.fromUri(RequestHelper.getRequestURL(request)).path(AdminServlet.ADMIN_UI).build()) .build(); return uri; }; diff --git a/backend/src/main/java/com/bakdata/conquery/resources/ResourceConstants.java b/backend/src/main/java/com/bakdata/conquery/resources/ResourceConstants.java index 78733db5fa..a01b2fcd29 100644 --- a/backend/src/main/java/com/bakdata/conquery/resources/ResourceConstants.java +++ b/backend/src/main/java/com/bakdata/conquery/resources/ResourceConstants.java @@ -26,6 +26,8 @@ public class ResourceConstants { public static final String ROLE_ID = "roleId"; public static final String GROUP_ID = "groupId"; public static final String SECONDARY_ID = "secondaryId"; + public static final String ADMIN_SERVLET_PATH = "admin"; + public static final String ADMIN_UI_SERVLET_PATH = "admin-ui"; public static final String FILE_EXTENTION_ARROW_FILE = "arrf"; public static final String FILE_EXTENTION_ARROW_STREAM = "arrs"; diff --git a/backend/src/main/java/com/bakdata/conquery/resources/admin/AdminServlet.java b/backend/src/main/java/com/bakdata/conquery/resources/admin/AdminServlet.java index 4385a3c662..e9234f9bf9 100644 --- a/backend/src/main/java/com/bakdata/conquery/resources/admin/AdminServlet.java +++ b/backend/src/main/java/com/bakdata/conquery/resources/admin/AdminServlet.java @@ -1,5 +1,5 @@ package com.bakdata.conquery.resources.admin; - +import static com.bakdata.conquery.resources.ResourceConstants.*; import java.util.Collections; import com.bakdata.conquery.commands.ManagerNode; @@ -8,7 +8,6 @@ import com.bakdata.conquery.io.jersey.IdParamConverter; import com.bakdata.conquery.io.jersey.RESTServer; import com.bakdata.conquery.models.auth.web.AuthCookieFilter; -import com.bakdata.conquery.models.auth.web.RedirectingAuthFilter; import com.bakdata.conquery.resources.admin.rest.*; import com.bakdata.conquery.resources.admin.ui.AdminUIResource; import com.bakdata.conquery.resources.admin.ui.AuthOverviewUIResource; @@ -35,6 +34,7 @@ @Slf4j public class AdminServlet { + public static final String ADMIN_UI = "admin-ui"; private final AdminProcessor adminProcessor; private final DropwizardResourceConfig jerseyConfig; private final AdminDatasetProcessor adminDatasetProcessor; @@ -48,8 +48,8 @@ public AdminServlet(ManagerNode manager) { RESTServer.configure(manager.getConfig(), jerseyConfig); - manager.getEnvironment().admin().addServlet("admin", new ServletContainer(jerseyConfig)).addMapping("/admin/*"); - manager.getEnvironment().admin().addServlet("admin-ui", new ServletContainer(jerseyConfigUI)).addMapping("/admin-ui/*"); + manager.getEnvironment().admin().addServlet(ADMIN_SERVLET_PATH, new ServletContainer(jerseyConfig)).addMapping("/" + ADMIN_SERVLET_PATH + "/*"); + manager.getEnvironment().admin().addServlet(ADMIN_UI_SERVLET_PATH, new ServletContainer(jerseyConfigUI)).addMapping("/" + ADMIN_UI_SERVLET_PATH + "/*"); jerseyConfig.register(new JacksonMessageBodyProvider(manager.getEnvironment().getObjectMapper())); // freemarker support diff --git a/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminResource.java b/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminResource.java index ce273bdb61..b0c75e099f 100644 --- a/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminResource.java +++ b/backend/src/main/java/com/bakdata/conquery/resources/admin/rest/AdminResource.java @@ -4,6 +4,7 @@ import com.bakdata.conquery.io.jersey.ExtraMimeTypes; import com.bakdata.conquery.models.auth.entities.User; import com.bakdata.conquery.models.common.Range; +import com.bakdata.conquery.models.config.auth.AuthenticationConfig; import com.bakdata.conquery.models.identifiable.ids.specific.DatasetId; import com.bakdata.conquery.models.jobs.Job; import com.bakdata.conquery.models.jobs.JobManagerStatus; @@ -17,6 +18,7 @@ import javax.inject.Inject; import javax.ws.rs.*; +import javax.ws.rs.core.Cookie; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; @@ -81,4 +83,11 @@ public Response cancelJob(@PathParam(JOB_ID) UUID jobId) { public ImmutableMap getJobs() { return processor.getJobs(); } + + @GET + @Path("logout") + public Response logout() { + return Response.ok().cookie(AuthenticationConfig.expireAuthCookie()).build(); + } + } diff --git a/backend/src/main/java/com/bakdata/conquery/resources/admin/ui/AdminUIResource.java b/backend/src/main/java/com/bakdata/conquery/resources/admin/ui/AdminUIResource.java index 20f457f6e2..33f5963bda 100644 --- a/backend/src/main/java/com/bakdata/conquery/resources/admin/ui/AdminUIResource.java +++ b/backend/src/main/java/com/bakdata/conquery/resources/admin/ui/AdminUIResource.java @@ -33,6 +33,7 @@ import com.bakdata.conquery.models.jobs.JobManagerStatus; import com.bakdata.conquery.models.messages.network.specific.CancelJobMessage; import com.bakdata.conquery.models.worker.ShardNodeInformation; +import com.bakdata.conquery.resources.admin.AdminServlet; import com.bakdata.conquery.resources.admin.rest.AdminProcessor; import com.bakdata.conquery.resources.admin.rest.UIProcessor; import com.bakdata.conquery.resources.admin.ui.model.UIView; diff --git a/backend/src/main/resources/com/bakdata/conquery/resources/admin/ui/templates/template.html.ftl b/backend/src/main/resources/com/bakdata/conquery/resources/admin/ui/templates/template.html.ftl index 0bc4c3773c..7638c3a860 100644 --- a/backend/src/main/resources/com/bakdata/conquery/resources/admin/ui/templates/template.html.ftl +++ b/backend/src/main/resources/com/bakdata/conquery/resources/admin/ui/templates/template.html.ftl @@ -81,6 +81,8 @@ + +
@@ -102,6 +104,12 @@ } ) } + + function logout(){ + event.preventDefault(); + rest('/${ctx.staticUriElem.ADMIN_SERVLET_PATH}/logout') + .then(function () { location.reload() }); + } function postFile(event, url) { event.preventDefault(); diff --git a/backend/src/test/resources/tests/endpoints/adminEndpointInfo.json b/backend/src/test/resources/tests/endpoints/adminEndpointInfo.json index 36b33b76d8..23a6b67998 100644 --- a/backend/src/test/resources/tests/endpoints/adminEndpointInfo.json +++ b/backend/src/test/resources/tests/endpoints/adminEndpointInfo.json @@ -229,6 +229,11 @@ "path": "/users/{userId}/roles/{roleId}", "clazz": "UserResource" }, + { + "method": "GET", + "path": "/logout", + "clazz": "AdminResource" + }, { "method": "GET", "path": "/jobs/", diff --git a/docs/Config JSON.md b/docs/Config JSON.md index e0e8f200f6..696d532b42 100644 --- a/docs/Config JSON.md +++ b/docs/Config JSON.md @@ -58,7 +58,7 @@ No fields can be set for this type.

-### JWT_PKCE_REALM [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L41-L43) +### JWT_PKCE_REALM [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L43-L45) A realm that verifies oauth tokens using PKCE.
Details

@@ -69,14 +69,14 @@ Supported Fields: | | Field | Type | Default | Example | Description | | --- | --- | --- | --- | --- | --- | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L56) | additionalTokenChecks | list of `String` | `[]` | | | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L71-L74) | alternativeIdClaims | list of `String` | `[]` | | Which claims hold alternative Ids of the user in case the user name does not match a user. Pay attention, that the user must not be able to alter the value of any of these claims. | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L50-L53) | client | `String` | `null` | | The client id is also used as the expected audience in the validated token. Ensure that the IDP is configured accordingly. | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L65-L67) | idpConfiguration | `IdpConfiguration` | `null` | | See wellKnownEndpoint. | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L59-L62) | wellKnownEndpoint | `URI` | `null` | | Either the wellKnownEndpoint from which an idpConfiguration can be obtained or the idpConfiguration must be supplied. If the idpConfiguration is given, the wellKnownEndpoint is ignored. | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L58) | additionalTokenChecks | list of `String` | `[]` | | | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L73-L76) | alternativeIdClaims | list of `String` | `[]` | | Which claims hold alternative Ids of the user in case the user name does not match a user. Pay attention, that the user must not be able to alter the value of any of these claims. | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L52-L55) | client | `String` | `null` | | The client id is also used as the expected audience in the validated token. Ensure that the IDP is configured accordingly. | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L67-L69) | idpConfiguration | `IdpConfiguration` | `null` | | See wellKnownEndpoint. | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/JwtPkceVerifyingRealmFactory.java#L61-L64) | wellKnownEndpoint | `URI` | `null` | | Either the wellKnownEndpoint from which an idpConfiguration can be obtained or the idpConfiguration must be supplied. If the idpConfiguration is given, the wellKnownEndpoint is ignored. |

-### LOCAL_AUTHENTICATION [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L32) +### LOCAL_AUTHENTICATION [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L34)
Details

@@ -87,10 +87,10 @@ Supported Fields: | | Field | Type | Default | Example | Description | | --- | --- | --- | --- | --- | --- | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L54) | directory | `File` | `"./storage"` | | | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L44) | jwtDuration | `@MinDuration(value=1, unit=TimeUnit.MINUTES) Duration` | `"12 hours"` | | | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L38-L40) | passwordStoreConfig | [XodusConfig](#Type-XodusConfig) | | | Configuration for the password store. An encryption for the store it self might be set here. | -| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L47-L49) | storeName | `String` | `"authenticationStore"` | | The name of the folder the store lives in. | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L56) | directory | `File` | `"./storage"` | | | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L46) | jwtDuration | `@MinDuration(value=1, unit=TimeUnit.MINUTES) Duration` | `"12 hours"` | | | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L40-L42) | passwordStoreConfig | [XodusConfig](#Type-XodusConfig) | | | Configuration for the password store. An encryption for the store it self might be set here. | +| [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/LocalAuthenticationConfig.java#L49-L51) | storeName | `String` | `"authenticationStore"` | | The name of the folder the store lives in. |

### OIDC_AUTHORIZATION_CODE_FLOW [✎](https://github.com/bakdata/conquery/edit/develop/backend/src/main/java/com/bakdata/conquery/models/config/auth/OIDCAuthorizationCodeFlowRealmFactory.java#L11-L13)