/************************************************************************* * * * CESeCore: CE Security Core * * * * This software is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or any later version. * * * * See terms of license at gnu.org. * * * *************************************************************************/ package org.cesecore.authentication.tokens; import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.util.Set; import org.bouncycastle.util.encoders.Hex; import org.cesecore.authentication.AuthenticationFailedException; import org.cesecore.authorization.user.AccessUserAspect; import org.cesecore.authorization.user.matchvalues.AccessMatchValue; /** * A token returned by the act of authentication. Ownership of such a token denotes that the caller has previously authenticated herself via the * Authentication session bean. * * The Sets of Principals and credentials contained within this class will correspond to the subset of those found in the Subject class submitted for * authentication used for that process. * * @version $Id: AuthenticationToken.java 26983 2017-11-02 13:58:25Z samuellb $ * */ public abstract class AuthenticationToken implements Serializable { private static final long serialVersionUID = 1888731103952962350L; private final Set principals; private final Set credentials; private transient String uniqueId = null; public static final int NO_PREFERRED_MATCH_KEY = -1; public AuthenticationToken(Set principals, Set credentials) { this.principals = principals; this.credentials = credentials; } public Set getPrincipals() { return principals; } public Set getCredentials() { return credentials; } /** * This method will take an AccessUserAspectData entity and return whether or not it matches to this AuthenticationToken. Will * specifically check for locality if required. * * @param accessUser An AccessUserAspectData entity to match. * @return true if matching. * @throws AuthenticationFailedException if any authentication errors were encountered during process */ public abstract boolean matches(AccessUserAspect accessUser) throws AuthenticationFailedException; @Override public abstract boolean equals(Object authenticationToken); @Override public abstract int hashCode(); public abstract AuthenticationTokenMetaData getMetaData(); /** * Default way of returning the user information of the user(s) this authentication token belongs to. * This should never return sensitive information, since it is used in logging (CESeCore.FAU_GEN.1.2). * @return a comma-separated list of all principal names in this token */ @Override public String toString() { final StringBuilder sb = new StringBuilder(); final Set principals = getPrincipals(); if (principals != null) { for (final Principal principal : principals) { if (sb.length() > 0) { sb.append(", "); } sb.append(principal.getName()); } } return sb.toString(); } /** * @param tokenType String a String from an AccessMatchValue derivative that matches this token type. * @return true if the given value matches this AuthenticationToken's inherent token type. */ public boolean matchTokenType(String tokenType) { return getMetaData().getTokenType().equals(tokenType); } /** * * @return the first available AccessMatchValue inherent to the implementing token type. */ public AccessMatchValue getDefaultMatchValue() { return getMetaData().getAccessMatchValueDefault(); } /** * * @param databaseValue the numeric value from the database. * @return the enum implementing AccessMatchValue that matches the given numeric value from the database. */ public AccessMatchValue getMatchValueFromDatabaseValue(Integer databaseValue) { return getMetaData().getAccessMatchValueIdMap().get(databaseValue); } /** * Returns the preferred match key for this type of authentication token. E.g. serial number for X.509 tokens * If not applicable to this authentication token, then it returns {@link #NO_PREFERRED_MATCH_KEY}. */ public abstract int getPreferredMatchKey(); /** * Returns the preferred match value for this authentication token. E.g. the serial number of X.509 tokens. * Note: For performance reasons, this value must support case sensitive searching. */ public abstract String getPreferredMatchValue(); /** @return a String that is guaranteed to be unique across all AuthenticationTokens of this type. */ protected abstract String generateUniqueId(); /** @return a hex-encoded string of the hash over all the provided arguments */ protected String generateUniqueId(final Object...arguments) { try { final MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); for (final Object argument : arguments) { if (argument instanceof byte[]) { messageDigest.update((byte[]) argument); messageDigest.update((byte) ';'); } else { messageDigest.update((String.valueOf(argument)+";").getBytes(StandardCharsets.UTF_8)); } } return new String(Hex.encode(messageDigest.digest())); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException(e); } } /** @return a String that is guaranteed to be unique across all AuthenticationTokens (and will be different if nested with different AuthenticationTokens). */ public String getUniqueId() { if (uniqueId==null) { uniqueId = getMetaData().getTokenType() + ";" + generateUniqueId(); } return uniqueId; } }