com.kumuluz.ee.security.KeycloakSecurityConfigurationUtilImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.kumuluz.ee.security.KeycloakSecurityConfigurationUtilImpl.java

Source

/*
 *  Copyright (c) 2014-2017 Kumuluz and/or its affiliates
 *  and other contributors as indicated by the @author tags and
 *  the contributor list.
 *
 *  Licensed under the MIT License (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  https://opensource.org/licenses/MIT
 *
 *  The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, express or
 *  implied, including but not limited to the warranties of merchantability,
 *  fitness for a particular purpose and noninfringement. in no event shall the
 *  authors or copyright holders be liable for any claim, damages or other
 *  liability, whether in an action of contract, tort or otherwise, arising from,
 *  out of or in connection with the software or the use or other dealings in the
 *  software. See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.kumuluz.ee.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.kumuluz.ee.configuration.utils.ConfigurationUtil;
import com.kumuluz.ee.security.annotations.Keycloak;
import com.kumuluz.ee.security.models.SecurityConstraint;
import com.kumuluz.ee.security.utils.SecurityConfigurationUtil;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.webapp.WebAppContext;
import org.keycloak.adapters.jetty.KeycloakJettyAuthenticator;

import javax.enterprise.context.ApplicationScoped;
import java.io.IOException;
import java.util.*;

/**
 * @author Benjamin Kastelic
 */
@ApplicationScoped
public class KeycloakSecurityConfigurationUtilImpl implements SecurityConfigurationUtil {

    private Map<String, String> roleMappings;

    public Map<String, String> getRoleMappings() {
        return roleMappings;
    }

    public void setRoleMappings(Map<String, String> roleMappings) {
        this.roleMappings = roleMappings;
    }

    @Override
    public void configureSecurity(Class targetClass, Object context, List<String> declaredRoles,
            List<SecurityConstraint> constraints, Map<String, String> roleMappings) {
        String keycloakConfig = getKeycloakConfig(targetClass);

        WebAppContext.Context webAppContext = null;
        WebAppContext webAppContextHandler = null;

        if (context instanceof WebAppContext.Context) {
            webAppContext = (WebAppContext.Context) context;
        }

        if (webAppContext != null && webAppContext.getContextHandler() instanceof WebAppContext) {
            webAppContextHandler = (WebAppContext) webAppContext.getContextHandler();
        }

        if (webAppContextHandler != null) {
            ConstraintSecurityHandler constraintSecurityHandler = new ConstraintSecurityHandler();
            constraintSecurityHandler.setAuthenticator(new KeycloakJettyAuthenticator());

            Set<String> roles = new HashSet<>(declaredRoles);
            constraintSecurityHandler.setRoles(roles);
            List<ConstraintMapping> constraintMappings = toConstraintMappings(constraints);
            constraintSecurityHandler.setConstraintMappings(constraintMappings);

            webAppContextHandler.setSecurityHandler(constraintSecurityHandler);
        }

        if (webAppContext != null) {
            webAppContext.setInitParameter("org.keycloak.json.adapterConfig", keycloakConfig);
        }

        this.roleMappings = roleMappings;
    }

    private String getKeycloakConfig(Class targetClass) {
        ObjectMapper mapper = new ObjectMapper();

        ConfigurationUtil configurationUtil = ConfigurationUtil.getInstance();

        Keycloak keycloakAnnotation = (Keycloak) targetClass.getAnnotation(Keycloak.class);

        String jsonString;
        ObjectNode json;
        String authServerUrl;
        String sslRequired;

        jsonString = configurationUtil.get("kumuluzee.security.keycloak.json").orElse("{}");
        json = toJSONObject(jsonString);

        if (jsonString.isEmpty() && keycloakAnnotation != null) {
            jsonString = keycloakAnnotation.json();
            json = toJSONObject(jsonString);

            authServerUrl = keycloakAnnotation.authServerUrl();
            sslRequired = keycloakAnnotation.sslRequired();

            if (!authServerUrl.isEmpty()) {
                json.put("auth-server-url", authServerUrl);
            }

            if (!sslRequired.isEmpty()) {
                json.put("ssl-required", sslRequired);
            }
        }

        return json.toString();
    }

    private ObjectNode toJSONObject(String jsonString) {
        ObjectMapper mapper = new ObjectMapper();

        ObjectNode json;
        try {
            json = mapper.readValue(jsonString, ObjectNode.class);
        } catch (IOException e) {
            json = mapper.createObjectNode();
        }
        return json;
    }

    private List<ConstraintMapping> toConstraintMappings(List<SecurityConstraint> constraints) {
        List<ConstraintMapping> constraintMappings = new ArrayList<>();
        constraints.forEach(constraint -> constraintMappings.add(toConstraintMapping(constraint)));
        return constraintMappings;
    }

    private ConstraintMapping toConstraintMapping(SecurityConstraint securityConstraint) {
        Constraint constraint = new Constraint();
        if (securityConstraint.getAnyRole()) {
            constraint.setRoles(new String[] { "*" });
        } else {
            constraint.setRoles(
                    securityConstraint.getRoles().toArray(new String[securityConstraint.getRoles().size()]));
        }
        constraint.setAuthenticate(true);

        ConstraintMapping constraintMapping = new ConstraintMapping();
        constraintMapping.setMethod(securityConstraint.getMethod());
        constraintMapping.setPathSpec(securityConstraint.getPath());
        constraintMapping.setConstraint(constraint);

        return constraintMapping;
    }
}