blob: 4e1f30fb0b70e63150b2d469f1c3d1d78d6c4556 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 EclipseSource Muenchen GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Edgar Mueller - initial API and implementation
******************************************************************************/
package org.eclipse.emf.emfstore.internal.server.accesscontrol;
import java.util.List;
import org.eclipse.emf.emfstore.common.extensionpoint.ESExtensionElement;
import org.eclipse.emf.emfstore.common.extensionpoint.ESExtensionPoint;
import org.eclipse.emf.emfstore.common.extensionpoint.ESExtensionPointException;
import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.internal.server.accesscontrol.authentication.ESUserVerifierFactory;
import org.eclipse.emf.emfstore.internal.server.core.MonitorProvider;
import org.eclipse.emf.emfstore.internal.server.exceptions.AccessControlException;
import org.eclipse.emf.emfstore.internal.server.exceptions.FatalESException;
import org.eclipse.emf.emfstore.internal.server.model.AuthenticationInformation;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACUser;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESAuthenticationInformationImpl;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESUserImpl;
import org.eclipse.emf.emfstore.server.auth.ESAuthenticationControlType;
import org.eclipse.emf.emfstore.server.auth.ESOrgUnitResolver;
import org.eclipse.emf.emfstore.server.auth.ESSessions;
import org.eclipse.emf.emfstore.server.auth.ESUserVerifier;
import org.eclipse.emf.emfstore.server.model.ESAuthenticationInformation;
import org.eclipse.emf.emfstore.server.model.ESClientVersionInfo;
import org.eclipse.emf.emfstore.server.model.ESOrgUnitProvider;
import org.eclipse.emf.emfstore.server.model.ESSessionId;
/**
* Service for logging users out and in. The user verification step is customizable via an extension point.
*
* @author emueller
*
*/
public class LoginService {
private static final String USER_VERIFIER_SERVICE_CLASS = "userVerifierServiceClass"; //$NON-NLS-1$
private static final String MONITOR_NAME = "authentication"; //$NON-NLS-1$
private static final String ACCESSCONTROL_EXTENSION_ID = "org.eclipse.emf.emfstore.server.accessControl"; //$NON-NLS-1$
private final ESSessions sessions;
private final ESOrgUnitResolver orgUnitResolver;
private final ESOrgUnitProvider orgUnitProvider;
private final ESAuthenticationControlType authenticationControlType;
private ESUserVerifier userVerifier;
/**
* Constructor.
*
* @param authenticationControlType
* the desired type authentication control type
* @param sessions
* a {@link ESSessions} map that will be updated in case an user successfully logins
* @param orgUnitProvider
* an {@link ESOrgUnitProvider} that provides access to all organizational units known by EMFStore.
* This may be consumed by an {@link ESUserVerifier} but boesn't necessarily needs to happen.
* It's absolutely fine if {@link ESUserVerifier} ignore the provider.
* @param orgUnitResolver
* an {@link ESOrgUnitResolver} for resolving any roles and groups on a given organizational unit
*/
public LoginService(
ESAuthenticationControlType authenticationControlType,
ESSessions sessions,
ESOrgUnitProvider orgUnitProvider,
ESOrgUnitResolver orgUnitResolver) {
this.authenticationControlType = authenticationControlType;
this.sessions = sessions;
this.orgUnitProvider = orgUnitProvider;
this.orgUnitResolver = orgUnitResolver;
}
private ESUserVerifier initUserVerifierService() {
try {
final ESExtensionPoint ext = new ESExtensionPoint(ACCESSCONTROL_EXTENSION_ID, false);
final List<ESExtensionElement> elements = ext.getExtensionElements();
ESUserVerifier verifier = null;
for (final ESExtensionElement el : elements) {
verifier = el.getClass(
USER_VERIFIER_SERVICE_CLASS, ESUserVerifier.class);
if (verifier != null) {
verifier.init(orgUnitProvider);
return verifier;
}
}
return ESUserVerifierFactory.getInstance().createUserVerifier(
authenticationControlType,
orgUnitProvider);
} catch (final ESExtensionPointException ex) {
ModelUtil.logException(Messages.LoginService_CustomLoginServiceInitFailed, ex);
return null;
} catch (final FatalESException ex) {
ModelUtil.logException(Messages.LoginService_CustomLoginServiceInitFailed, ex);
return null;
}
}
/**
* Login the given user with the provided password and client version.
*
* @param username
* the name of the user to be logged in
* @param password
* the password of the user
* @param clientVersionInfo
* the client version of the user
* @return an {@link ESAuthenticationInformation} in case the login was successfull
* @throws AccessControlException in case user verification fails
*/
public ESAuthenticationInformation logIn(String username, String password,
ESClientVersionInfo clientVersionInfo)
throws AccessControlException {
synchronized (MonitorProvider.getInstance().getMonitor(MONITOR_NAME)) {
final ESAuthenticationInformation authInfo = getUserVerifierService().verifyUser(
username,
password,
clientVersionInfo);
sessions.add(authInfo);
final ACUser resolvedUser = (ACUser) ESUserImpl.class.cast(
orgUnitResolver.resolveRoles(authInfo))
.toInternalAPI();
final AuthenticationInformation authenticationInformation = ESAuthenticationInformationImpl.class.cast(
authInfo).toInternalAPI();
authenticationInformation.setResolvedACUser(resolvedUser);
return authInfo;
}
}
private ESUserVerifier getUserVerifierService() {
if (userVerifier == null) {
userVerifier = initUserVerifierService();
}
return userVerifier;
}
/**
* Logout the given session.
*
* @param sessionId
* the ID of the session that should be logged out
* @throws AccessControlException in case the the session ID is null
*/
public void logout(ESSessionId sessionId) throws AccessControlException {
synchronized (MonitorProvider.getInstance().getMonitor(MONITOR_NAME)) {
if (sessionId == null) {
throw new AccessControlException(Messages.AccessControlImpl_SessionID_Is_Null);
}
sessions.remove(sessionId);
}
}
/**
* Checks whether the given credentials are valid without logging the client in.
*
* @param username
* the user name
* @param password
* the encrypted password of the user
* @param clientVersionInfo
* the client's version
* @return {@code true}, if the user's credentials are valid, {@code false} otherwise
*/
public boolean verifyUser(String username, String password, ESClientVersionInfo clientVersionInfo) {
try {
getUserVerifierService().verifyUser(
username,
password,
clientVersionInfo);
return true;
} catch (final AccessControlException e) {
// ignore
}
return false;
}
}