/** * Copyright 2013 Tommi S.E. Laukkanen * * Licensed 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.bubblecloud.ilves.security; import com.yubico.u2f.data.DeviceRegistration; import org.bubblecloud.ilves.model.AuthenticationDevice; import org.bubblecloud.ilves.model.AuthenticationDeviceType; import org.bubblecloud.ilves.model.Company; import org.bubblecloud.ilves.model.User; import org.bubblecloud.ilves.site.SiteContext; import javax.persistence.EntityManager; import java.util.ArrayList; import java.util.List; /** * Universal second factor (U2F) service. * * @author Tommi S.E. Laukkanen */ public class U2fService { /** * Checks if user has device registrations. * @param context the security context * @param emailAddress the email address * @return true if device registrations exist */ public static boolean hasDeviceRegistrations(final SiteContext context, final String emailAddress) { final Company company = context.getObject(Company.class); final EntityManager entityManager = context.getEntityManager(); final User user = UserDao.getUser(entityManager, company, emailAddress); final List<AuthenticationDevice> authenticationDevices = AuthenticationDeviceDao.getAuthenticationDevices(entityManager, user); for (final AuthenticationDevice authenticationDevice : authenticationDevices) { if (authenticationDevice.getType() == AuthenticationDeviceType.UNIVERSAL_SECOND_FACTOR) { return true; } } return false; } /** * Gets device registrations. * @param context the security context * @param emailAddress the email address * @return list of device registrations */ public static List<DeviceRegistration> getDeviceRegistrations(final SiteContext context, final String emailAddress) { final Company company = context.getObject(Company.class); final EntityManager entityManager = context.getEntityManager(); final User user = UserDao.getUser(entityManager, company, emailAddress); final List<AuthenticationDevice> authenticationDevices = AuthenticationDeviceDao.getAuthenticationDevices(entityManager, user); final List<DeviceRegistration> deviceRegistrations = new ArrayList<>(); for (final AuthenticationDevice authenticationDevice : authenticationDevices) { if (authenticationDevice.getType() == AuthenticationDeviceType.UNIVERSAL_SECOND_FACTOR) { final String secret = SecurityUtil.decryptSecretKey(authenticationDevice.getEncryptedSecret()); final DeviceRegistration deviceRegistration = DeviceRegistration.fromJson(secret); deviceRegistrations.add(deviceRegistration); } } return deviceRegistrations; } /** * Adds device registration. * @param context the context * @param emailAddress the email address * @param deviceRegistration the device registration */ public static void addDeviceRegistration(final SiteContext context, final String emailAddress, final DeviceRegistration deviceRegistration) { final Company company = context.getObject(Company.class); final EntityManager entityManager = context.getEntityManager(); final User user = UserDao.getUser(entityManager, company, emailAddress); final String secret = deviceRegistration.toJson(); final String encryptedSecret = SecurityUtil.encryptSecretKey(secret); final AuthenticationDevice authenticationDevice = new AuthenticationDevice(); authenticationDevice.setKey(deviceRegistration.getKeyHandle()); String name; try { name = deviceRegistration.getAttestationCertificate().getSubjectDN().toString(); if (name.startsWith("CN=")) { name = name.substring(3); } } catch (final Exception e) { name = "u2f device"; } authenticationDevice.setName(name); authenticationDevice.setType(AuthenticationDeviceType.UNIVERSAL_SECOND_FACTOR); authenticationDevice.setUser(user); authenticationDevice.setEncryptedSecret(encryptedSecret); AuthenticationDeviceDao.addAuthenticationDevice(entityManager, authenticationDevice); } /** * Updates device registration. * @param context the context * @param emailAddress the email address * @param deviceRegistration the device registration */ public static void updateDeviceRegistration(final SiteContext context, final String emailAddress, final DeviceRegistration deviceRegistration) { final Company company = context.getObject(Company.class); final EntityManager entityManager = context.getEntityManager(); final User user = UserDao.getUser(entityManager, company, emailAddress); final String secret = deviceRegistration.toJson(); final String encryptedSecret = SecurityUtil.encryptSecretKey(secret); final AuthenticationDevice authenticationDevice = AuthenticationDeviceDao.getAuthenticationDeviceByKey(entityManager, deviceRegistration.getKeyHandle()); if (!user.getUserId().equals(authenticationDevice.getUser().getUserId())) { throw new SecurityException("Authentication device user mismatch."); } authenticationDevice.setEncryptedSecret(encryptedSecret); AuthenticationDeviceDao.updateAuthenticationDevice(entityManager, authenticationDevice); } }