[New] Implemented Basic authentication for REST APIs

This commit is contained in:
Robert von Burg 2020-04-23 10:06:55 +02:00
parent 984f6bff41
commit 0481ecc90d
2 changed files with 57 additions and 16 deletions

View File

@ -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();

View File

@ -1,12 +1,12 @@
/*
* Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
*
*
* 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 <reto.breitenmoser@4trees.ch>
@ -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);
}
}
}