org.wso2.carbon.identity.application.authenticator.fido.u2f.U2FService.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.application.authenticator.fido.u2f.U2FService.java

Source

/*
 * Copyright (c) 2015, 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.application.authenticator.fido.u2f;

import com.yubico.u2f.U2F;
import com.yubico.u2f.data.DeviceRegistration;
import com.yubico.u2f.data.messages.AuthenticateRequestData;
import com.yubico.u2f.data.messages.RegisterRequestData;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.application.authentication.framework.exception.AuthenticationFailedException;
import org.wso2.carbon.identity.application.authenticator.fido.dao.DeviceStoreDAO;
import org.wso2.carbon.identity.application.authenticator.fido.dto.FIDOUser;
import org.wso2.carbon.identity.application.authenticator.fido.exception.FIDOAuthenticatorServerException;
import org.wso2.carbon.identity.base.IdentityException;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class U2FService {

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

    private static volatile U2FService u2FService;
    private final U2F u2f = new U2F();
    private static Map<String, String> requestStorage = new HashMap<String, String>();

    /**
     * Gets a U2FService instance.
     * @return a U2FService.
     */
    public static U2FService getInstance() {

        if (u2FService == null) {
            synchronized (U2FService.class) {
                if (u2FService == null) {
                    u2FService = new U2FService();
                    return u2FService;
                } else {
                    return u2FService;
                }
            }
        } else {
            return u2FService;
        }
    }

    private U2FService() {

    }

    private Iterable<DeviceRegistration> getRegistrations(final FIDOUser user)
            throws FIDOAuthenticatorServerException {

        Collection<String> serializedRegistrations = null;
        serializedRegistrations = DeviceStoreDAO.getInstance().getDeviceRegistration(user.getUserName(),
                user.getTenantDomain(), user.getUserStoreDomain());

        List<DeviceRegistration> registrations = new ArrayList<DeviceRegistration>();
        for (String serialized : serializedRegistrations) {
            registrations.add(DeviceRegistration.fromJson(serialized));
        }

        return registrations;
    }

    /**
     * Initiate FIDO authentication.
     *
     * @param user the FIDO user.
     * @return AuthenticateRequestData.
     * @throws AuthenticationFailedException when U2F can not generate the challenge
     */
    public AuthenticateRequestData startAuthentication(final FIDOUser user) throws AuthenticationFailedException {
        AuthenticateRequestData authenticateRequestData = null;
        int numberOfRegistereddevice = 0;

        Iterable<DeviceRegistration> registeredDeviceList = null;
        try {
            registeredDeviceList = getRegistrations(user);
        } catch (Exception e) {
            throw new AuthenticationFailedException(e.getMessage(), e);
        }
        if (registeredDeviceList instanceof Collection<?>) {
            numberOfRegistereddevice = ((Collection<?>) registeredDeviceList).size();
        }
        if (numberOfRegistereddevice > 0) {
            try {
                authenticateRequestData = u2f.startAuthentication(user.getAppID(), registeredDeviceList);
            } catch (Exception e) {
                throw new AuthenticationFailedException("Could not start FIDO authentication", e);
            }

            requestStorage.put(authenticateRequestData.getRequestId(), authenticateRequestData.toJson());
        }
        return authenticateRequestData;
    }

    /**
     * Finish FIDO authentication.
     *
     * @param user the FIDO user.
     * @throws AuthenticationFailedException when validation fails.
     */
    public void finishAuthentication(final FIDOUser user) throws AuthenticationFailedException {

        AuthenticateRequestData authenticateRequest;
        try {
            authenticateRequest = AuthenticateRequestData
                    .fromJson(requestStorage.remove(user.getAuthenticateResponse().getRequestId()));

            u2f.finishAuthentication(authenticateRequest, user.getAuthenticateResponse(), getRegistrations(user));

        } catch (Exception e) {
            throw new AuthenticationFailedException("Could not complete FIDO authentication", e);
        }
    }

    /**
     * Initiate FIDO Device Registration.
     *
     * @param user the FIDO user.
     * @throws IdentityException when U2F can not generate the challenge.
     */
    public RegisterRequestData startRegistration(final FIDOUser user) throws FIDOAuthenticatorServerException {

        RegisterRequestData registerRequestData = u2f.startRegistration(user.getAppID(), getRegistrations(user));
        requestStorage.put(registerRequestData.getRequestId(), registerRequestData.toJson());
        return registerRequestData;
    }

    /**
     * Finish FIDO Device registration
     *
     * @param user the FIDO user.
     * @return success or failure.
     * @throws IdentityException when validation fails.
     */
    public void finishRegistration(final FIDOUser user) throws FIDOAuthenticatorServerException {

        RegisterRequestData registerRequestData = RegisterRequestData
                .fromJson(requestStorage.remove(user.getRegisterResponse().getRequestId()));

        user.setDeviceRegistration(u2f.finishRegistration(registerRequestData, user.getRegisterResponse()));
        addRegistration(user);
    }

    private void addRegistration(FIDOUser user) throws FIDOAuthenticatorServerException {
        Timestamp timestamp = new Timestamp(new Date().getTime());
        DeviceStoreDAO.getInstance().addDeviceRegistration(user.getUserName(), user.getDeviceRegistration(),
                user.getTenantDomain(), user.getUserStoreDomain(), timestamp);
    }

    public boolean isDeviceRegistered(FIDOUser user) throws FIDOAuthenticatorServerException {
        Collection<String> registrations = DeviceStoreDAO.getInstance().getDeviceRegistration(user.getUserName(),
                user.getTenantDomain(), user.getUserStoreDomain());
        if (!registrations.isEmpty()) {
            return true;
        } else {
            return false;
        }

    }

    public ArrayList<String> getDeviceMetadata(FIDOUser user) throws FIDOAuthenticatorServerException {
        return DeviceStoreDAO.getInstance().getDeviceMetadata(user.getUserName(), user.getTenantDomain(),
                user.getUserStoreDomain());

    }

    public void removeAllRegistrations(FIDOUser user) throws FIDOAuthenticatorServerException {
        DeviceStoreDAO.getInstance().removeAllRegistrations(user.getUserName(), user.getTenantDomain(),
                user.getUserStoreDomain());
    }

    public void removeRegistration(FIDOUser user, String deviceRemarks) throws FIDOAuthenticatorServerException {
        DeviceStoreDAO.getInstance().removeRegistration(user.getUserName(), user.getTenantDomain(),
                user.getUserStoreDomain(), Timestamp.valueOf(deviceRemarks));

    }
}