All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.imunity.vaadin.auth.AuthenticationOptionsHandler Maven / Gradle / Ivy

There is a newer version: 4.0.3
Show newest version
/*
 * Copyright (c) 2021 Bixbit - Krzysztof Benedyczak. All rights reserved.
 * See LICENCE.txt file for licensing information.
 */
package io.imunity.vaadin.auth;

import org.apache.logging.log4j.Logger;

import pl.edu.icm.unity.base.authn.AuthenticationOptionKeyUtils;
import pl.edu.icm.unity.base.authn.AuthenticationRealm;
import pl.edu.icm.unity.base.utils.Log;
import pl.edu.icm.unity.engine.api.authn.AuthenticationFlow;
import pl.edu.icm.unity.engine.api.authn.AuthenticatorInstance;
import pl.edu.icm.unity.engine.api.authn.AuthenticatorStepContext;
import pl.edu.icm.unity.engine.api.authn.AuthenticatorStepContext.FactorOrder;

import java.util.*;

/**
 * Helps to find and create UIs matching given spec
 */
public class AuthenticationOptionsHandler
{
	private static final Logger log = Log.getLogger(Log.U_SERVER_WEB, AuthenticationOptionsHandler.class);
	private final Map authenticatorsByName = new LinkedHashMap<>();
	private final String endpoint;
	private final AuthenticationRealm realm;
	private final String endpointPath;

	private final Set consumedAuthenticators = new HashSet<>();
	private final Set consumedAuthenticatorEntries = new HashSet<>();

	public AuthenticationOptionsHandler(List availableAuthentionFlows, String endpoint,
	                                    AuthenticationRealm realm, String endpointPath)
	{
		this.endpoint = endpoint;
		this.realm = realm;
		this.endpointPath = endpointPath;
		for (AuthenticationFlow ao : availableAuthentionFlows)
			for (AuthenticatorInstance a: ao.getFirstFactorAuthenticators())
			{
				String authenticatorId = a.getRetrieval().getAuthenticatorId();
				if (authenticatorsByName.containsKey(authenticatorId))
					log.warn("Endpoint {} has authenticator {} enabled more then once as a first "
							+ "factor. Most likely it is provisioned from 2 flows. "
							+ "Random one will be used.", endpoint, authenticatorId);
				authenticatorsByName.put(authenticatorId, new AuthenticatorWithFlow(ao, a));
			}
	}

	void clear()
	{
		consumedAuthenticators.clear();
		consumedAuthenticatorEntries.clear();
	}

	AuthenticatorInstance getMatchingAuthenticator(String spec)
	{
		String authenticatorName = AuthenticationOptionKeyUtils.decodeAuthenticator(spec);
		return authenticatorsByName.get(authenticatorName).authenticator;
	}

	AuthNOption getFirstMatchingOption(String spec)
	{
		List ret = getMatchingAuthnOptions(spec);
		return ret.isEmpty() ? null : ret.get(0);
	}

	public List getMatchingAuthnOptions(String spec)
	{
		String authenticatorName = AuthenticationOptionKeyUtils.decodeAuthenticator(spec);
		AuthenticatorWithFlow authenticatorWF = authenticatorsByName.get(authenticatorName);
		if (authenticatorWF == null)
		{
			log.warn("There is no authenticator '{}' configured for the endpoint {} for the '{}' "
					+ "authentication contents entry", authenticatorName, endpoint, spec);
			return Collections.emptyList();
		}

		String authenticatonOptionName = AuthenticationOptionKeyUtils.decodeOption(spec);
		if (authenticatonOptionName == null)
		{
			if (!consumedAuthenticators.add(AuthenticationOptionKeyUtils.decodeAuthenticator(spec)))
				return Collections.emptyList();
		}
		
		VaadinAuthentication vaadinAuthenticator = (VaadinAuthentication) authenticatorWF.authenticator.getRetrieval();
		AuthenticatorStepContext authenticatorContext = new AuthenticatorStepContext(realm, authenticatorWF.flow, 
				endpointPath, FactorOrder.FIRST);
		Collection optionUIInstances = vaadinAuthenticator.createUIInstance(
				VaadinAuthentication.Context.LOGIN, authenticatorContext);
		List ret = new ArrayList<>();
		for (VaadinAuthentication.VaadinAuthenticationUI vaadinAuthenticationUI : optionUIInstances)
		{
			if (!vaadinAuthenticationUI.isAvailable())
				continue;
			String currentKey = AuthenticationOptionKeyUtils.encode(vaadinAuthenticator.getAuthenticatorId(),
					vaadinAuthenticationUI.getId());
			if (consumedAuthenticatorEntries.contains(currentKey))
				continue;
			if (authenticatonOptionName == null
					|| authenticatonOptionName.equals(vaadinAuthenticationUI.getId()))
			{
				ret.add(new AuthNOption(authenticatorWF.flow,
						(VaadinAuthentication) authenticatorWF.authenticator.getRetrieval(), 
						vaadinAuthenticationUI));
				consumedAuthenticatorEntries.add(currentKey);
			}
		}
		return ret;
	}

	List getRemainingAuthnOptions()
	{
		List ret = new ArrayList<>();
		for (AuthenticatorWithFlow authenticatorWF : authenticatorsByName.values())
		{
			if (consumedAuthenticators.contains(authenticatorWF.authenticator.getRetrieval().getAuthenticatorId()))
				continue;

			VaadinAuthentication retrieval = (VaadinAuthentication) authenticatorWF.authenticator.getRetrieval();
			AuthenticatorStepContext authenticatorContext = new AuthenticatorStepContext(realm, authenticatorWF.flow, 
					endpointPath, FactorOrder.FIRST);
			Collection optionUIInstances = retrieval.createUIInstance(VaadinAuthentication.Context.LOGIN,
					authenticatorContext);
			for (VaadinAuthentication.VaadinAuthenticationUI vaadinAuthenticationUI : optionUIInstances)
			{
				if (!vaadinAuthenticationUI.isAvailable())
					continue;
				String entryKey = AuthenticationOptionKeyUtils.encode(retrieval.getAuthenticatorId(), 
						vaadinAuthenticationUI.getId());
				if (!consumedAuthenticatorEntries.contains(entryKey))
					ret.add(new AuthNOption(authenticatorWF.flow, retrieval, vaadinAuthenticationUI));
			}
		}
		return ret;
	}

	private static class AuthenticatorWithFlow
	{
		final AuthenticationFlow flow;
		final AuthenticatorInstance authenticator;

		public AuthenticatorWithFlow(AuthenticationFlow flow, AuthenticatorInstance authenticator)
		{
			this.flow = flow;
			this.authenticator = authenticator;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy