Merge pull request #1298 from AOEpeople/KEYCLOAK-1103
KEYCLOAK-1103 proxy configuration for inject header if user is logged in, but do not enforce login
This commit is contained in:
commit
5680be743c
6 changed files with 248 additions and 93 deletions
|
@ -214,7 +214,6 @@ $ java -jar bin/launcher.jar [your-config.json]
|
||||||
</para>
|
</para>
|
||||||
<section>
|
<section>
|
||||||
<title>Constraint Config</title>
|
<title>Constraint Config</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Next under each application you can define one or more constraints in the <literal>constraints</literal> array attribute.
|
Next under each application you can define one or more constraints in the <literal>constraints</literal> array attribute.
|
||||||
A constraint defines a URL pattern relative to the base-path. You can deny, permit, or require authentication for
|
A constraint defines a URL pattern relative to the base-path. You can deny, permit, or require authentication for
|
||||||
|
@ -271,6 +270,14 @@ $ java -jar bin/launcher.jar [your-config.json]
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>permit-and-inject</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Permit all access, but inject the headers, if user is already authenticated.<emphasis>OPTIONAL.</emphasis>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>authenticate</term>
|
<term>authenticate</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -283,6 +290,55 @@ $ java -jar bin/launcher.jar [your-config.json]
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
<section>
|
||||||
|
<title>Header Names Config</title>
|
||||||
|
<para>
|
||||||
|
Next under the list of applications you can override the defaults for the names of the header fields injected by the proxy (see Keycloak Identity Headers).
|
||||||
|
This mapping is optional.
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>keycloak-subject</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
e.g. MYAPP_USER_ID
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>keycloak-username</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
e.g. MYAPP_USER_NAME
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>keycloak-email</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
e.g. MYAPP_USER_EMAIL
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>keycloak-name</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
e.g. MYAPP_USER_ID
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>keycloak-access-token</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
e.g. MYAPP_ACCESS_TOKEN
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<title>Keycloak Identity Headers</title>
|
<title>Keycloak Identity Headers</title>
|
||||||
|
@ -333,6 +389,14 @@ $ java -jar bin/launcher.jar [your-config.json]
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
Header field names can be configured using a map of <literal>header-names</literal> in configuration file:
|
||||||
|
<programlisting><![CDATA[
|
||||||
|
{
|
||||||
|
"header-names" {
|
||||||
|
"keycloak-subject": "MY_SUBJECT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]]></programlisting>
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
|
@ -6,36 +6,59 @@ import io.undertow.util.HttpString;
|
||||||
import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
|
import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
|
||||||
import org.keycloak.representations.IDToken;
|
import org.keycloak.representations.IDToken;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class ConstraintAuthorizationHandler implements HttpHandler {
|
public class ConstraintAuthorizationHandler implements HttpHandler {
|
||||||
public static final HttpString KEYCLOAK_SUBJECT = new HttpString("KEYCLOAK-SUBJECT");
|
|
||||||
public static final HttpString KEYCLOAK_USERNAME = new HttpString("KEYCLOAK-USERNAME");
|
public static final String KEYCLOAK_SUBJECT = "KEYCLOAK_SUBJECT";
|
||||||
public static final HttpString KEYCLOAK_EMAIL = new HttpString("KEYCLOAK-EMAIL");
|
public static final String KEYCLOAK_USERNAME = "KEYCLOAK_USERNAME";
|
||||||
public static final HttpString KEYCLOAK_NAME = new HttpString("KEYCLOAK-NAME");
|
public static final String KEYCLOAK_EMAIL = "KEYCLOAK_EMAIL";
|
||||||
public static final HttpString KEYCLOAK_ACCESS_TOKEN = new HttpString("KEYCLOAK-ACCESS-TOKEN");
|
public static final String KEYCLOAK_NAME = "KEYCLOAK_NAME";
|
||||||
|
public static final String KEYCLOAK_ACCESS_TOKEN = "KEYCLOAK_ACCESS_TOKEN";
|
||||||
|
private final Map<String, HttpString> httpHeaderNames;
|
||||||
|
|
||||||
protected HttpHandler next;
|
protected HttpHandler next;
|
||||||
protected String errorPage;
|
protected String errorPage;
|
||||||
protected boolean sendAccessToken;
|
protected boolean sendAccessToken;
|
||||||
|
|
||||||
public ConstraintAuthorizationHandler(HttpHandler next, String errorPage, boolean sendAccessToken) {
|
public ConstraintAuthorizationHandler(HttpHandler next, String errorPage, boolean sendAccessToken, Map<String, String> headerNames) {
|
||||||
this.next = next;
|
this.next = next;
|
||||||
this.errorPage = errorPage;
|
this.errorPage = errorPage;
|
||||||
this.sendAccessToken = sendAccessToken;
|
this.sendAccessToken = sendAccessToken;
|
||||||
|
|
||||||
|
this.httpHeaderNames = new HashMap<>();
|
||||||
|
this.httpHeaderNames.put(KEYCLOAK_SUBJECT, new HttpString(getOrDefault(headerNames, "keycloak-subject", KEYCLOAK_SUBJECT)));
|
||||||
|
this.httpHeaderNames.put(KEYCLOAK_SUBJECT, new HttpString(getOrDefault(headerNames, "keycloak-username", KEYCLOAK_USERNAME)));
|
||||||
|
this.httpHeaderNames.put(KEYCLOAK_EMAIL, new HttpString(getOrDefault(headerNames, "keycloak-email", KEYCLOAK_EMAIL)));
|
||||||
|
this.httpHeaderNames.put(KEYCLOAK_NAME, new HttpString(getOrDefault(headerNames, "keycloak-name", KEYCLOAK_NAME)));
|
||||||
|
this.httpHeaderNames.put(KEYCLOAK_ACCESS_TOKEN, new HttpString(getOrDefault(headerNames, "keycloak-access-token", KEYCLOAK_ACCESS_TOKEN)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getOrDefault(Map<String, String> map, String key, String defaultValue) {
|
||||||
|
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequest(HttpServerExchange exchange) throws Exception {
|
public void handleRequest(HttpServerExchange exchange) throws Exception {
|
||||||
|
|
||||||
KeycloakUndertowAccount account = (KeycloakUndertowAccount)exchange.getSecurityContext().getAuthenticatedAccount();
|
KeycloakUndertowAccount account = (KeycloakUndertowAccount)exchange.getSecurityContext().getAuthenticatedAccount();
|
||||||
|
|
||||||
SingleConstraintMatch match = exchange.getAttachment(ConstraintMatcherHandler.CONSTRAINT_KEY);
|
SingleConstraintMatch match = exchange.getAttachment(ConstraintMatcherHandler.CONSTRAINT_KEY);
|
||||||
if (match == null || (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.AUTHENTICATE)) {
|
if (match == null || (match.getRequiredRoles().isEmpty() && match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.AUTHENTICATE)) {
|
||||||
authenticatedRequest(account, exchange);
|
authenticatedRequest(account, exchange);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
|
if(SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED.equals(match.getEmptyRoleSemantic())) {
|
||||||
|
authenticatedRequest(account, exchange);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
for (String role : match.getRequiredRoles()) {
|
for (String role : match.getRequiredRoles()) {
|
||||||
if (account.getRoles().contains(role)) {
|
if (account.getRoles().contains(role)) {
|
||||||
authenticatedRequest(account, exchange);
|
authenticatedRequest(account, exchange);
|
||||||
|
@ -43,6 +66,8 @@ public class ConstraintAuthorizationHandler implements HttpHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (errorPage != null) {
|
if (errorPage != null) {
|
||||||
exchange.setRequestPath(errorPage);
|
exchange.setRequestPath(errorPage);
|
||||||
exchange.setRelativePath(errorPage);
|
exchange.setRelativePath(errorPage);
|
||||||
|
@ -61,20 +86,20 @@ public class ConstraintAuthorizationHandler implements HttpHandler {
|
||||||
IDToken idToken = account.getKeycloakSecurityContext().getToken();
|
IDToken idToken = account.getKeycloakSecurityContext().getToken();
|
||||||
if (idToken == null) return;
|
if (idToken == null) return;
|
||||||
if (idToken.getSubject() != null) {
|
if (idToken.getSubject() != null) {
|
||||||
exchange.getRequestHeaders().put(KEYCLOAK_SUBJECT, idToken.getSubject());
|
exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_SUBJECT), idToken.getSubject());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idToken.getPreferredUsername() != null) {
|
if (idToken.getPreferredUsername() != null) {
|
||||||
exchange.getRequestHeaders().put(KEYCLOAK_USERNAME, idToken.getPreferredUsername());
|
exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_USERNAME), idToken.getPreferredUsername());
|
||||||
}
|
}
|
||||||
if (idToken.getEmail() != null) {
|
if (idToken.getEmail() != null) {
|
||||||
exchange.getRequestHeaders().put(KEYCLOAK_EMAIL, idToken.getEmail());
|
exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_EMAIL), idToken.getEmail());
|
||||||
}
|
}
|
||||||
if (idToken.getName() != null) {
|
if (idToken.getName() != null) {
|
||||||
exchange.getRequestHeaders().put(KEYCLOAK_NAME, idToken.getName());
|
exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_NAME), idToken.getName());
|
||||||
}
|
}
|
||||||
if (sendAccessToken) {
|
if (sendAccessToken) {
|
||||||
exchange.getRequestHeaders().put(KEYCLOAK_ACCESS_TOKEN, account.getKeycloakSecurityContext().getTokenString());
|
exchange.getRequestHeaders().put(httpHeaderNames.get(KEYCLOAK_ACCESS_TOKEN), account.getKeycloakSecurityContext().getTokenString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next.handleRequest(exchange);
|
next.handleRequest(exchange);
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package org.keycloak.proxy;
|
package org.keycloak.proxy;
|
||||||
|
|
||||||
import io.undertow.security.handlers.AuthenticationConstraintHandler;
|
import io.undertow.security.api.AuthenticationMechanism;
|
||||||
import io.undertow.server.HttpHandler;
|
import io.undertow.server.HttpHandler;
|
||||||
import io.undertow.server.HttpServerExchange;
|
import io.undertow.server.HttpServerExchange;
|
||||||
import io.undertow.util.AttachmentKey;
|
import io.undertow.util.AttachmentKey;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -47,10 +48,42 @@ public class ConstraintMatcherHandler implements HttpHandler {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (match.getRequiredRoles().isEmpty()
|
||||||
|
&& match.getEmptyRoleSemantic() == SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED) {
|
||||||
|
|
||||||
|
boolean successfulAuthenticatedMethodFound = isSuccessfulAuthenticatedMethodFound(exchange);
|
||||||
|
|
||||||
|
if(successfulAuthenticatedMethodFound) {
|
||||||
|
//in case of authenticated we go for injecting headers
|
||||||
|
exchange.putAttachment(CONSTRAINT_KEY, match);
|
||||||
|
securedHandler.handleRequest(exchange);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
//in case of not authenticated we just show the resource
|
||||||
|
unsecuredHandler.handleRequest(exchange);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.debug("found constraint");
|
log.debug("found constraint");
|
||||||
exchange.getSecurityContext().setAuthenticationRequired();
|
exchange.getSecurityContext().setAuthenticationRequired();
|
||||||
exchange.putAttachment(CONSTRAINT_KEY, match);
|
exchange.putAttachment(CONSTRAINT_KEY, match);
|
||||||
securedHandler.handleRequest(exchange);
|
securedHandler.handleRequest(exchange);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSuccessfulAuthenticatedMethodFound(HttpServerExchange exchange) {
|
||||||
|
boolean successfulAuthenticatedMethodFound = false;
|
||||||
|
List<AuthenticationMechanism> authenticationMechanisms = exchange.getSecurityContext().getAuthenticationMechanisms();
|
||||||
|
|
||||||
|
for (AuthenticationMechanism authenticationMechanism : authenticationMechanisms) {
|
||||||
|
AuthenticationMechanism.AuthenticationMechanismOutcome authenticationMechanismOutcome =
|
||||||
|
authenticationMechanism.authenticate(exchange, exchange.getSecurityContext());
|
||||||
|
if(authenticationMechanismOutcome.equals(AuthenticationMechanism.AuthenticationMechanismOutcome.AUTHENTICATED)) {
|
||||||
|
successfulAuthenticatedMethodFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return successfulAuthenticatedMethodFound;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,7 @@ package org.keycloak.proxy;
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -41,6 +38,8 @@ public class ProxyConfig {
|
||||||
protected boolean sendAccessToken;
|
protected boolean sendAccessToken;
|
||||||
@JsonProperty("applications")
|
@JsonProperty("applications")
|
||||||
protected List<Application> applications = new LinkedList<Application>();
|
protected List<Application> applications = new LinkedList<Application>();
|
||||||
|
@JsonProperty("header-names")
|
||||||
|
private Map<String,String> headerNames = new HashMap<>();
|
||||||
|
|
||||||
public String getBindAddress() {
|
public String getBindAddress() {
|
||||||
return bindAddress;
|
return bindAddress;
|
||||||
|
@ -154,6 +153,14 @@ public class ProxyConfig {
|
||||||
this.sendAccessToken = sendAccessToken;
|
this.sendAccessToken = sendAccessToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHeaderNames(Map<String, String> headerNames) {
|
||||||
|
this.headerNames = headerNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getHeaderNames() {
|
||||||
|
return headerNames;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Application {
|
public static class Application {
|
||||||
@JsonProperty("base-path")
|
@JsonProperty("base-path")
|
||||||
protected String basePath;
|
protected String basePath;
|
||||||
|
@ -212,6 +219,8 @@ public class ProxyConfig {
|
||||||
protected boolean permit;
|
protected boolean permit;
|
||||||
@JsonProperty("authenticate")
|
@JsonProperty("authenticate")
|
||||||
protected boolean authenticate;
|
protected boolean authenticate;
|
||||||
|
@JsonProperty("permit-and-inject")
|
||||||
|
protected boolean permitAndInject;
|
||||||
|
|
||||||
public String getPattern() {
|
public String getPattern() {
|
||||||
return pattern;
|
return pattern;
|
||||||
|
@ -253,6 +262,14 @@ public class ProxyConfig {
|
||||||
this.authenticate = authenticate;
|
this.authenticate = authenticate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPermitAndInject() {
|
||||||
|
return permitAndInject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermitAndInject(boolean permitAndInject) {
|
||||||
|
this.permitAndInject = permitAndInject;
|
||||||
|
}
|
||||||
|
|
||||||
public Set<String> getMethods() {
|
public Set<String> getMethods() {
|
||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,7 @@ import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -76,6 +73,8 @@ public class ProxyServerBuilder {
|
||||||
protected HttpHandler proxyHandler;
|
protected HttpHandler proxyHandler;
|
||||||
protected boolean sendAccessToken;
|
protected boolean sendAccessToken;
|
||||||
|
|
||||||
|
protected Map<String, String> headerNameConfig;
|
||||||
|
|
||||||
public ProxyServerBuilder target(String uri) {
|
public ProxyServerBuilder target(String uri) {
|
||||||
SimpleProxyClientProvider provider = null;
|
SimpleProxyClientProvider provider = null;
|
||||||
try {
|
try {
|
||||||
|
@ -98,6 +97,12 @@ public class ProxyServerBuilder {
|
||||||
this.sendAccessToken = flag;
|
this.sendAccessToken = flag;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ProxyServerBuilder headerNameConfig(Map<String, String> headerNameConfig) {
|
||||||
|
this.headerNameConfig = headerNameConfig;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ApplicationBuilder application(AdapterConfig config) {
|
public ApplicationBuilder application(AdapterConfig config) {
|
||||||
return new ApplicationBuilder(config);
|
return new ApplicationBuilder(config);
|
||||||
}
|
}
|
||||||
|
@ -169,6 +174,11 @@ public class ProxyServerBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConstraintBuilder injectIfAuthenticated() {
|
||||||
|
semantic = SecurityInfo.EmptyRoleSemantic.PERMIT_AND_INJECT_IF_AUTHENTICATED;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ConstraintBuilder excludedMethods(Set<String> excludedMethods) {
|
public ConstraintBuilder excludedMethods(Set<String> excludedMethods) {
|
||||||
this.excludedMethods = excludedMethods;
|
this.excludedMethods = excludedMethods;
|
||||||
return this;
|
return this;
|
||||||
|
@ -222,7 +232,7 @@ public class ProxyServerBuilder {
|
||||||
errorPage = base + "/" + errorPage;
|
errorPage = base + "/" + errorPage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handler = new ConstraintAuthorizationHandler(handler, errorPage, sendAccessToken);
|
handler = new ConstraintAuthorizationHandler(handler, errorPage, sendAccessToken, headerNameConfig);
|
||||||
handler = new ProxyAuthenticationCallHandler(handler);
|
handler = new ProxyAuthenticationCallHandler(handler);
|
||||||
handler = new ConstraintMatcherHandler(matches, handler, toWrap, errorPage);
|
handler = new ConstraintMatcherHandler(matches, handler, toWrap, errorPage);
|
||||||
final List<AuthenticationMechanism> mechanisms = new LinkedList<AuthenticationMechanism>();
|
final List<AuthenticationMechanism> mechanisms = new LinkedList<AuthenticationMechanism>();
|
||||||
|
@ -373,6 +383,7 @@ public class ProxyServerBuilder {
|
||||||
if (constraint.isDeny()) constraintBuilder.deny();
|
if (constraint.isDeny()) constraintBuilder.deny();
|
||||||
if (constraint.isPermit()) constraintBuilder.permit();
|
if (constraint.isPermit()) constraintBuilder.permit();
|
||||||
if (constraint.isAuthenticate()) constraintBuilder.authenticate();
|
if (constraint.isAuthenticate()) constraintBuilder.authenticate();
|
||||||
|
if (constraint.isPermitAndInject()) constraintBuilder.injectIfAuthenticated();
|
||||||
constraintBuilder.add();
|
constraintBuilder.add();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,6 +394,7 @@ public class ProxyServerBuilder {
|
||||||
|
|
||||||
public static void initOptions(ProxyConfig config, ProxyServerBuilder builder) {
|
public static void initOptions(ProxyConfig config, ProxyServerBuilder builder) {
|
||||||
builder.sendAccessToken(config.isSendAccessToken());
|
builder.sendAccessToken(config.isSendAccessToken());
|
||||||
|
builder.headerNameConfig(config.getHeaderNames());
|
||||||
if (config.getBufferSize() != null) builder.setBufferSize(config.getBufferSize());
|
if (config.getBufferSize() != null) builder.setBufferSize(config.getBufferSize());
|
||||||
if (config.getBuffersPerRegion() != null) builder.setBuffersPerRegion(config.getBuffersPerRegion());
|
if (config.getBuffersPerRegion() != null) builder.setBuffersPerRegion(config.getBuffersPerRegion());
|
||||||
if (config.getIoThreads() != null) builder.setIoThreads(config.getIoThreads());
|
if (config.getIoThreads() != null) builder.setIoThreads(config.getIoThreads());
|
||||||
|
|
|
@ -46,8 +46,12 @@ public class SecurityInfo<T extends SecurityInfo> implements Cloneable {
|
||||||
/**
|
/**
|
||||||
* Mandate authentication but authorize access as no roles to check against.
|
* Mandate authentication but authorize access as no roles to check against.
|
||||||
*/
|
*/
|
||||||
AUTHENTICATE;
|
AUTHENTICATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permit access in any case, but provide authorization info only if authorized.
|
||||||
|
*/
|
||||||
|
PERMIT_AND_INJECT_IF_AUTHENTICATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
private volatile EmptyRoleSemantic emptyRoleSemantic = EmptyRoleSemantic.DENY;
|
private volatile EmptyRoleSemantic emptyRoleSemantic = EmptyRoleSemantic.DENY;
|
||||||
|
|
Loading…
Reference in a new issue