Java tutorial
/* * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.carbon.apimgt.handlers; import com.google.gson.Gson; import org.apache.axis2.context.MessageContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.synapse.core.axis2.Axis2MessageContext; import org.apache.synapse.rest.AbstractHandler; import org.wso2.carbon.apimgt.handlers.beans.Certificate; import org.wso2.carbon.apimgt.handlers.beans.ValidationResponce; import org.wso2.carbon.apimgt.handlers.config.IOTServerConfiguration; import org.wso2.carbon.apimgt.handlers.invoker.RESTInvoker; import org.wso2.carbon.apimgt.handlers.invoker.RESTResponse; import org.wso2.carbon.apimgt.handlers.utils.AuthConstants; import org.wso2.carbon.apimgt.handlers.utils.Utils; import org.wso2.carbon.certificate.mgt.core.impl.CertificateGenerator; import org.wso2.carbon.context.PrivilegedCarbonContext; import javax.security.cert.CertificateEncodingException; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; /** * Synapse gateway handler for API authentication. */ public class AuthenticationHandler extends AbstractHandler { private static final Log log = LogFactory.getLog(AuthenticationHandler.class); private RESTInvoker restInvoker; private static final String X_JWT_ASSERTION = "X-JWT-Assertion"; private static final String JWTTOKEN = "JWTToken"; private static final String AUTHORIZATION = "Authorization"; private static final String BEARER = "Bearer "; private static final String CONTENT_TYPE = "Content-Type"; private IOTServerConfiguration iotServerConfiguration; /** * Setting up configurations at the constructor */ public AuthenticationHandler() { log.info("Engaging API Security Handler.........."); restInvoker = new RESTInvoker(); this.iotServerConfiguration = Utils.initConfig(); } /** * Handling the message and checking the security. * * @param messageContext Request message context. * @return Boolean value of the result of the processing the request. */ @Override public boolean handleRequest(org.apache.synapse.MessageContext messageContext) { org.apache.axis2.context.MessageContext axisMC = ((Axis2MessageContext) messageContext) .getAxis2MessageContext(); String ctxPath = messageContext.getTo().getAddress().trim(); if (log.isDebugEnabled()) { log.debug("Authentication handler invoked by: " + ctxPath); } Map<String, String> headers = (Map<String, String>) axisMC.getProperty(MessageContext.TRANSPORT_HEADERS); try { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); RESTResponse response = null; if (headers.containsKey(AuthConstants.MDM_SIGNATURE)) { String mdmSignature = headers.get(AuthConstants.MDM_SIGNATURE); if (log.isDebugEnabled()) { log.debug("Verify Cert:\n" + mdmSignature); } String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim()); if (deviceType == null) { return false; } URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType); Map<String, String> certVerifyHeaders = this.setHeaders(this.restInvoker); Certificate certificate = new Certificate(); certificate.setPem(mdmSignature); certificate.setTenantId(tenantId); certificate.setSerial(""); Gson gson = new Gson(); String certVerifyContent = gson.toJson(certificate); response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, certVerifyContent); String str = response.getContent(); if (log.isDebugEnabled()) { log.debug("Verify response:" + response.getContent()); log.debug("Response String : " + str); } if (response.getHttpStatus() == 200 && str.contains(JWTTOKEN)) { ValidationResponce validationResponce = gson.fromJson(str, ValidationResponce.class); headers.put(X_JWT_ASSERTION, validationResponce.getJWTToken()); } else { return false; } } else if (headers.containsKey(AuthConstants.PROXY_MUTUAL_AUTH_HEADER)) { String subjectDN = headers.get(AuthConstants.PROXY_MUTUAL_AUTH_HEADER); if (log.isDebugEnabled()) { log.debug("Verify subject DN: " + subjectDN); } String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim()); URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType); Map<String, String> certVerifyHeaders = this.setHeaders(this.restInvoker); Certificate certificate = new Certificate(); certificate.setPem(subjectDN); certificate.setTenantId(tenantId); certificate.setSerial(AuthConstants.PROXY_MUTUAL_AUTH_HEADER); Gson gson = new Gson(); String certVerifyContent = gson.toJson(certificate); response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, certVerifyContent); if (log.isDebugEnabled()) { log.debug("Verify response:" + response.getContent()); } } else if (headers.containsKey(AuthConstants.MUTUAL_AUTH_HEADER)) { javax.security.cert.X509Certificate[] certs = (javax.security.cert.X509Certificate[]) axisMC .getProperty(AuthConstants.CLIENT_CERTIFICATE); CertificateFactory cf = CertificateFactory.getInstance("X.509"); ByteArrayInputStream bais = new ByteArrayInputStream(certs[0].getEncoded()); X509Certificate x509 = (X509Certificate) cf.generateCertificate(bais); bais.close(); if (x509 != null) { headers.put(AuthConstants.PROXY_MUTUAL_AUTH_HEADER, CertificateGenerator.getCommonName(x509)); return true; } } else if (headers.containsKey(AuthConstants.ENCODED_PEM)) { String encodedPem = headers.get(AuthConstants.ENCODED_PEM); if (log.isDebugEnabled()) { log.debug("Verify Cert:\n" + encodedPem); } String deviceType = this.getDeviceType(messageContext.getTo().getAddress().trim()); URI certVerifyUrl = new URI(iotServerConfiguration.getVerificationEndpoint() + deviceType); Map<String, String> certVerifyHeaders = this.setHeaders(this.restInvoker); Certificate certificate = new Certificate(); certificate.setPem(encodedPem); certificate.setTenantId(tenantId); certificate.setSerial(""); Gson gson = new Gson(); String certVerifyContent = gson.toJson(certificate); response = restInvoker.invokePOST(certVerifyUrl, certVerifyHeaders, certVerifyContent); if (log.isDebugEnabled()) { log.debug("Verify response:" + response.getContent()); } } else { log.warn("Unauthorized request for api: " + ctxPath); return false; } if (response != null && !response.getContent().contains("invalid")) { return true; } log.warn("Unauthorized request for api: " + ctxPath); return false; } catch (IOException e) { log.error("Error while processing certificate.", e); return false; } catch (URISyntaxException e) { log.error("Error while processing certificate.", e); return false; } catch (APIMCertificateMGTException e) { log.error("Error while processing certificate.", e); return false; } catch (CertificateException e) { log.error("Certificate issue occurred when generating converting PEM to x509Certificate", e); return false; } catch (CertificateEncodingException e) { log.error("Error while attempting to encode certificate.", e); return false; } } @Override public boolean handleResponse(org.apache.synapse.MessageContext messageContext) { return true; } private String getDeviceType(String url) { StringTokenizer parts = new StringTokenizer(url, "/"); while (parts.hasMoreElements()) { if (parts.nextElement().equals("api")) { return (String) parts.nextElement(); } } return null; } private Map<String, String> setHeaders(RESTInvoker restInvoker) throws APIMCertificateMGTException { Map<String, String> map = new HashMap<>(); String accessToken = Utils.getAccessToken(iotServerConfiguration, restInvoker); map.put(AUTHORIZATION, BEARER + accessToken); map.put(CONTENT_TYPE, "application/json"); return map; } }