use of org.dcache.gplazma.AuthenticationException in project dcache by dCache.
the class QueryUserInfoEndpoint method identityProviders.
private Collection<IdentityProvider> identityProviders(String token) throws AuthenticationException {
if (JsonWebToken.isCompatibleFormat(token)) {
try {
JsonWebToken jwt = new JsonWebToken(token);
Optional<String> iss = jwt.getPayloadString("iss");
if (iss.isPresent()) {
try {
URI issuer = new URI(iss.get());
IdentityProvider ip = providersByIssuer.get(issuer);
checkAuthentication(ip != null, "JWT with unknown \"iss\" claim");
LOG.debug("Discovered token is JWT issued by {}", ip.getName());
return Collections.singleton(ip);
} catch (URISyntaxException e) {
LOG.debug("Bad \"iss\" claim \"{}\": {}", iss.get(), e.toString());
throw new AuthenticationException("Bad \"iss\" claim in JWT");
}
}
} catch (IOException e) {
LOG.debug("Failed to parse JWT: {}", e.toString());
throw new AuthenticationException("Bad JWT");
}
}
return providersByIssuer.values();
}
use of org.dcache.gplazma.AuthenticationException in project dcache by dCache.
the class QueryUserInfoEndpoint method extract.
@Override
public ExtractResult extract(String token) throws AuthenticationException {
Stopwatch userinfoLookupTiming = Stopwatch.createStarted();
List<LookupResult> allResults;
try {
allResults = userInfoCache.get(token);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
Throwables.throwIfInstanceOf(cause, AuthenticationException.class);
Throwables.throwIfUnchecked(cause);
if (cause instanceof InterruptedException) {
throw new AuthenticationException("Shutting down");
}
throw new RuntimeException("Unexpected exception", e);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Doing user-info lookup against {} OPs took {}", allResults.size(), TimeUtils.describe(userinfoLookupTiming.elapsed()).orElse("no time"));
}
List<LookupResult> successfulResults = allResults.stream().filter(LookupResult::isSuccess).collect(Collectors.toList());
if (successfulResults.isEmpty()) {
if (allResults.size() == 1) {
LookupResult result = allResults.get(0);
throw new AuthenticationException("OpenId Validation failed for " + result.getIdentityProvider().getName() + ": " + result.getError());
} else {
String randomId = randomId();
String errors = allResults.stream().map(r -> "[" + r.getIdentityProvider().getName() + ": " + r.getError() + "]").collect(Collectors.joining(", "));
LOG.warn("OpenId Validation Failure ({}): {}", randomId, errors);
throw new AuthenticationException("OpenId Validation Failed check [log entry #" + randomId + "]");
}
}
if (successfulResults.size() > 1) {
String names = successfulResults.stream().map(LookupResult::getIdentityProvider).map(IdentityProvider::getName).collect(Collectors.joining(", "));
LOG.warn("Multiple OpenID-Connect endpoints accepted access token: {}", names);
throw new AuthenticationException("Multiple OPs accepted token.");
}
var result = successfulResults.get(0);
return new ExtractResult(result.getIdentityProvider(), result.getClaims());
}
use of org.dcache.gplazma.AuthenticationException in project dcache by dCache.
the class Nis method session.
@Override
public void session(Set<Principal> authorizedPrincipals, Set<Object> attrib) throws AuthenticationException {
Principal principal = find(authorizedPrincipals, instanceOf(UserNamePrincipal.class), null);
checkAuthentication(principal != null, "no username principal");
try {
Attributes userAttr = _ctx.getAttributes(NISMAP_PASSWORD_BY_NAME + "/" + principal.getName());
attrib.add(new HomeDirectory((String) userAttr.get(HOME_DIR_ATTRIBUTE).get()));
attrib.add(new RootDirectory("/"));
} catch (NamingException e) {
throw new AuthenticationException("no mapping: " + e.getMessage(), e);
}
}
use of org.dcache.gplazma.AuthenticationException in project dcache by dCache.
the class Nis method map.
@Override
public void map(Set<Principal> principals) throws AuthenticationException {
boolean mapped;
Principal principal = find(principals, instanceOf(UserNamePrincipal.class), null);
checkAuthentication(principal != null, "no username principal");
try {
Attributes userAttr = _ctx.getAttributes(NISMAP_PASSWORD_BY_NAME + "/" + principal.getName());
principals.add(new UidPrincipal((String) userAttr.get(UID_NUMBER_ATTRIBUTE).get()));
principals.add(new GidPrincipal((String) userAttr.get(GID_NUMBER_ATTRIBUTE).get(), true));
NamingEnumeration<SearchResult> groupResult = _ctx.search(NISMAP_GROUP_BY_NAME, new BasicAttributes(MEMBER_UID_ATTRIBUTE, principal.getName()));
mapped = true;
while (groupResult.hasMore()) {
SearchResult result = groupResult.next();
principals.add(new GidPrincipal((String) result.getAttributes().get(GID_NUMBER_ATTRIBUTE).get(), false));
}
} catch (NamingException e) {
LOGGER.debug("Failed to get mapping: {}", e.toString());
throw new AuthenticationException("no mapping: " + e.getMessage(), e);
}
checkAuthentication(mapped, "no matching principal");
}
use of org.dcache.gplazma.AuthenticationException in project dcache by dCache.
the class BanFilePlugin method loadConfigIfNeeded.
/**
* Create a list of principals from the source file. The empty lines and comments, i.e., lines
* starting with '#' are ignored. It expects the file to be of the format: alias <alias>=<full
* qualified classname> ban <full qualified classname or alias>:<principal string> e.g., alias
* username=org.dcache.auth.UserNamePrincipal ban username:Someuser or ban
* org.dcache.auth.UserNamePrincipal:Someuser
*
* @return a set of banned principals
*/
private synchronized Set<Principal> loadConfigIfNeeded() throws AuthenticationException {
try {
if (bannedPrincipals == null || lastFileRead.isBefore(Files.readAttributes(configFile, BasicFileAttributes.class).lastModifiedTime().toInstant())) {
// alias -> value, like uid=org.dcache.auth.UidPrincipal
Map<String, String> aliases = new HashMap<>();
// class/alias -> value, like uid:123 or org.dcache.auth.UidPrincipal:123
Map<String, String> bans = new HashMap<>();
// group all 'alias' and all 'ban' records, skip comments and empty lines
Map<String, List<String>> config = loadConfigLines().stream().map(String::strip).filter(not(String::isEmpty)).filter(l -> l.charAt(0) != '#').collect(Collectors.groupingBy(l -> l.split("\\s")[0]));
// process aliases as they might be used in the next step
List<String> configuredAliases = config.remove("alias");
if (configuredAliases != null) {
configuredAliases.forEach(a -> {
Matcher m = ALIAS_PATTERN.matcher(a);
if (!m.matches()) {
throw new IllegalArgumentException("Bad alias line format: '" + a + "', expected 'alias <alias>=<class>'");
}
String alias = m.group(1);
String clazz = m.group(2);
aliases.put(alias, clazz);
});
}
// process ban records. substitute aliases, if needed
List<String> configuredBans = config.remove("ban");
if (configuredBans != null) {
configuredBans.forEach(a -> {
Matcher m = BAN_PATTERN.matcher(a);
if (!m.matches()) {
throw new IllegalArgumentException("Bad ban line format: '" + a + "', expected 'ban <classOrAlias>:<value>'");
}
String clazz = m.group(1);
String value = m.group(2);
bans.put(aliases.getOrDefault(clazz, clazz), value);
});
}
// any other key is an error
if (!config.isEmpty()) {
String badLines = config.values().stream().flatMap(List::stream).collect(Collectors.joining(",", "[", "]"));
throw new IllegalArgumentException("Line has bad format: '" + badLines + "', expected '[alias|ban] <key>:<value>'");
}
// construct lines suitable for Subjects.principalsFromArgs
// class:value or shortname:value
List<String> bannedNames = bans.entrySet().stream().map(e -> e.getKey() + ":" + e.getValue()).collect(Collectors.toList());
bannedPrincipals = Subjects.principalsFromArgs(bannedNames);
lastFileRead = Instant.now();
}
} catch (IOException e) {
throw new AuthenticationException(e);
}
return bannedPrincipals;
}
Aggregations