Adapter documentation / fix confidential port

This commit is contained in:
AFaust
2020-10-20 21:27:24 +02:00
parent f34b6eed2d
commit a31309296a
13 changed files with 191 additions and 84 deletions

View File

@@ -37,6 +37,8 @@ The Share sub-module provides a Keycloak-based filter and customisations that su
- Share logout action triggering a Keycloak logout (logging user out of other applications handled by Keycloak if those support Keycloak back-channel logout requests)
- [RFC 8693 OAuth 2.0 Token Exchange](https://tools.ietf.org/html/rfc8693) (a [preview functionality in Keycloak](https://www.keycloak.org/docs/latest/securing_apps/#_token-exchange) to properly delegate the Share-tier authentication to the Repository, if signed on via Keycloak SSO
All authentication functionality of this addon is based on OpenID Connect. Though Keycloak does support SAML clients, no support was implemented to have Alfresco act as a SAML client against Keycloak as an alternative to OpenID Connect client behaviour.
# Configuration
The configuration of both the Keycloak server and this module offer a large number of properties to adjust, and various modes of operation. Therefore, the following sub-documents have been created to provide details and guides:
@@ -44,7 +46,7 @@ The configuration of both the Keycloak server and this module offer a large numb
- [Getting Started (Simple Configuration)](./docs/Simple-Configuration.md)
- Repository Configuration Reference
- [Keycloak Subsystem](./docs/Reference-Repository-Subsystem.md)
- [Keycloak Adapter](./docs/Reference-Repository-Adapter.md)
- [Keycloak Adapter](./docs/Reference-Adapter.md)
- [Extension API](./docs/Reference-Repository-Extension.md)
- [Share Configuration Reference](./docs/Reference-Repository.md)

97
docs/Reference-Adapter.md Normal file
View File

@@ -0,0 +1,97 @@
# Keycloak Adapter Configuration Reference
Both the Repository and Share sub-modules of this addon use the Keycloak-provided adapter library to easily integrate with the Keycloak authentication server. In order to retain much of the adapter libraries flexibility when it comes to different deployment scenarios / configurations that Keycloak is able to handle, most of the configuration properties of this library have been exposed for configuration in both the Repository-tier Keycloak authentication subsystem and the Share-tier `share-config-custom.xml`.
Configuration of adapter properties in the Repository-tier subsystem is straight-forward. Properties can be either configured in `alfresco-global.properties` or within the subsystems extension path, e.g. in a `alfresco/extension/subsystems/Authentication/keycloak/keycloak1/*.properties` (assuming the `authentication.chain` contains a value for `keycloak1:keycloak`). All adapter-specific properties use the common key prefix of `keycloak.adapter.`, with the remaining key denoting the specific property to set. In case a particular property of the Keycloak adapter library denotes a map, entries can be specified by simply appending the entry key to property key, e.g. if `keycloak.adapter.propertyX` denotes a map, `keycloak.adapter.propertyX.key1=value1` would set `value1` in the map for the key `key1`.
Configuration of adapter properties in the Share-tier `share-config-custom.xml` is also straight-forward. Instead of using a common property key prefix, the configuration properties are all child elements of the same XML structure. Multiple configuration sections can be defined and their configuration will be properly merged with a reliable last-wins behaviour. Map entries are handled by specifying entry keys as sub-elements of the map-based property. As part of the merging behaviour, any element which is redefined in a later configuration section with an empty value is effectively removed from the configuration - this is in contrast to Alfresco Share's default merging behaviour which generally does not support easy removal of configurations.
`share-config-custom.xml` example for adapter configuration:
```xml
<config evaluator="string-compare" condition="Keycloak">
<keycloak-adapter-config>
<directAuthHost></directAuthHost>
<auth-server-url>http://localhost:8180/auth</auth-server-url>
<realm>alfresco</realm>
<resource>alfresco-share</resource>
<credentials> <!-- map-based property -->
<provider>secret</provider>
<secret>...</secret>
</credentials>
</keycloak-adapter-config>
</config>
```
## Supported Adapter Properties
Note: This listing does not include the common property key prefix `keycloak.adapter.` that needs to be prepended in Repository-tier configuration.
| Property | Default Value | Description |
| --- | ---: | --- |
| `auth-server-url` | `http://localhost:8180/auth` | Publically resolvable base URL to the Keycloak server to be used in redirect URLs and remote calls |
| `directAuthHost` | | Alternative base URL for the Keycloak server (excluding path) to be used for calls from Alfresco to Keycloak - useful e.g. in scenarios where the regular `auth-server-url` can not be resolved or round-trips via a public gateway / proxy should be avoided |
| `realm` | `alfresco` | Technical name of the Keycloak realm |
| `realm-public-key` | | Fixed public key of the realm (PEM string) - if not set, the public key(s) will be dynamically loaded and automatically refreshed after a configurable amount of times between JSON Web Key Store requests |
| `resource` | `alfresco` / `alfresco-share` | Technical name of the client set up in the realm |
| `ssl-required` | `none` | SSL requirement mode, controlling both redirect URL generation and redirect validation - defaults to `none` for simple default deployment, but should typically be set to `external` (localhost / loopback requests may use HTTP) or `all` |
| `confidential-port` | `-1` | SSL port to use when generating redirect URLs back to an SSL protected Alfresco resource - when a value of `-1` is configured, the addon will try to determine the port from the request, e.g. if a request contains a `X-Forwarded-Port` port with either port `80`/`443`, it is assumed Alfresco is operated behind a proxy and port `443` is used, otherwise the module will try to determine the SSL port from the raw request and fall back to the Tomcat default SSL port `8443`. This property **must to be changed** if Alfresco is operated in any constellation other than previously described. |
| `bearer-only` | `false` | Flag determining whether authentication handling is terminated after checking for bearer token |
| `autodetect-bearer-only` | `false` | Flag determining whether the Keycloak adapter library should attempt to determine if authentication handling for a request should be terminated after checking for bearer token (i.e. XMLHttpRequest, SOAPAction, or partial Faces requests, or any other request that does not accept `text/html`, `text/*` or `*/*` response content types) |
| `enable-basic-auth` | `false` | Flag determining whether the Keycloak adapter library should handle basic authentications - if enabled, this supersedes any Alfresco provided basic authentication handling, limiting users to Keycloak-authenticated users only |
| `public-client` | `false` | Flag whether the client uses the authentication flow of an OAuth public client |
| `credentials` | | Map of credential parameters use to configure the way the client authenticates against Keycloak for direct requests |
| `credentials.provider` | `secret` | Type of credential provider to use for client authentication - out-of-the-box, this addon supports `secret`, `jwt` and `secret-jwt` providers, while additional providers can be provided via Java's `ServiceLoader` facility, using the `ClientCredentialsProvider` interface in the shaded Repository / Share dependencies sub-module |
| `credentials.secret` | | Value of the shared secret to use when either the `secret` or `secret-jwt` credential provider is used |
| `credentials.algorithm` | `HS256` | Signing algorithm to use when the `secret-jwt` credential provider is used |
| `credentials.client-keystore-file` | | File or class path location of the client's keystore, when the `jwt` credential provider is used |
| `credentials.client-keystore-type` | | Type of the client's keystore, when the `jwt` credential provider is used |
| `credentials.client-keystore-password` | | Password of the client's keystore, when the `jwt` credential provider is used |
| `credentials.client-key-password` | | Password of the client's key inside the keystore, when the `jwt` credential provider is used |
| `credentials.client-key-alias` | | Alias of the client's key inside the keystore, when the `jwt` credential provider is used |
| `redirect-rewrite-rules` | | Map of key-value replacement tokens for dynamically rewriting the path of the generated redirect URI - note: only one / the first map entry will actually be processed by the Keycloak adapter library |
| `allow-any-hostname` | `false` | Flag whether to disable the host name verification on the Apache HTTP client used to call Keycloak |
| `disable-trust-manager` | `false` | Flag whether to disable the trust manager on the Apache HTTP client used to call Keycloak |
| `truststore` | | File or class path location of the client's custom truststore for validating Keycloak's SSL server certificate |
| `truststore-password` | | Password of the client's custom truststore for validating Keycloak's SSL server certificate |
| `client-keystore` | | File or class path location of the client's keystore containing its SSL client certificate to be presented to the Keycloak server |
| `client-keystore-password` | | Password for the client's keystore containing its SSL client certificate to be presented to the Keycloak server |
| `client-key-password` | | Password for the client's key within the keystore containing its SSL client certificate to be presented to the Keycloak server |
| `connection-pool-size` | `20` | Number of connections in the Apache HTTP clients connection pool for calls to the Keycloak server |
| `always-refresh-token` | `true` | Flag determining whether a user's access token should always be refreshed when its remaining time-to-live is less than the allowed minimum value, or it has already expired - if `false`, user logins in Alfresco will effectively expire and require a new (transparent) authentication via Keycloak, as no component in the addon performs an explicit refresh |
| `adapter-state-cookie-path` | | The path to use for the client cookie holding adapter state during execution of the authentication redirects - if not set, this will use the context path from the raw request, which is typically the correct value to use |
| `principal-attribute` | | The name of the attribute to extract from the access token as an override to the token's subject for the name of the authenticated principal - since this addon does not use the principal name for anything (only the `preferred_username`), this configuration likely has no practical effect if changed |
| `token-minimum-time-to-live` | | The minimum allowed time-to-live for an access token in seconds - if an access token is returned by Keycloak in exchange for an authorisation code or as part of a token refresh with a lower time-to-live, the validation of that token will fail |
| `min-time-between-jwks-requests` | `10` | The minimum time in seconds that must be elapsed between two JSON Web Key Store requests to Keycloak to load public key(s) of the realm |
| `public-key-cache-ttl` | `86400` | Time-to-live in seconds for public key cache entries |
| `ignore-oauth-query-parameter` | `false` | Flag determining whether OAuth `access_token` in an URL query is to be ignored |
| `verify-token-audience` | `true` / `false` | Flag enabling validation of the audience specified in an access token, enabled by default on the Repository-tier - must be disabled if Share or any other application which authenticates users via Keycloak is not delegating user authentication using RFC 8693 OAuth 2.0 Token Exchange |
## Non-Standard Adapter Properties
The following properties are not supported by the Keycloak adapter library, but have been added by the addon for customisation of the adapter's behaviour.
| Property | Default Value | Description |
| --- | ---: | --- |
| `connectionTimeout` | `-1` | Connect timeout for the Apache HTTP client used in calls to Keycloak |
| `socketTimeout` | `-1` | General socket timeout for the Apache HTTP client used in calls to Keycloak |
## Unsupported Adapter Properties
This listing details configuration properties from the Keycloak adapter library which are not supported by this addon and may result in `UnsupportedOperationException` or other errors potentially being triggered at runtime when set to a non-default value.
| Property | Default Value | Description |
| --- | ---: | --- |
| `use-resource-role-mappings` | `false` | Flag effectively limited to determining whether resource config on Keycloak can override the realm's caller verification setting. If caller verification is required, clients must provide a certificate. - This is not supported by the Keycloak adapter library outside of a JBoss deployment. |
| `enable-cors` | `false` | Flag enabling special handling for CORS requests (e.g. containing an Origin header). - No tests or special considerations have been done for CORS requests, as CORS should not be relevant in a proper Alfresco setup (e.g. whenever CORS would be needed for an ADF app or similar SPA, a simple proxy should do the trick without all the complexities of CORS). Additionally, CORS handling in Alfresco is already [provided out-of-the-box](https://docs.alfresco.com/6.2/concepts/enabling-cors.html). |
| `cors-max-age` | `-1` | Value for the HTTP `Access-Control-Max-Age` response header |
| `cors-allowed-headers` | | Value for the HTTP `Access-Control-Allow-Headers` response header |
| `cors-allowed-methods` | | Value for the HTTP `Access-Control-Allow-Methods` response header |
| `cors-exposed-headers` | | Value for the HTTP `Access-Control-Expose-Headers`response header |
| `expose-token` | `false` | Flag determining whether CORS requests can retrieve a bearer token via special request URI |
| `register-node-at-startup` | `false` | Flag determining whether the Keycloak adapter will register the node (server) with the Keycloak server - not relevant on Alfresco installations as this relates to [clustering on JBoss server technology](https://www.keycloak.org/docs/latest/securing_apps/#_applicationclustering), this addon already handles relevant caches for potential clustering in Alfresco Enterprise, and the necessary component of the Keycloak adapter library is not used in the integration of this addon |
| `register-node-period` | `-1` | Time in seconds between node registration requests |
| `token-store` | `session` | Mode for how the Keycloak adapter stores user account information - related to clustering like previous two settings and not relevant for the integration as provided by the addon |
| `turn-off-change-session-id-on-login` | | Completely unused flag in the Keycloak adapter library |
| `policy-enforcer` | | Complex configuration object determining fine-grained access policies to the Repository / Share application. - This is currently not supported for configuration by the addon due to use of complex object structures |
| `enable-pkce` | `false` | RFC 7636 - Flag enabling the use of the Proof Key for Code Exchange for OAuth public clients. - This has not yet implemented by the Keycloak adapter library. |

View File

@@ -99,11 +99,11 @@ The following core configuration properties can be set (more extensive list in t
| `...groupFilter.containedInGroup.property.groupPaths` | | Comma-separated list of group paths (e.g. `/Group A/Group B,/Group A/Group C`) to use in filtering which groups are synchronised to Alfresco (by default - configured separately - any match qualifies, and transitive containment is considered) |
| `...groupFilter.containedInGroup.property.groupIds` | | Comma-separated list of group IDs to use in filtering which groups are synchronised to Alfresco (by default - configured separately - any match qualifies, and transitive containment is considered) |
| `keycloak.adapter.auth-server-url` | `http://localhost:8180/auth` | Publically resolvable base URL to the Keycloak server to be used in redirect URLs and remote calls |
| `keycloak.authentication.directAuthHost` | | Alternative base URL for the Keycloak server (excluding path) to be used for calls from Alfresco to Keycloak - useful e.g. in scenarios where the regular `auth-server-url` can not be resolved by the Alfresco Repository host or round-trips via a public gateway / proxy should be avoided |
| `keycloak.adapter.realm` | `alfresco` | Technical name of the Keycloak realm |
| `keycloak.adapter.resource` | `alfresco` | Technical name of the client set up for the Alfresco Repository in the realm |
| `keycloak.adapter.keycloak.adapter.credentials.secret` | | Shared secret for validation of authorisation codes / access tokens |
| `keycloak.adapter.verify-token-audience` | `true` | Flag enabling validation of the audience specified in an access token - must be disabled if Share or any other application which authenticates users via Keycloak is not delegating user authentication using RFC 8693 OAuth 2.0 Token Exchange |
| `...directAuthHost` | | Alternative base URL for the Keycloak server (excluding path) to be used for calls from Alfresco to Keycloak - useful e.g. in scenarios where the regular `auth-server-url` can not be resolved by the Alfresco Repository host or round-trips via a public gateway / proxy should be avoided |
| `...realm` | `alfresco` | Technical name of the Keycloak realm |
| `...resource` | `alfresco` | Technical name of the client set up for the Alfresco Repository in the realm |
| `...keycloak.adapter.credentials.secret` | | Shared secret for validation of authorisation codes / access tokens |
| `...verify-token-audience` | `true` | Flag enabling validation of the audience specified in an access token - must be disabled if Share or any other application which authenticates users via Keycloak is not delegating user authentication using RFC 8693 OAuth 2.0 Token Exchange |
## Alfresco Share

View File

@@ -30,9 +30,9 @@
<bean id="keycloakDeployment" class="${project.artifactId}.spring.KeycloakDeploymentBeanFactory">
<property name="adapterConfig" ref="keycloakAdapterConfig" />
<property name="connectionTimeout" value="${keycloak.authentication.connectionTimeout}" />
<property name="socketTimeout" value="${keycloak.authentication.socketTimeout}" />
<property name="directAuthHost" value="${keycloak.authentication.directAuthHost}" />
<property name="connectionTimeout" value="${keycloak.adapter.connectionTimeout}" />
<property name="socketTimeout" value="${keycloak.adapter.socketTimeout}" />
<property name="directAuthHost" value="${keycloak.adapter.directAuthHost}" />
</bean>
<bean id="sessionIdMapper" class="${project.artifactId}.authentication.SimpleCacheBackedSessionIdMapper">
@@ -135,7 +135,6 @@
<property name="originalRequestUrlHeaderName" value="${keycloak.authentication.sso.originalRequestUrlHeaderName}" />
<property name="noKeycloakHandlingHeaderName" value="x-${moduleId}-no-keycloak-handling" />
<property name="bodyBufferLimit" value="${keycloak.authentication.bodyBufferLimit}" />
<property name="sslRedirectPort" value="${keycloak.authentication.sslRedirectPort}" />
<property name="keycloakDeployment" ref="keycloakDeployment" />
<property name="sessionIdMapper" ref="sessionIdMapper" />

View File

@@ -13,19 +13,20 @@ keycloak.authentication.mapPersonPropertiesOnLogin=true
keycloak.authentication.authenticateFTP=true
keycloak.authentication.silentRemoteUserValidationFailure=true
keycloak.authentication.connectionTimeout=-1
keycloak.authentication.socketTimeout=-1
keycloak.authentication.sslRedirectPort=8443
keycloak.authentication.bodyBufferLimit=10485760
# override for a direct route to the auth server host
# useful primarily for Docker-ized deployments where container running Alfresco cannot resolve the auth server via the public DNS name
keycloak.authentication.directAuthHost=
keycloak.adapter.directAuthHost=
# other custom adapter properties not part of default Keycloak adapter library
keycloak.adapter.connectionTimeout=-1
keycloak.adapter.socketTimeout=-1
keycloak.adapter.auth-server-url=http://localhost:8180/auth
keycloak.adapter.realm=alfresco
keycloak.adapter.resource=alfresco
keycloak.adapter.ssl-required=none
keycloak.adapter.confidential-port=-1
keycloak.adapter.public-client=false
keycloak.adapter.credentials.provider=secret
keycloak.adapter.credentials.secret=

View File

@@ -126,10 +126,6 @@ public class KeycloakAuthenticationFilter extends BaseAuthenticationFilter
protected int bodyBufferLimit = DEFAULT_BODY_BUFFER_LIMIT;
// use 8443 as default SSL redirect based on Tomcat default server.xml configuration
// can't rely on SysAdminParams#getAlfrescoPort either because that may be proxied / non-SSL
protected int sslRedirectPort = 8443;
protected KeycloakDeployment keycloakDeployment;
protected SessionIdMapper sessionIdMapper;
@@ -250,15 +246,6 @@ public class KeycloakAuthenticationFilter extends BaseAuthenticationFilter
this.bodyBufferLimit = bodyBufferLimit;
}
/**
* @param sslRedirectPort
* the sslRedirectPort to set
*/
public void setSslRedirectPort(final int sslRedirectPort)
{
this.sslRedirectPort = sslRedirectPort;
}
/**
* @param keycloakDeployment
* the keycloakDeployment to set
@@ -540,8 +527,11 @@ public class KeycloakAuthenticationFilter extends BaseAuthenticationFilter
final OIDCFilterSessionStore tokenStore = new OIDCFilterSessionStore(req, facade,
this.bodyBufferLimit > 0 ? this.bodyBufferLimit : DEFAULT_BODY_BUFFER_LIMIT, this.keycloakDeployment, this.sessionIdMapper);
final int sslPort = this.determineLikelySslPort(req);
final FilterRequestAuthenticator authenticator = new FilterRequestAuthenticator(this.keycloakDeployment, tokenStore, facade, req,
this.sslRedirectPort);
sslPort);
final AuthOutcome authOutcome = authenticator.authenticate();
if (authOutcome == AuthOutcome.AUTHENTICATED)
@@ -1252,6 +1242,38 @@ public class KeycloakAuthenticationFilter extends BaseAuthenticationFilter
}
}
/**
* Determines the likely SSL port to be used in redirects from the incoming request. This operation should only be used to determine a
* technical default value in lieu of an explicitly configured value.
*
* @param req
* the incoming request
* @return the assumed SSL port to be used in redirects
*/
protected int determineLikelySslPort(final HttpServletRequest req)
{
int rqPort = req.getServerPort();
final String forwardedPort = req.getHeader("X-Forwarded-Port");
if (forwardedPort != null && forwardedPort.matches("^\\d+$"))
{
rqPort = Integer.parseInt(forwardedPort);
}
final int sslPort;
if (rqPort == 80 || rqPort == 443)
{
sslPort = 443;
}
else if (req.isSecure() && "https".equals(req.getScheme()))
{
sslPort = rqPort;
}
else
{
sslPort = 8443;
}
return sslPort;
}
/**
* {@inheritDoc}
*/

View File

@@ -25,7 +25,7 @@ keycloak.adapter.credentials.provider=secret
keycloak.adapter.credentials.secret=6f70a28f-98cd-41ca-8f2f-368a8797d708
# localhost in auth-server-url won't work for direct access in a Docker deployment
keycloak.authentication.directAuthHost=http://keycloak:8080
keycloak.adapter.directAuthHost=http://keycloak:8080
keycloak.synchronization.userFilter.containedInGroup.property.groupPaths=/Test A
keycloak.synchronization.groupFilter.containedInGroup.property.groupPaths=/Test A

View File

@@ -31,8 +31,6 @@
<enhance-login-form>true</enhance-login-form>
<enable-sso-filter>true</enable-sso-filter>
<force-keycloak-sso>false</force-keycloak-sso>
<!-- use 8443 as default SSL redirect based on Tomcat default server.xml configuration -->
<ssl-redirect-port>8443</ssl-redirect-port>
<body-buffer-limit>10485760</body-buffer-limit>
<session-mapper-limit>1000</session-mapper-limit>
<ignore-default-filter>true</ignore-default-filter>
@@ -43,8 +41,9 @@
<!-- by default use the same client as alfresco (not really "clean") -->
<auth-server-url>http://localhost:8180/auth</auth-server-url>
<realm>alfresco</realm>
<resource>alfresco</resource>
<resource>alfresco-share</resource>
<ssl-required>none</ssl-required>
<confidential-port>-1</confidential-port>
<!-- other than content-app / Identity Service, Share must/should be a confidential client to exchange code for access token + refresh -->
<public-client>false</public-client>
<credentials>

View File

@@ -39,8 +39,6 @@ public class KeycloakAuthenticationConfigElement extends BaseCustomConfigElement
protected final ConfigValueHolder<Integer> bodyBufferLimit = new ConfigValueHolder<>();
protected final ConfigValueHolder<Integer> sslRedirectPort = new ConfigValueHolder<>();
protected final ConfigValueHolder<Integer> sessionMapperLimit = new ConfigValueHolder<>();
protected final ConfigValueHolder<Boolean> ignoreDefaultFilter = new ConfigValueHolder<>();
@@ -125,23 +123,6 @@ public class KeycloakAuthenticationConfigElement extends BaseCustomConfigElement
return this.bodyBufferLimit.getValue();
}
/**
* @param sslRedirectPort
* the sslRedirectPort to set
*/
public void setSslRedirectPort(final Integer sslRedirectPort)
{
this.sslRedirectPort.setValue(sslRedirectPort);
}
/**
* @return the sslRedirectPort
*/
public Integer getSslRedirectPort()
{
return this.sslRedirectPort.getValue();
}
/**
* @param sessionMapperLimit
* the sessionMapperLimit to set
@@ -265,16 +246,6 @@ public class KeycloakAuthenticationConfigElement extends BaseCustomConfigElement
otherConfigElement.getBodyBufferLimit() != null ? otherConfigElement.getBodyBufferLimit() : this.getBodyBufferLimit());
}
if (otherConfigElement.sslRedirectPort.isUnset())
{
combined.sslRedirectPort.unset();
}
else
{
combined.setSslRedirectPort(
otherConfigElement.getSslRedirectPort() != null ? otherConfigElement.getSslRedirectPort() : this.getSslRedirectPort());
}
if (otherConfigElement.sessionMapperLimit.isUnset())
{
combined.sessionMapperLimit.unset();
@@ -341,9 +312,6 @@ public class KeycloakAuthenticationConfigElement extends BaseCustomConfigElement
builder.append("bodyBufferLimit=");
builder.append(this.bodyBufferLimit);
builder.append(", ");
builder.append("sslRedirectPort=");
builder.append(this.sslRedirectPort);
builder.append(", ");
builder.append("sessionMapperLimit=");
builder.append(this.sessionMapperLimit);
builder.append(", ");

View File

@@ -65,13 +65,6 @@ public class KeycloakAuthenticationConfigElementReader implements ConfigElementR
configElement.setBodyBufferLimit(value.isEmpty() ? null : Integer.valueOf(value));
}
final Element sslRedirectPort = element.element("ssl-redirect-port");
if (sslRedirectPort != null)
{
final String value = sslRedirectPort.getTextTrim();
configElement.setSslRedirectPort(value.isEmpty() ? null : Integer.valueOf(value));
}
final Element sessionMapperLimit = element.element("session-mapper-limit");
if (sessionMapperLimit != null)
{

View File

@@ -556,7 +556,6 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
.getConfig(KeycloakConfigConstants.KEYCLOAK_CONFIG_SECTION_NAME).getConfigElement(KeycloakAuthenticationConfigElement.NAME);
final Integer bodyBufferLimit = keycloakAuthConfig.getBodyBufferLimit();
final Integer sslRedirectPort = keycloakAuthConfig.getSslRedirectPort();
final OIDCServletHttpFacade facade = new OIDCServletHttpFacade(req, res);
@@ -604,7 +603,7 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
}
else
{
this.processFilterAuthentication(context, req, res, chain, bodyBufferLimit, sslRedirectPort, facade);
this.processFilterAuthentication(context, req, res, chain, bodyBufferLimit, facade);
}
}
@@ -689,8 +688,6 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
* @param bodyBufferLimit
* the configured size limit to apply to any HTTP POST/PUT body buffering that may need to be applied to process the
* authentication via an intermediary redirect
* @param sslRedirectPort
* the configured port to use for any forced redirection to HTTPS/SSL communication
* @param facade
* the Keycloak HTTP facade
* @throws IOException
@@ -699,8 +696,7 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
* if any error occurs during Keycloak authentication or processing of the filter chain
*/
protected void processFilterAuthentication(final ServletContext context, final HttpServletRequest req, final HttpServletResponse res,
final FilterChain chain, final Integer bodyBufferLimit, final Integer sslRedirectPort, final OIDCServletHttpFacade facade)
throws IOException, ServletException
final FilterChain chain, final Integer bodyBufferLimit, final OIDCServletHttpFacade facade) throws IOException, ServletException
{
final OIDCFilterSessionStore tokenStore = new OIDCFilterSessionStore(req, facade,
bodyBufferLimit != null ? bodyBufferLimit.intValue() : DEFAULT_BODY_BUFFER_LIMIT, this.keycloakDeployment,
@@ -708,7 +704,7 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
// use 8443 as default SSL redirect based on Tomcat default server.xml configuration
final FilterRequestAuthenticator authenticator = new FilterRequestAuthenticator(this.keycloakDeployment, tokenStore, facade, req,
sslRedirectPort != null ? sslRedirectPort.intValue() : 8443);
this.keycloakDeployment.getConfidentialPort());
final AuthOutcome authOutcome = authenticator.authenticate();
if (authOutcome == AuthOutcome.AUTHENTICATED)
@@ -814,7 +810,6 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
.getConfig(KeycloakConfigConstants.KEYCLOAK_CONFIG_SECTION_NAME).getConfigElement(KeycloakAuthenticationConfigElement.NAME);
final Integer bodyBufferLimit = keycloakAuthConfig.getBodyBufferLimit();
final Integer sslRedirectPort = keycloakAuthConfig.getSslRedirectPort();
// fake a request that will yield a redirect
final HttpServletRequest wrappedReq = new HttpServletRequestWrapper(req)
@@ -838,9 +833,9 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
final OIDCFilterSessionStore tokenStore = new OIDCFilterSessionStore(req, captureFacade,
bodyBufferLimit != null ? bodyBufferLimit.intValue() : DEFAULT_BODY_BUFFER_LIMIT, this.keycloakDeployment, null);
// use 8443 as default SSL redirect based on Tomcat default server.xml configuration
final OAuthRequestAuthenticator authenticator = new OAuthRequestAuthenticator(null, captureFacade, this.keycloakDeployment,
sslRedirectPort != null ? sslRedirectPort.intValue() : 8443, tokenStore);
final int sslPort = this.determineLikelySslPort(req);
final OAuthRequestAuthenticator authenticator = new OAuthRequestAuthenticator(null, captureFacade, this.keycloakDeployment, sslPort,
tokenStore);
final AuthOutcome authOutcome = authenticator.authenticate();
if (authOutcome != AuthOutcome.NOT_ATTEMPTED)
@@ -1781,6 +1776,38 @@ public class KeycloakAuthenticationFilter implements DependencyInjectedFilter, I
}
}
/**
* Determines the likely SSL port to be used in redirects from the incoming request. This operation should only be used to determine a
* technical default value in lieu of an explicitly configured value.
*
* @param req
* the incoming request
* @return the assumed SSL port to be used in redirects
*/
protected int determineLikelySslPort(final HttpServletRequest req)
{
int rqPort = req.getServerPort();
final String forwardedPort = req.getHeader("X-Forwarded-Port");
if (forwardedPort != null && forwardedPort.matches("^\\d+$"))
{
rqPort = Integer.parseInt(forwardedPort);
}
final int sslPort;
if (rqPort == 80 || rqPort == 443)
{
sslPort = 443;
}
else if (req.isSecure() && "https".equals(req.getScheme()))
{
sslPort = rqPort;
}
else
{
sslPort = 8443;
}
return sslPort;
}
/**
* Sets up a forced route for the Keycloak-library backing HTTP client if configured. This may be necessary to deal with situations
* where Share cannot use the public address of the authentication server (used in authentication redirects) to talk with the server

View File

@@ -52,7 +52,6 @@ public class KeycloakAdapterConfigTest
Assert.assertTrue(keycloakAuthConfig.getEnhanceLoginForm());
Assert.assertTrue(keycloakAuthConfig.getEnableSsoFilter());
Assert.assertFalse(keycloakAuthConfig.getForceKeycloakSso());
Assert.assertEquals(Integer.valueOf(8443), keycloakAuthConfig.getSslRedirectPort());
Assert.assertEquals(Integer.valueOf(10485760), keycloakAuthConfig.getBodyBufferLimit());
Assert.assertEquals(Integer.valueOf(1000), keycloakAuthConfig.getSessionMapperLimit());
@@ -99,7 +98,6 @@ public class KeycloakAdapterConfigTest
Assert.assertFalse(keycloakAuthConfig.getEnhanceLoginForm());
Assert.assertFalse(keycloakAuthConfig.getEnableSsoFilter());
Assert.assertFalse(keycloakAuthConfig.getForceKeycloakSso());
Assert.assertEquals(Integer.valueOf(8443), keycloakAuthConfig.getSslRedirectPort());
Assert.assertEquals(Integer.valueOf(10485760), keycloakAuthConfig.getBodyBufferLimit());
Assert.assertEquals(Integer.valueOf(2000), keycloakAuthConfig.getSessionMapperLimit());

View File

@@ -40,6 +40,7 @@
<alfresco-resource-name>alfresco</alfresco-resource-name>
</keycloak-auth-config>
<keycloak-adapter-config>
<directAuthHost>http://keycloak:8080</directAuthHost>
<!-- by default use the same client as alfresco (not really "clean") -->
<auth-server-url>http://localhost:8180/auth</auth-server-url>
<realm>alfresco</realm>