fi.vm.kapa.identification.proxy.service.MetadataService.java Source code

Java tutorial

Introduction

Here is the source code for fi.vm.kapa.identification.proxy.service.MetadataService.java

Source

/**
 * The MIT License
 * Copyright (c) 2015 Population Register Centre
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * 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.
 */
package fi.vm.kapa.identification.proxy.service;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import fi.vm.kapa.identification.dto.AuthenticationProviderDTO;
import fi.vm.kapa.identification.dto.MetadataDTO;
import fi.vm.kapa.identification.type.AuthMethod;
import fi.vm.kapa.identification.type.ProviderType;
import fi.vm.kapa.identification.type.SessionProfile;

import org.apache.commons.lang.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.inject.Singleton;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
@Singleton
public class MetadataService {

    private static final Logger logger = LoggerFactory.getLogger(MetadataService.class);
    private static final int HTTP_OK = 200;

    @Value("${metadata.server.url}")
    private String metadataServerUrl;

    //cached service providers
    private Map<String, MetadataDTO> serviceProviderMetaDataCache = new HashMap<>();
    //cahced authentication providers
    private ApprovedAuthenticationProviders approvedAuthenticationProviders = new ApprovedAuthenticationProviders(
            metadataServerUrl);

    public SessionProfile getProfileByRelyingParty(String relyingParty) {
        if (serviceProviderMetaDataCache.containsKey(relyingParty)) {
            return serviceProviderMetaDataCache.get(relyingParty).getSessionProfile();
        }
        return null;
    }

    public List<AuthenticationProviderDTO> getAuthenticationProvidersByRelyingParty(String relyingParty) {
        if (serviceProviderMetaDataCache.containsKey(relyingParty)) {
            List<AuthenticationProviderDTO> result = serviceProviderMetaDataCache.get(relyingParty)
                    .getAuthenticationProviderDTOList();
            return result;
        }
        List<AuthenticationProviderDTO> emptyList = new ArrayList<AuthenticationProviderDTO>();
        return emptyList;
    }

    public String getLevelOfAssurance(String relyingParty) {
        if (serviceProviderMetaDataCache.containsKey(relyingParty)) {
            return serviceProviderMetaDataCache.get(relyingParty).getLevelOfAssurance();
        }
        return null;
    }

    public AuthMethod getAuthenticationMethodByAuthContextUrl(String authContextUrl) {
        if (approvedAuthenticationProviders.getAuthMethodByAuthProviderAuthContextUrl(authContextUrl) != null) {
            return AuthMethod.valueOf(
                    approvedAuthenticationProviders.getAuthMethodByAuthProviderAuthContextUrl(authContextUrl));
        }
        return null;
    }

    public String getAuthProviderEntityIdByAuthContextUrl(String authContextUrl) {
        return approvedAuthenticationProviders
                .getDbEntityIdAuthContextUrlByAuthProviderAuthContextUrl(authContextUrl);
    }

    public String getAuthenticationMethodsByRelyingParty(String relyingParty) {
        if (serviceProviderMetaDataCache.containsKey(relyingParty)) {
            if (serviceProviderMetaDataCache.get(relyingParty).getAttributeLevelOfAssurance() != null) {
                return serviceProviderMetaDataCache.get(relyingParty).getAttributeLevelOfAssurance();
            }
        }
        return null;
    }

    public boolean isVtjVerificationRequired(String relyingParty) throws Exception {
        if (StringUtils.isNotBlank(relyingParty) && serviceProviderMetaDataCache.containsKey(relyingParty)) {
            return serviceProviderMetaDataCache.get(relyingParty).isVtjVerificationRequired();
        } else {
            logger.error("Error finding requested relying party: " + relyingParty
                    + " for vtj verification requirement check");
            throw new Exception("Error finding requested relying party: " + relyingParty
                    + " for vtj verification requirement check");
        }
    }

    public void updateMetadataCache() {
        try {
            approvedAuthenticationProviders = new ApprovedAuthenticationProviders(metadataServerUrl);
            CloseableHttpClient httpClient = HttpClients.createDefault();
            final String serviceProviderMetadataReqUrl = metadataServerUrl + "?type="
                    + ProviderType.SERVICE_PROVIDER.toString();
            logger.debug("url to metadata server: {}", serviceProviderMetadataReqUrl);
            HttpGet getMethod = new HttpGet(serviceProviderMetadataReqUrl);
            HttpContext context = HttpClientContext.create();
            CloseableHttpResponse response = httpClient.execute(getMethod, context);

            //            HttpEntity entity = response.getEntity();
            //            String content = EntityUtils.toString(entity);
            //            logger.debug("HTTP Entity:" + content);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HTTP_OK) {
                Gson gson = new Gson();
                List<MetadataDTO> metadata = gson.fromJson(EntityUtils.toString(response.getEntity()),
                        new TypeToken<List<MetadataDTO>>() {
                        }.getType());
                response.close();
                if (!CollectionUtils.isEmpty(metadata)) {
                    logger.debug("Clearing previous metadata cache, content size {}",
                            serviceProviderMetaDataCache.size());
                    Map<String, MetadataDTO> newMetaDataCache = new HashMap<>();
                    metadata.forEach(data -> {
                        MetadataDTO toCache = new MetadataDTO();
                        toCache.setEntityId(data.getEntityId());
                        logger.debug("data.getDbEntityIdAuthContextUrlByAuthProviderAuthContextUrl(): "
                                + data.getEntityId());
                        toCache.setDnsName(data.getDnsName());
                        toCache.setLevelOfAssurance(data.getLevelOfAssurance());
                        toCache.setAttributeLevelOfAssurance(data.getAttributeLevelOfAssurance());
                        toCache.setAcsAddress(data.getAcsAddress());
                        toCache.setProviderType(data.getProviderType());
                        toCache.setSessionProfile(data.getSessionProfile());
                        toCache.setVtjVerificationRequired(data.isVtjVerificationRequired());
                        logger.debug("data.getAuthenticationMethods(): " + data.getAttributeLevelOfAssurance());
                        toCache.setAuthenticationProviderDTOList(
                                approvedAuthenticationProviders.getByName(data.getAttributeLevelOfAssurance()));
                        logger.debug("--adding metadata - ent ID: " + data.getEntityId() + ", dns: "
                                + data.getDnsName() + ", permitted auth methods: "
                                + data.getAttributeLevelOfAssurance() + ", type: " + data.getProviderType()
                                + ", profile: " + data.getSessionProfile());
                        newMetaDataCache.put(data.getEntityId(), toCache);
                    });
                    serviceProviderMetaDataCache = newMetaDataCache; // when done replace old with new
                }
            } else {
                logger.warn("Metadata server responded with HTTP {}", statusCode);
                response.close();
            }
        } catch (Exception e) {
            logger.error("Error updating proxy metadata", e);
        }
    }

    public static class ApprovedAuthenticationProviders {

        private List<AuthenticationProviderDTO> allProviders;

        public ApprovedAuthenticationProviders(final String _metadataServerUrl) {
            /**
             * this class encloses all known auth providers for now - until a better way is found
             */
            allProviders = new ArrayList<AuthenticationProviderDTO>();
            final String authenticationProviderMetadataReqUrl = _metadataServerUrl + "?type="
                    + ProviderType.AUTHENTICATION_PROVIDER.toString();
            logger.debug("url to metadata server - authenticationProviders: {}",
                    authenticationProviderMetadataReqUrl);
            try {
                CloseableHttpClient httpClient = HttpClients.createDefault();
                logger.debug("url to metadata server: {}", authenticationProviderMetadataReqUrl);
                HttpGet getMethod = new HttpGet(authenticationProviderMetadataReqUrl);
                HttpContext context = HttpClientContext.create();
                CloseableHttpResponse response = httpClient.execute(getMethod, context);
                int statusCode = response.getStatusLine().getStatusCode();
                if (statusCode == HTTP_OK) {
                    Gson gson = new Gson();
                    List<MetadataDTO> metadata = gson.fromJson(EntityUtils.toString(response.getEntity()),
                            new TypeToken<List<MetadataDTO>>() {
                            }.getType());
                    response.close();
                    metadata.forEach(data -> {
                        allProviders.add(new AuthenticationProviderDTO() {
                            {
                                setName(data.getName() + "");
                                setDomainName(data.getDnsName());
                                setAuthenticationMethod(data.getAttributeLevelOfAssurance());
                                setAuthProviderAuthContextUrl(data.getAcsAddress());
                                setDbEntityIdAuthContextUrl(data.getEntityId());
                            }
                        });
                    });
                } else {
                    logger.warn("Metadata server responded with HTTP {}", statusCode);
                    response.close();
                }
            } catch (Exception e) {
                logger.error("Error updating proxy ApprovedAuthenticationProviders", e);
            }
        }

        public List<AuthenticationProviderDTO> getByName(final String authMethods) {
            if (null != authMethods) {
                Set<String> permittedMethodSet = new HashSet<String>(Arrays.asList(authMethods.split(";")));
                List<AuthenticationProviderDTO> filtered = new ArrayList<AuthenticationProviderDTO>();
                for (AuthenticationProviderDTO authProvider : allProviders) {
                    if (permittedMethodSet.contains(authProvider.getAuthenticationMethod())) {
                        logger.debug("*** authProvider {}",
                                authProvider + " -- type: " + authProvider.getAuthenticationMethod());
                        filtered.add(authProvider);
                    }
                }
                return filtered;
            }
            return null;
        }

        public String getAuthMethodByAuthProviderAuthContextUrl(final String authContextUrl) {
            for (AuthenticationProviderDTO authProvider : allProviders) {
                if (authProvider.getAuthProviderAuthContextUrl().equals(authContextUrl)) {
                    return authProvider.getAuthenticationMethod();
                }
            }
            return null;
        }

        public String getDbEntityIdAuthContextUrlByAuthProviderAuthContextUrl(final String authContextUrl) {
            for (AuthenticationProviderDTO authProvider : allProviders) {
                if (authProvider.getAuthProviderAuthContextUrl().equals(authContextUrl)) {
                    return authProvider.getDbEntityIdAuthContextUrl();
                }
            }
            return null;
        }
    }
}