smarter auth handling

This commit is contained in:
Jörg Prante 2024-04-17 16:26:06 +02:00
parent caf267fd9a
commit 3bf46413b1
6 changed files with 56 additions and 34 deletions

View file

@ -40,7 +40,8 @@ public class J2HtmlResource extends HtmlTemplateResource {
.header("cache-control", cacheControl()) // override default must-revalidate behavior .header("cache-control", cacheControl()) // override default must-revalidate behavior
.header("content-length", Integer.toString(dataBuffer.writePosition())) .header("content-length", Integer.toString(dataBuffer.writePosition()))
.header(CONTENT_TYPE, "text/html; charset=" + getCharset().displayName()) .header(CONTENT_TYPE, "text/html; charset=" + getCharset().displayName())
.body(dataBuffer); .body(dataBuffer)
.done();
} }
protected String cacheControl() { protected String cacheControl() {

View file

@ -39,7 +39,9 @@ public class BasicAuthenticationHandler extends LoginAuthenticationHandler imple
} }
userProfile = new BaseUserProfile(); userProfile = new BaseUserProfile();
try { try {
authenticate(userProfile, tokens[0], tokens[1], httpRequest); if (authenticate(userProfile, tokens[0], tokens[1], httpRequest)) {
context.setAuthenticated(true);
}
context.getAttributes().put("userprofile", userProfile); context.getAttributes().put("userprofile", userProfile);
return; return;
} catch (Exception e) { } catch (Exception e) {

View file

@ -23,9 +23,11 @@ public class FormAuthenticationHandler extends LoginAuthenticationHandler implem
@Override @Override
public void handle(HttpRouterContext context) throws IOException { public void handle(HttpRouterContext context) throws IOException {
logger.log(Level.FINE, "request = " + context.getRequest());
UserProfile userProfile = context.getAttributes().get(UserProfile.class, "userprofile"); UserProfile userProfile = context.getAttributes().get(UserProfile.class, "userprofile");
if (userProfile != null && userProfile.getUserId() != null) { if (userProfile != null && userProfile.getUserId() != null) {
logger.log(Level.FINE, "user id already set: " + userProfile.getUserId()); logger.log(Level.FINE, "user id already set: " + userProfile.getUserId());
context.setAuthenticated(true);
return; return;
} }
if (context.isAuthenticated()) { if (context.isAuthenticated()) {
@ -34,29 +36,30 @@ public class FormAuthenticationHandler extends LoginAuthenticationHandler implem
} }
// always add an "anonymous" user profile with a null user ID // always add an "anonymous" user profile with a null user ID
userProfile = new BaseUserProfile(); userProfile = new BaseUserProfile();
context.getAttributes().put("userprofile", userProfile);
boolean isAuthenticated = false; boolean isAuthenticated = false;
try { try {
Parameter parameter = context.getRequest().getParameter(); Parameter parameter = context.getRequest().getParameter();
if (!parameter.containsKey(getUserParameterName(), Parameter.Domain.FORM)) { if (!parameter.containsKey(getUserParameterName(), Parameter.Domain.FORM)) {
logger.log(Level.WARNING, "usernameParameter not set, unable to authenticate"); logger.log(Level.WARNING, "username parameter not set, unable to authenticate");
prepareFormAuthentication(context); prepareFormAuthentication(context);
return; return;
} }
String username = parameter.getAsString(getUserParameterName(), Parameter.Domain.FORM); String username = parameter.getAsString(getUserParameterName(), Parameter.Domain.FORM);
if (!parameter.containsKey(getPasswordParameterName(), Parameter.Domain.FORM)) { if (!parameter.containsKey(getPasswordParameterName(), Parameter.Domain.FORM)) {
logger.log(Level.WARNING, "passwordParameter not set, unable to authenticate"); logger.log(Level.WARNING, "password parameter not set, unable to authenticate");
prepareFormAuthentication(context); prepareFormAuthentication(context);
return; return;
} }
String password = parameter.getAsString(getPasswordParameterName(), Parameter.Domain.FORM); String password = parameter.getAsString(getPasswordParameterName(), Parameter.Domain.FORM);
authenticate(userProfile, username, password, context.getRequest()); if (authenticate(userProfile, username, password, context.getRequest())) {
isAuthenticated = true; isAuthenticated = true;
}
} catch (ParameterException e) { } catch (ParameterException e) {
logger.log(Level.SEVERE, "parameter error"); logger.log(Level.SEVERE, "parameter error");
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.SEVERE, "authentication error"); logger.log(Level.SEVERE, "authentication error");
} finally { } finally {
context.getAttributes().put("userprofile", userProfile);
context.setAuthenticated(isAuthenticated); context.setAuthenticated(isAuthenticated);
if (!isAuthenticated) { if (!isAuthenticated) {
prepareFormAuthentication(context); prepareFormAuthentication(context);

View file

@ -2,6 +2,7 @@ package org.xbib.net.http.server.auth;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Objects;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.xbib.net.Authenticator; import org.xbib.net.Authenticator;
@ -26,12 +27,12 @@ public class LoginAuthenticationHandler implements HttpHandler {
private final SecurityRealm securityRealm; private final SecurityRealm securityRealm;
public LoginAuthenticationHandler(String userParameterName, public LoginAuthenticationHandler(String usernameParameterName,
String passwordParameterName, String passwordParameterName,
SecurityRealm securityRealm) { SecurityRealm securityRealm) {
this.userParameterName = userParameterName; this.userParameterName = Objects.requireNonNull(usernameParameterName, "username parameter must not be null");
this.passwordParameterName = passwordParameterName; this.passwordParameterName = Objects.requireNonNull(passwordParameterName, "password parameter must not be null");
this.securityRealm = securityRealm; this.securityRealm = Objects.requireNonNull(securityRealm, "security realm must not be null");
} }
public String getUserParameterName() { public String getUserParameterName() {
@ -49,7 +50,12 @@ public class LoginAuthenticationHandler implements HttpHandler {
@Override @Override
public void handle(HttpRouterContext context) throws IOException { public void handle(HttpRouterContext context) throws IOException {
UserProfile userProfile = context.getAttributes().get(UserProfile.class, "userprofile"); UserProfile userProfile = context.getAttributes().get(UserProfile.class, "userprofile");
if (userProfile != null && userProfile.getUserId() != null) { if (userProfile == null) {
logger.log(Level.FINE, "no user profile found in context");
return;
}
if (userProfile.getUserId() != null) {
logger.log(Level.FINE, "user id already set");
return; return;
} }
Parameter parameter = context.getRequest().getParameter(); Parameter parameter = context.getRequest().getParameter();
@ -59,8 +65,9 @@ public class LoginAuthenticationHandler implements HttpHandler {
try { try {
String username = parameter.getAsString(getUserParameterName(), Parameter.Domain.FORM); String username = parameter.getAsString(getUserParameterName(), Parameter.Domain.FORM);
String password = parameter.getAsString(getPasswordParameterName(), Parameter.Domain.FORM); String password = parameter.getAsString(getPasswordParameterName(), Parameter.Domain.FORM);
authenticate(userProfile, username, password, context.getRequest()); if (authenticate(userProfile, username, password, context.getRequest())) {
isAuthenticated = true; isAuthenticated = true;
}
} catch (ParameterException e) { } catch (ParameterException e) {
logger.log(Level.SEVERE, "parameter error"); logger.log(Level.SEVERE, "parameter error");
} catch (Exception e) { } catch (Exception e) {
@ -70,29 +77,33 @@ public class LoginAuthenticationHandler implements HttpHandler {
} }
} }
protected void authenticate(UserProfile userProfile, String username, String password, Request request) { protected boolean authenticate(UserProfile userProfile, String username, String password, Request request) {
if (username == null) { if (username == null) {
logger.log(Level.FINE, "no username given for check, doing nothing"); logger.log(Level.FINE, "no username given for check, doing nothing");
return; return false;
} }
if (password == null) { if (password == null) {
logger.log(Level.FINE, "no password given for check, doing nothing"); logger.log(Level.FINE, "no password given for check, doing nothing");
return; return false;
} }
Authenticator auth = securityRealm.getAuthenticator(); Authenticator auth = securityRealm.getAuthenticator();
Authenticator.Context authContext = new Authenticator.Context(username, password, request); Authenticator.Context authContext = new Authenticator.Context(username, password, request);
if (auth.authenticate(authContext)) { if (auth.authenticate(authContext)) {
logger.log(Level.FINE, "authenticated, augmenting user profile with " + authContext.getUsername());
userProfile.setUserId(authContext.getUsername()); userProfile.setUserId(authContext.getUsername());
UsersProvider.Context userContext = new UsersProvider.Context(username, null);
UserDetails userDetails = securityRealm.getUsersProvider().getUserDetails(userContext);
userProfile.setEffectiveUserId(userDetails.getEffectiveUserId());
userProfile.setName(userDetails.getName());
GroupsProvider.Context groupContext = new GroupsProvider.Context(username, null);
Collection<String> groups = securityRealm.getGroupsProvider().getGroups(groupContext);
for (String group : groups) {
userProfile.addRole(group);
}
logger.log(Level.FINE, "authentication success: userProfile = " + userProfile);
return true;
} }
UsersProvider.Context userContext = new UsersProvider.Context(username, null); logger.log(Level.FINE, "authentication failure");
UserDetails userDetails = securityRealm.getUsersProvider().getUserDetails(userContext); return false;
userProfile.setEffectiveUserId(userDetails.getEffectiveUserId());
userProfile.setName(userDetails.getName());
GroupsProvider.Context groupContext = new GroupsProvider.Context(username, null);
Collection<String> groups = securityRealm.getGroupsProvider().getGroups(groupContext);
for (String group : groups) {
userProfile.addRole(group);
}
logger.log(Level.FINE, "authenticate: userProfile = " + userProfile);
} }
} }

View file

@ -233,6 +233,9 @@ public class HtmlTemplateResource implements HttpServerResource {
private static String toOrigin(URL url) { private static String toOrigin(URL url) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (url == null) {
return sb.toString();
}
if (url.getPath() != null) { if (url.getPath() != null) {
sb.append(url.getPath()); sb.append(url.getPath());
} }
@ -242,7 +245,7 @@ public class HtmlTemplateResource implements HttpServerResource {
if (url.getFragment() != null) { if (url.getFragment() != null) {
sb.append('#').append(url.getFragment()); sb.append('#').append(url.getFragment());
} }
if (sb.length() == 0) { if (sb.isEmpty()) {
sb.append('/'); sb.append('/');
} }
return sb.toString(); return sb.toString();

View file

@ -53,9 +53,11 @@ public class GroovyFormAuthenticationHandler extends FormAuthenticationHandler {
String username = parameter.getAsString(getUserParameterName(), Parameter.Domain.FORM); String username = parameter.getAsString(getUserParameterName(), Parameter.Domain.FORM);
String password = parameter.getAsString(getPasswordParameterName(), Parameter.Domain.FORM); String password = parameter.getAsString(getPasswordParameterName(), Parameter.Domain.FORM);
logger.log(Level.FINE, "username and password found, ready for authentication"); logger.log(Level.FINE, "username and password found, ready for authentication");
authenticate(userProfile, username, password, context.getRequest()); if (authenticate(userProfile, username, password, context.getRequest())) {
logger.log(Level.FINE, "successful authentication"); context.setAuthenticated(true);
return; logger.log(Level.FINE, "successful authentication");
return;
}
} catch (ParameterException e) { } catch (ParameterException e) {
logger.log(Level.SEVERE, "parameter error"); logger.log(Level.SEVERE, "parameter error");
} catch (Exception e) { } catch (Exception e) {
@ -70,8 +72,8 @@ public class GroovyFormAuthenticationHandler extends FormAuthenticationHandler {
// We need a full path resolve against the server URL. // We need a full path resolve against the server URL.
logger.log(Level.FINE, "set new templatePath, login template = " + loginTemplate); logger.log(Level.FINE, "set new templatePath, login template = " + loginTemplate);
context.getAttributes().put("templatePath", loginTemplate); context.getAttributes().put("templatePath", loginTemplate);
URL loc = context.getContextURL().resolve(context.getRequest().getRequestURI()).normalize(); URL origin = context.getContextURL().resolve(context.getRequest().getRequestURI()).normalize();
logger.log(Level.FINE, "context URL = " + context.getContextURL() + " request URI = " + context.getRequest().getRequestURI() + " loc = " + loc); logger.log(Level.FINE, "context URL = " + context.getContextURL() + " request URI = " + context.getRequest().getRequestURI() + " origin = " + origin);
context.getAttributes().put("originalPath", loc.toExternalForm()); context.getAttributes().put("originalPath", origin.toExternalForm());
} }
} }