org.wso2.carbon.identity.authenticator.wikid.WiKIDAuthenticator.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.authenticator.wikid.WiKIDAuthenticator.java

Source

/*
 *  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.identity.authenticator.wikid;

import org.apache.commons.lang.StringUtils;
import org.wso2.carbon.identity.application.authentication.framework.config.ConfigurationFacade;
import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext;
import org.wso2.carbon.identity.application.authentication.framework.exception.AuthenticationFailedException;
import org.wso2.carbon.identity.application.authentication.framework.exception.InvalidCredentialsException;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils;
import org.wso2.carbon.identity.application.authenticator.oidc.OpenIDConnectAuthenticator;
import org.wso2.carbon.identity.application.authentication.framework.FederatedApplicationAuthenticator;
import org.wso2.carbon.identity.application.common.model.Property;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.*;
import java.lang.String;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Authenticator of WiKID
 */
public class WiKIDAuthenticator extends OpenIDConnectAuthenticator implements FederatedApplicationAuthenticator {

    private static Log log = LogFactory.getLog(WiKIDAuthenticator.class);

    /**
     * Check whether the authentication or logout request can be handled by the authenticator
     */
    public boolean canHandle(HttpServletRequest request) {
        if (log.isDebugEnabled()) {
            log.debug("Inside WiKIDAuthenticator canHandle method");
        }
        return (StringUtils.isNotEmpty(request.getParameter(WiKIDAuthenticatorConstants.WIKID_REGISTRATION_CODE))
                && StringUtils.isNotEmpty(request.getParameter(WiKIDAuthenticatorConstants.WIKID_USER_ID)));
    }

    /**
     * Initiate the authentication request
     */
    @Override
    protected void initiateAuthenticationRequest(HttpServletRequest request, HttpServletResponse response,
            AuthenticationContext context) throws AuthenticationFailedException {
        try {
            Map<String, String> authenticatorProperties = context.getAuthenticatorProperties();
            String username = authenticatorProperties.get(WiKIDAuthenticatorConstants.WIKID_USERNAME);
            String password = authenticatorProperties.get(WiKIDAuthenticatorConstants.WIKID_PASSWORD);
            if (StringUtils.isNotEmpty(username) && StringUtils.isNotEmpty(password)) {
                if (StringUtils.isEmpty(login(username, password))) {
                    log.error("Invalid username or password");
                    throw new AuthenticationFailedException("Invalid username or password");
                } else {
                    String retryParam = "";
                    if (context.isRetrying()) {
                        retryParam = WiKIDAuthenticatorConstants.RETRY_PARAMS;
                    }
                    String wikidPage = ConfigurationFacade.getInstance().getAuthenticationEndpointURL().replace(
                            WiKIDAuthenticatorConstants.LOGIN_PAGE, WiKIDAuthenticatorConstants.WIKID_PAGE);
                    String queryParams = FrameworkUtils.getQueryStringWithFrameworkContextId(
                            context.getQueryParams(), context.getCallerSessionKey(),
                            context.getContextIdentifier());
                    response.sendRedirect(response.encodeRedirectURL(wikidPage + ("?" + queryParams))
                            + WiKIDAuthenticatorConstants.AUTHENTICATORS + getName() + ":"
                            + WiKIDAuthenticatorConstants.LOCAL + "&" + retryParam);
                }
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("Error while retrieving properties. WiKID username and password cannot be null");
                }
                throw new AuthenticationFailedException(
                        "Error while retrieving properties. WiKID username and password cannot be null");
            }
        } catch (IOException e) {
            throw new AuthenticationFailedException("Exception while redirecting the page: " + e.getMessage(), e);
        }
    }

    /**
     * Process the response of the WiKID end-point
     */
    @Override
    protected void processAuthenticationResponse(HttpServletRequest request, HttpServletResponse response,
            AuthenticationContext context) throws AuthenticationFailedException {
        String regCode = request.getParameter(WiKIDAuthenticatorConstants.WIKID_REGISTRATION_CODE);
        String userId = request.getParameter(WiKIDAuthenticatorConstants.WIKID_USER_ID);
        if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(regCode)) {
            log.error("Registration Code and User ID cannot not be null");
            throw new InvalidCredentialsException("Registration Code and User ID cannot not be null");
        } else {
            String deviceMapId = getDeviceMapId(regCode);
            if (StringUtils.isNotEmpty(deviceMapId)) {
                String validateUserResponse = validateUser(regCode, deviceMapId, userId);
                if (StringUtils.isNotEmpty(validateUserResponse)) {
                    AuthenticatedUser authenticatedUser = AuthenticatedUser
                            .createFederateAuthenticatedUserFromSubjectIdentifier(userId);
                    authenticatedUser.setUserName(userId);
                    context.setSubject(authenticatedUser);
                } else {
                    log.error("Unable to validate the user");
                    throw new AuthenticationFailedException("Unable to validate the user");
                }
            } else {
                log.error("Unable to find device map id");
                throw new AuthenticationFailedException("Unable to find device map id");
            }
        }
    }

    private String login(String username, String password) {
        String successMessage = "Current Statistics:";
        String urlToLogin = WiKIDAuthenticatorConstants.WIKID_ENDPOINT
                + WiKIDAuthenticatorConstants.WIKID_LOGIN_ENDPOINT;
        String loginResponse = sendRESTCall(urlToLogin,
                WiKIDAuthenticatorConstants.WIKID_USERNAME + "=" + username + "&"
                        + WiKIDAuthenticatorConstants.WIKID_PASSWORD + "=" + password,
                "", WiKIDAuthenticatorConstants.HTTP_POST);
        if (!loginResponse.startsWith(WiKIDAuthenticatorConstants.FAILED)
                && loginResponse.contains(successMessage)) {
            return WiKIDAuthenticatorConstants.SUCCESS;
        }
        return null;
    }

    private String getDeviceMapId(String regCode) {
        String urlToGetAllPreRegisteredUsers = WiKIDAuthenticatorConstants.WIKID_ENDPOINT
                + WiKIDAuthenticatorConstants.WIKID_VALIDATION_ENDPOINT;
        String preRegisteredUsersResponse = sendRESTCall(urlToGetAllPreRegisteredUsers, "", "",
                WiKIDAuthenticatorConstants.HTTP_GET);
        if (!preRegisteredUsersResponse.startsWith(WiKIDAuthenticatorConstants.FAILED)) {
            return preRegisteredUsersResponse.substring(
                    preRegisteredUsersResponse.indexOf(WiKIDAuthenticatorConstants.WIKID_REGISTRATION_CODE + "="
                            + regCode + "&" + WiKIDAuthenticatorConstants.WIKID_DEVICE_MAP_ID + "="),
                    preRegisteredUsersResponse.indexOf("\">" + regCode));
        }
        return null;
    }

    private String validateUser(String regCode, String deviceMapId, String userId) {
        String successMessage = "UserID " + userId + "Registered.";
        String urlToValidateUser = WiKIDAuthenticatorConstants.MAILING_ENDPOINT
                + WiKIDAuthenticatorConstants.WIKID_VALIDATION_ENDPOINT;
        String validateUserResponse = sendRESTCall(urlToValidateUser,
                WiKIDAuthenticatorConstants.WIKID_ACTION + "=" + WiKIDAuthenticatorConstants.WIKID_ACTION_REGISTER
                        + "&" + WiKIDAuthenticatorConstants.WIKID_REGISTRATION_CODE + "=" + regCode + "&"
                        + WiKIDAuthenticatorConstants.WIKID_DEVICE_MAP_ID + "=" + deviceMapId + "&"
                        + WiKIDAuthenticatorConstants.WIKID_USER_ID + "=" + userId,
                "", WiKIDAuthenticatorConstants.HTTP_POST);
        if (!validateUserResponse.startsWith(WiKIDAuthenticatorConstants.FAILED)
                || validateUserResponse.contains(successMessage)) {
            return WiKIDAuthenticatorConstants.SUCCESS;
        }
        return null;
    }

    /**
     * Send REST call
     */
    private String sendRESTCall(String url, String urlParameters, String formParameters, String httpMethod) {
        String line;
        StringBuilder responseString = new StringBuilder();
        HttpsURLConnection connection = null;
        try {
            setHttpsClientCert(
                    "/media/sf_SharedFoldersToVBox/is-connectors/wikid/wikid-authenticator/org.wso2.carbon.identity.authenticator/src/main/resources/localhostWiKID",
                    "shakila");
            SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();

            URL wikidEP = new URL(url + urlParameters);
            connection = (HttpsURLConnection) wikidEP.openConnection();
            connection.setSSLSocketFactory(sslsocketfactory);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestMethod(httpMethod);
            connection.setRequestProperty(WiKIDAuthenticatorConstants.HTTP_CONTENT_TYPE,
                    WiKIDAuthenticatorConstants.HTTP_CONTENT_TYPE_XWFUE);
            if (httpMethod.toUpperCase().equals(WiKIDAuthenticatorConstants.HTTP_POST)) {
                OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(),
                        WiKIDAuthenticatorConstants.CHARSET);
                writer.write(formParameters);
                writer.close();
            }
            if (connection.getResponseCode() == 200) {
                BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                while ((line = br.readLine()) != null) {
                    responseString.append(line);
                }
                br.close();
            } else {
                return WiKIDAuthenticatorConstants.FAILED + WiKIDAuthenticatorConstants.REQUEST_FAILED;
            }
        } catch (ProtocolException e) {
            if (log.isDebugEnabled()) {
                log.debug(WiKIDAuthenticatorConstants.FAILED + e.getMessage());
            }
            return WiKIDAuthenticatorConstants.FAILED + e.getMessage();
        } catch (MalformedURLException e) {
            if (log.isDebugEnabled()) {
                log.debug(WiKIDAuthenticatorConstants.FAILED + e.getMessage());
            }
            return WiKIDAuthenticatorConstants.FAILED + e.getMessage();
        } catch (IOException e) {
            if (log.isDebugEnabled()) {
                log.debug(WiKIDAuthenticatorConstants.FAILED + e.getMessage());
            }
            return WiKIDAuthenticatorConstants.FAILED + e.getMessage();
        } finally {
            connection.disconnect();
        }
        return responseString.toString();
    }

    public static void setHttpsClientCert(String certificateFile, String certPassword) {
        try {
            if (certificateFile == null || !new File(certificateFile).exists()) {
                return;
            }
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            InputStream keyInput = new FileInputStream(certificateFile);
            keyStore.load(keyInput, certPassword.toCharArray());
            keyInput.close();
            keyManagerFactory.init(keyStore, certPassword.toCharArray());
            SSLContext context = SSLContext.getInstance("TLS");
            context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
            SSLContext.setDefault(context);
        } catch (KeyStoreException e) {
        } catch (NoSuchAlgorithmException e) {
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        } catch (CertificateException e) {
        } catch (UnrecoverableKeyException e) {
        } catch (KeyManagementException e) {
        }
    }

    /**
     * Get WiKID endpoint.
     */
    protected String getEndpoint() {
        return WiKIDAuthenticatorConstants.WIKID_ENDPOINT;
    }

    /**
     * Check ID token in WiKID OAuth.
     */
    @Override
    protected boolean requiredIDToken(Map<String, String> authenticatorProperties) {
        return false;
    }

    /**
     * Get the friendly name of the Authenticator
     */
    @Override
    public String getFriendlyName() {
        return WiKIDAuthenticatorConstants.AUTHENTICATOR_FRIENDLY_NAME;
    }

    /**
     * Get the name of the Authenticator
     */
    @Override
    public String getName() {
        return WiKIDAuthenticatorConstants.AUTHENTICATOR_NAME;
    }

    @Override
    protected boolean retryAuthenticationEnabled() {
        return true;
    }

    /**
     * Get Configuration Properties
     */
    @Override
    public List<Property> getConfigurationProperties() {

        List<Property> configProperties = new ArrayList<Property>();

        Property userName = new Property();
        userName.setName(WiKIDAuthenticatorConstants.WIKID_USERNAME);
        userName.setRequired(true);
        userName.setDisplayName("Username");
        userName.setDescription("Enter username of WiKID server");
        userName.setDisplayOrder(0);
        configProperties.add(userName);

        Property password = new Property();
        password.setName(WiKIDAuthenticatorConstants.WIKID_PASSWORD);
        userName.setRequired(true);
        userName.setConfidential(true);
        password.setDisplayName("Password");
        password.setDescription("Enter the password of WiKID server");
        password.setDisplayOrder(1);
        configProperties.add(password);

        return configProperties;
    }
}