diff --git a/li.strolch.rest/src/main/java/li/strolch/rest/filters/AuthenticationRequestFilter.java b/li.strolch.rest/src/main/java/li/strolch/rest/filters/AuthenticationRequestFilter.java index caba15dd5..d8a9688ae 100644 --- a/li.strolch.rest/src/main/java/li/strolch/rest/filters/AuthenticationRequestFilter.java +++ b/li.strolch.rest/src/main/java/li/strolch/rest/filters/AuthenticationRequestFilter.java @@ -26,7 +26,8 @@ import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.core.*; import javax.ws.rs.ext.Provider; -import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -34,6 +35,7 @@ import java.util.Set; import li.strolch.exception.StrolchAccessDeniedException; import li.strolch.exception.StrolchNotAuthenticatedException; import li.strolch.privilege.model.Certificate; +import li.strolch.privilege.model.Usage; import li.strolch.rest.RestfulStrolchComponent; import li.strolch.rest.StrolchRestfulConstants; import li.strolch.rest.StrolchSessionHandler; @@ -103,7 +105,7 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter { } @Override - public void filter(ContainerRequestContext requestContext) throws IOException { + public void filter(ContainerRequestContext requestContext) { String remoteIp = getRemoteIp(this.request); logger.info("Remote IP: " + remoteIp + ": " + requestContext.getMethod() + " " + requestContext.getUriInfo() .getRequestUri()); @@ -152,8 +154,8 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter { */ protected Certificate validateSession(ContainerRequestContext requestContext, String remoteIp) { - String sessionId = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION); - if (StringHelper.isEmpty(sessionId)) { + String authorization = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION); + if (StringHelper.isEmpty(authorization)) { Cookie cookie = requestContext.getCookies().get(StrolchRestfulConstants.STROLCH_AUTHORIZATION); if (cookie == null) { @@ -166,7 +168,7 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter { return null; } - sessionId = cookie.getValue(); + String sessionId = cookie.getValue(); if (StringHelper.isEmpty(sessionId)) { logger.error("Authorization Cookie value missing on request to URL " + requestContext.getUriInfo() .getPath()); @@ -176,11 +178,34 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter { .build()); return null; } + + return validateCertificate(requestContext, sessionId, remoteIp); } - StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance() - .getComponent(StrolchSessionHandler.class); - Certificate certificate = sessionHandler.validate(sessionId, remoteIp); + authorization = authorization.trim(); + if (authorization.startsWith("Basic ")) { + return authenticateBasic(requestContext, authorization, remoteIp); + } + + return validateCertificate(requestContext, authorization, remoteIp); + } + + private Certificate authenticateBasic(ContainerRequestContext requestContext, String authorization, + String remoteIp) { + String basicAuth = authorization.substring("Basic ".length()); + basicAuth = new String(Base64.getDecoder().decode(basicAuth.getBytes()), StandardCharsets.UTF_8); + String[] parts = basicAuth.split(":"); + if (parts.length != 2) { + requestContext.abortWith( + Response.status(Response.Status.BAD_REQUEST).header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN) + .entity("Invalid Basic Authorization!") //$NON-NLS-1$ + .build()); + return null; + } + + logger.info("Performing basic auth for user " + parts[0] + "..."); + StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance().getSessionHandler(); + Certificate certificate = sessionHandler.authenticate(parts[0], parts[1].toCharArray(), remoteIp, Usage.SINGLE); requestContext.setProperty(STROLCH_CERTIFICATE, certificate); requestContext.setProperty(STROLCH_REQUEST_SOURCE, remoteIp); @@ -188,6 +213,15 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter { return certificate; } + private Certificate validateCertificate(ContainerRequestContext requestContext, String sessionId, String remoteIp) { + StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance().getSessionHandler(); + Certificate certificate = sessionHandler.validate(sessionId, remoteIp); + + requestContext.setProperty(STROLCH_CERTIFICATE, certificate); + requestContext.setProperty(STROLCH_REQUEST_SOURCE, remoteIp); + return certificate; + } + public static String getRemoteIp(HttpServletRequest request) { String remoteHost = request.getRemoteHost(); diff --git a/li.strolch.rest/src/main/java/li/strolch/rest/filters/AuthenticationResponseFilter.java b/li.strolch.rest/src/main/java/li/strolch/rest/filters/AuthenticationResponseFilter.java index 50eba7490..33c45729f 100644 --- a/li.strolch.rest/src/main/java/li/strolch/rest/filters/AuthenticationResponseFilter.java +++ b/li.strolch.rest/src/main/java/li/strolch/rest/filters/AuthenticationResponseFilter.java @@ -1,12 +1,12 @@ /* * Copyright 2015 Robert von Burg - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,15 +17,16 @@ package li.strolch.rest.filters; import static li.strolch.rest.StrolchRestfulConstants.STROLCH_CERTIFICATE; -import java.io.IOException; - import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; -import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.ext.Provider; +import java.io.IOException; import li.strolch.privilege.model.Certificate; +import li.strolch.rest.RestfulStrolchComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Reto Breitenmoser @@ -34,13 +35,19 @@ import li.strolch.privilege.model.Certificate; @Provider public class AuthenticationResponseFilter implements ContainerResponseFilter { + private static final Logger logger = LoggerFactory.getLogger(AuthenticationResponseFilter.class); + @Override public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException { Certificate cert = (Certificate) requestContext.getProperty(STROLCH_CERTIFICATE); - if (cert != null) { - responseContext.getHeaders().add(HttpHeaders.AUTHORIZATION, cert.getAuthToken()); + if (cert == null) + return; + + if (cert.getUsage().isSingle()) { + logger.info("Invalidating single usage certificate for " + cert.getUsername()); + RestfulStrolchComponent.getInstance().getSessionHandler().invalidate(cert); } } }