Search in sources :

Example 1 with Request

use of org.keycloak.adapters.spi.HttpFacade.Request in project keycloak by keycloak.

the class AbstractPolicyEnforcer method authorize.

public AuthorizationContext authorize(OIDCHttpFacade httpFacade) {
    EnforcementMode enforcementMode = getEnforcerConfig().getEnforcementMode();
    KeycloakSecurityContext securityContext = httpFacade.getSecurityContext();
    if (EnforcementMode.DISABLED.equals(enforcementMode)) {
        if (securityContext == null) {
            httpFacade.getResponse().sendError(401, "Invalid bearer");
        }
        return createEmptyAuthorizationContext(true);
    }
    Request request = httpFacade.getRequest();
    PathConfig pathConfig = getPathConfig(request);
    if (securityContext == null) {
        if (!isDefaultAccessDeniedUri(request)) {
            if (pathConfig != null) {
                if (EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) {
                    return createEmptyAuthorizationContext(true);
                } else {
                    challenge(pathConfig, getRequiredScopes(pathConfig, request), httpFacade);
                }
            } else {
                handleAccessDenied(httpFacade);
            }
        }
        return createEmptyAuthorizationContext(false);
    }
    AccessToken accessToken = securityContext.getToken();
    if (accessToken != null) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debugf("Checking permissions for path [%s] with config [%s].", request.getURI(), pathConfig);
        }
        if (pathConfig == null) {
            if (EnforcementMode.PERMISSIVE.equals(enforcementMode)) {
                return createAuthorizationContext(accessToken, null);
            }
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debugf("Could not find a configuration for path [%s]", getPath(request));
            }
            if (isDefaultAccessDeniedUri(request)) {
                return createAuthorizationContext(accessToken, null);
            }
            handleAccessDenied(httpFacade);
            return createEmptyAuthorizationContext(false);
        }
        if (EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) {
            return createAuthorizationContext(accessToken, pathConfig);
        }
        MethodConfig methodConfig = getRequiredScopes(pathConfig, request);
        Map<String, List<String>> claims = resolveClaims(pathConfig, httpFacade);
        if (isAuthorized(pathConfig, methodConfig, accessToken, httpFacade, claims)) {
            try {
                return createAuthorizationContext(accessToken, pathConfig);
            } catch (Exception e) {
                throw new RuntimeException("Error processing path [" + pathConfig.getPath() + "].", e);
            }
        }
        if (methodConfig != null && ScopeEnforcementMode.DISABLED.equals(methodConfig.getScopesEnforcementMode())) {
            return createEmptyAuthorizationContext(true);
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debugf("Sending challenge to the client. Path [%s]", pathConfig);
        }
        if (!challenge(pathConfig, methodConfig, httpFacade)) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debugf("Challenge not sent, sending default forbidden response. Path [%s]", pathConfig);
            }
            handleAccessDenied(httpFacade);
        }
    }
    return createEmptyAuthorizationContext(false);
}
Also used : MethodConfig(org.keycloak.representations.adapters.config.PolicyEnforcerConfig.MethodConfig) PathConfig(org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig) KeycloakSecurityContext(org.keycloak.KeycloakSecurityContext) AccessToken(org.keycloak.representations.AccessToken) ScopeEnforcementMode(org.keycloak.representations.adapters.config.PolicyEnforcerConfig.ScopeEnforcementMode) EnforcementMode(org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode) Request(org.keycloak.adapters.spi.HttpFacade.Request) ArrayList(java.util.ArrayList) List(java.util.List)

Example 2 with Request

use of org.keycloak.adapters.spi.HttpFacade.Request in project keycloak by keycloak.

the class AbstractPolicyEnforcer method isAuthorized.

protected boolean isAuthorized(PathConfig actualPathConfig, MethodConfig methodConfig, AccessToken accessToken, OIDCHttpFacade httpFacade, Map<String, List<String>> claims) {
    Request request = httpFacade.getRequest();
    if (isDefaultAccessDeniedUri(request)) {
        return true;
    }
    Authorization authorization = accessToken.getAuthorization();
    if (authorization == null) {
        return false;
    }
    boolean hasPermission = false;
    Collection<Permission> grantedPermissions = authorization.getPermissions();
    for (Permission permission : grantedPermissions) {
        if (permission.getResourceId() != null) {
            if (isResourcePermission(actualPathConfig, permission)) {
                hasPermission = true;
                if (actualPathConfig.isInstance() && !matchResourcePermission(actualPathConfig, permission)) {
                    continue;
                }
                if (hasResourceScopePermission(methodConfig, permission)) {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debugf("Authorization GRANTED for path [%s]. Permissions [%s].", actualPathConfig, grantedPermissions);
                    }
                    if (HTTP_METHOD_DELETE.equalsIgnoreCase(request.getMethod()) && actualPathConfig.isInstance()) {
                        policyEnforcer.getPathMatcher().removeFromCache(getPath(request));
                    }
                    return hasValidClaims(permission, claims);
                }
            }
        } else {
            if (hasResourceScopePermission(methodConfig, permission)) {
                hasPermission = true;
                return true;
            }
        }
    }
    if (!hasPermission && EnforcementMode.PERMISSIVE.equals(actualPathConfig.getEnforcementMode())) {
        return true;
    }
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debugf("Authorization FAILED for path [%s]. Not enough permissions [%s].", actualPathConfig, grantedPermissions);
    }
    return false;
}
Also used : Authorization(org.keycloak.representations.AccessToken.Authorization) Request(org.keycloak.adapters.spi.HttpFacade.Request) Permission(org.keycloak.representations.idm.authorization.Permission)

Example 3 with Request

use of org.keycloak.adapters.spi.HttpFacade.Request in project keycloak by keycloak.

the class RequestPlaceHolderResolver method resolve.

@Override
public List<String> resolve(String placeHolder, HttpFacade httpFacade) {
    String source = placeHolder.substring(placeHolder.indexOf('.') + 1);
    Request request = httpFacade.getRequest();
    if (source.startsWith("parameter")) {
        String parameterName = getParameter(source, "Could not obtain parameter name from placeholder [" + source + "]");
        String parameterValue = request.getQueryParamValue(parameterName);
        if (parameterValue == null) {
            parameterValue = request.getFirstParam(parameterName);
        }
        if (parameterValue != null) {
            return Arrays.asList(parameterValue);
        }
    } else if (source.startsWith("header")) {
        String headerName = getParameter(source, "Could not obtain header name from placeholder [" + source + "]");
        List<String> headerValue = request.getHeaders(headerName);
        if (headerValue != null) {
            return headerValue;
        }
    } else if (source.startsWith("cookie")) {
        String cookieName = getParameter(source, "Could not obtain cookie name from placeholder [" + source + "]");
        Cookie cookieValue = request.getCookie(cookieName);
        if (cookieValue != null) {
            return Arrays.asList(cookieValue.getValue());
        }
    } else if (source.startsWith("remoteAddr")) {
        String value = request.getRemoteAddr();
        if (value != null) {
            return Arrays.asList(value);
        }
    } else if (source.startsWith("method")) {
        String value = request.getMethod();
        if (value != null) {
            return Arrays.asList(value);
        }
    } else if (source.startsWith("uri")) {
        String value = request.getURI();
        if (value != null) {
            return Arrays.asList(value);
        }
    } else if (source.startsWith("relativePath")) {
        String value = request.getRelativePath();
        if (value != null) {
            return Arrays.asList(value);
        }
    } else if (source.startsWith("secure")) {
        return Arrays.asList(String.valueOf(request.isSecure()));
    } else if (source.startsWith("body")) {
        String contentType = request.getHeader("Content-Type");
        if (contentType == null) {
            contentType = "";
        } else if (contentType.indexOf(';') != -1) {
            contentType = contentType.substring(0, contentType.indexOf(';')).trim();
        }
        InputStream body = request.getInputStream(true);
        try {
            if (body == null || body.available() == 0) {
                return Collections.emptyList();
            }
        } catch (IOException cause) {
            throw new RuntimeException("Failed to check available bytes in request input stream", cause);
        }
        if (body.markSupported()) {
            body.mark(0);
        }
        List<String> values = new ArrayList<>();
        try {
            switch(contentType) {
                case "application/json":
                    try {
                        JsonNode jsonNode = JsonSerialization.mapper.readTree(new BufferedInputStream(body) {

                            @Override
                            public void close() {
                            // we can't close the stream because it may be used later by the application
                            }
                        });
                        String path = getParameter(source, null);
                        if (path == null) {
                            values.addAll(JsonUtils.getValues(jsonNode));
                        } else {
                            values.addAll(JsonUtils.getValues(jsonNode, path));
                        }
                    } catch (IOException cause) {
                        throw new RuntimeException("Could not extract claim from request JSON body", cause);
                    }
                    break;
                default:
                    StringBuilder value = new StringBuilder();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(body));
                    try {
                        int ch;
                        while ((ch = reader.read()) != -1) {
                            value.append((char) ch);
                        }
                    } catch (IOException cause) {
                        throw new RuntimeException("Could not extract claim from request body", cause);
                    }
                    values.add(value.toString());
            }
        } finally {
            if (body.markSupported()) {
                try {
                    body.reset();
                } catch (IOException cause) {
                    throw new RuntimeException("Failed to reset request input stream", cause);
                }
            }
        }
        return values;
    }
    return Collections.emptyList();
}
Also used : Cookie(org.keycloak.adapters.spi.HttpFacade.Cookie) InputStreamReader(java.io.InputStreamReader) BufferedInputStream(java.io.BufferedInputStream) InputStream(java.io.InputStream) Request(org.keycloak.adapters.spi.HttpFacade.Request) ArrayList(java.util.ArrayList) JsonNode(com.fasterxml.jackson.databind.JsonNode) IOException(java.io.IOException) BufferedInputStream(java.io.BufferedInputStream) BufferedReader(java.io.BufferedReader) ArrayList(java.util.ArrayList) List(java.util.List)

Example 4 with Request

use of org.keycloak.adapters.spi.HttpFacade.Request in project shinyproxy by openanalytics.

the class KeycloakAuthenticationBackend method adapterDeploymentContext.

@Bean
@ConditionalOnProperty(name = "shiny.proxy.authentication", havingValue = "keycloak")
protected AdapterDeploymentContext adapterDeploymentContext() throws Exception {
    AdapterConfig cfg = new AdapterConfig();
    cfg.setRealm(environment.getProperty("shiny.proxy.keycloak.realm"));
    cfg.setAuthServerUrl(environment.getProperty("shiny.proxy.keycloak.auth-server-url"));
    cfg.setResource(environment.getProperty("shiny.proxy.keycloak.resource"));
    Map<String, Object> credentials = new HashMap<>();
    credentials.put("secret", environment.getProperty("shiny.proxy.keycloak.credentials-secret"));
    cfg.setCredentials(credentials);
    KeycloakDeployment dep = KeycloakDeploymentBuilder.build(cfg);
    AdapterDeploymentContextFactoryBean factoryBean = new AdapterDeploymentContextFactoryBean(new KeycloakConfigResolver() {

        @Override
        public KeycloakDeployment resolve(Request facade) {
            return dep;
        }
    });
    factoryBean.afterPropertiesSet();
    return factoryBean.getObject();
}
Also used : HashMap(java.util.HashMap) KeycloakConfigResolver(org.keycloak.adapters.KeycloakConfigResolver) AdapterConfig(org.keycloak.representations.adapters.config.AdapterConfig) KeycloakDeployment(org.keycloak.adapters.KeycloakDeployment) Request(org.keycloak.adapters.spi.HttpFacade.Request) AdapterDeploymentContextFactoryBean(org.keycloak.adapters.springsecurity.AdapterDeploymentContextFactoryBean) AdapterDeploymentContextFactoryBean(org.keycloak.adapters.springsecurity.AdapterDeploymentContextFactoryBean) Bean(org.springframework.context.annotation.Bean) ConditionalOnProperty(org.springframework.boot.autoconfigure.condition.ConditionalOnProperty)

Example 5 with Request

use of org.keycloak.adapters.spi.HttpFacade.Request in project keycloak by keycloak.

the class ClaimInformationPointProviderTest method createHttpRequest.

private Request createHttpRequest(Map<String, List<String>> headers, InputStream requestBody) {
    Map<String, List<String>> queryParameter = new HashMap<>();
    queryParameter.put("a", Arrays.asList("parameter-a"));
    headers.put("b", Arrays.asList("header-b"));
    Map<String, Cookie> cookies = new HashMap<>();
    cookies.put("c", new Cookie("c", "cookie-c", 1, "localhost", "/"));
    return new Request() {

        private InputStream inputStream;

        @Override
        public String getMethod() {
            return "GET";
        }

        @Override
        public String getURI() {
            return "/app/request-uri";
        }

        @Override
        public String getRelativePath() {
            return "/request-relative-path";
        }

        @Override
        public boolean isSecure() {
            return true;
        }

        @Override
        public String getFirstParam(String param) {
            List<String> values = queryParameter.getOrDefault(param, Collections.emptyList());
            if (!values.isEmpty()) {
                return values.get(0);
            }
            return null;
        }

        @Override
        public String getQueryParamValue(String param) {
            return getFirstParam(param);
        }

        @Override
        public Cookie getCookie(String cookieName) {
            return cookies.get(cookieName);
        }

        @Override
        public String getHeader(String name) {
            List<String> headers = getHeaders(name);
            if (!headers.isEmpty()) {
                return headers.get(0);
            }
            return null;
        }

        @Override
        public List<String> getHeaders(String name) {
            return headers.getOrDefault(name, Collections.emptyList());
        }

        @Override
        public InputStream getInputStream() {
            return getInputStream(false);
        }

        @Override
        public InputStream getInputStream(boolean buffer) {
            if (requestBody == null) {
                return new ByteArrayInputStream(new byte[] {});
            }
            if (inputStream != null) {
                return inputStream;
            }
            if (buffer) {
                return inputStream = new BufferedInputStream(requestBody);
            }
            return requestBody;
        }

        @Override
        public String getRemoteAddr() {
            return "user-remote-addr";
        }

        @Override
        public void setError(AuthenticationError error) {
        }

        @Override
        public void setError(LogoutError error) {
        }
    };
}
Also used : Cookie(org.keycloak.adapters.spi.HttpFacade.Cookie) AuthenticationError(org.keycloak.adapters.spi.AuthenticationError) HashMap(java.util.HashMap) BufferedInputStream(java.io.BufferedInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) Request(org.keycloak.adapters.spi.HttpFacade.Request) LogoutError(org.keycloak.adapters.spi.LogoutError) ByteArrayInputStream(java.io.ByteArrayInputStream) BufferedInputStream(java.io.BufferedInputStream) List(java.util.List)

Aggregations

Request (org.keycloak.adapters.spi.HttpFacade.Request)6 List (java.util.List)3 BufferedInputStream (java.io.BufferedInputStream)2 InputStream (java.io.InputStream)2 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 KeycloakSecurityContext (org.keycloak.KeycloakSecurityContext)2 Cookie (org.keycloak.adapters.spi.HttpFacade.Cookie)2 AccessToken (org.keycloak.representations.AccessToken)2 JsonNode (com.fasterxml.jackson.databind.JsonNode)1 BufferedReader (java.io.BufferedReader)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 IOException (java.io.IOException)1 InputStreamReader (java.io.InputStreamReader)1 X509Certificate (javax.security.cert.X509Certificate)1 KeycloakConfigResolver (org.keycloak.adapters.KeycloakConfigResolver)1 KeycloakDeployment (org.keycloak.adapters.KeycloakDeployment)1 OIDCHttpFacade (org.keycloak.adapters.OIDCHttpFacade)1 AuthenticationError (org.keycloak.adapters.spi.AuthenticationError)1 LogoutError (org.keycloak.adapters.spi.LogoutError)1