[Fix] Returning 401 if session is invalid, 403 for privilege

This commit is contained in:
Robert von Burg 2017-07-26 15:15:20 +02:00
parent ae1de1112d
commit c79f1d6ae6
8 changed files with 119 additions and 18 deletions

View File

@ -30,6 +30,7 @@ import li.strolch.agent.api.StrolchRealm;
import li.strolch.model.audit.AccessType;
import li.strolch.model.audit.Audit;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.base.NotAuthenticatedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.DefaultPrivilegeHandler;
import li.strolch.privilege.handler.EncryptionHandler;
@ -141,7 +142,7 @@ public class DefaultStrolchPrivilegeHandler extends StrolchComponent implements
}
@Override
public void isCertificateValid(Certificate certificate) throws PrivilegeException {
public void isCertificateValid(Certificate certificate) throws PrivilegeException, NotAuthenticatedException {
assertStarted();
this.privilegeHandler.isCertificateValid(certificate);
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2013 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.exception;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class StrolchNotAuthenticatedException extends StrolchException {
private static final long serialVersionUID = 1L;
public StrolchNotAuthenticatedException(String message) {
super(message);
}
public StrolchNotAuthenticatedException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2013 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.privilege.base;
/**
* Exception thrown if user is not authenticated, i.e. certificate is not valid anymore, etc.
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class NotAuthenticatedException extends PrivilegeException {
private static final long serialVersionUID = 1L;
/**
* @param msg
* detail on why and where access was denied
*/
public NotAuthenticatedException(String msg) {
super(msg);
}
/**
* @param msg
* detail on why and where access was denied
* @param e
* root exception
*/
public NotAuthenticatedException(String msg, Exception e) {
super(msg, e);
}
}

View File

@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.InvalidCredentialsException;
import li.strolch.privilege.base.NotAuthenticatedException;
import li.strolch.privilege.base.PrivilegeConflictResolution;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
@ -1389,7 +1390,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
}
@Override
public void isCertificateValid(Certificate certificate) {
public void isCertificateValid(Certificate certificate) throws PrivilegeException, NotAuthenticatedException {
// certificate must not be null
if (certificate == null)
@ -1399,7 +1400,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
PrivilegeContext privilegeContext = this.privilegeContextMap.get(certificate.getSessionId());
if (privilegeContext == null) {
String msg = MessageFormat.format("There is no session information for {0}", certificate); //$NON-NLS-1$
throw new AccessDeniedException(msg);
throw new NotAuthenticatedException(msg);
}
// validate certificate has not been tampered with
@ -1416,7 +1417,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
ZoneId.systemDefault());
if (dateTime.plusHours(1).isBefore(LocalDateTime.now())) {
invalidateSession(sessionCertificate);
throw new PrivilegeException("Certificate has already expired!"); //$NON-NLS-1$
throw new NotAuthenticatedException("Certificate has already expired!"); //$NON-NLS-1$
}
}
@ -1433,7 +1434,8 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
}
@Override
public PrivilegeContext getPrivilegeContext(Certificate certificate) throws PrivilegeException {
public PrivilegeContext getPrivilegeContext(Certificate certificate)
throws PrivilegeException, NotAuthenticatedException {
// first validate certificate
isCertificateValid(certificate);

View File

@ -20,6 +20,7 @@ import java.util.Locale;
import java.util.Map;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.NotAuthenticatedException;
import li.strolch.privilege.base.PrivilegeConflictResolution;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
@ -603,8 +604,10 @@ public interface PrivilegeHandler {
*
* @throws PrivilegeException
* if there is anything wrong with this certificate
* @throws NotAuthenticatedException
* if the certificate has expired
*/
public void isCertificateValid(Certificate certificate) throws PrivilegeException;
public void isCertificateValid(Certificate certificate) throws PrivilegeException, NotAuthenticatedException;
/**
* Returns the {@link PrivilegeContext} for the given {@link Certificate}. The {@link PrivilegeContext} is an
@ -617,8 +620,11 @@ public interface PrivilegeHandler {
*
* @throws PrivilegeException
* if there is a configuration error or the {@link Certificate} is invalid
* @throws NotAuthenticatedException
* if the certificate has expired
*/
public PrivilegeContext getPrivilegeContext(Certificate certificate) throws PrivilegeException;
public PrivilegeContext getPrivilegeContext(Certificate certificate)
throws PrivilegeException, NotAuthenticatedException;
/**
* Validate that the given password meets certain requirements. What these requirements are is a decision made by

View File

@ -40,7 +40,7 @@ import org.slf4j.LoggerFactory;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchComponent;
import li.strolch.exception.StrolchException;
import li.strolch.exception.StrolchNotAuthenticatedException;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
@ -152,22 +152,26 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
}
@Override
public Certificate validate(String authToken) {
public Certificate validate(String authToken) throws StrolchNotAuthenticatedException {
DBC.PRE.assertNotEmpty("authToken must be set!", authToken); //$NON-NLS-1$
Certificate certificate = this.certificateMap.get(authToken);
if (certificate == null)
throw new StrolchException(MessageFormat.format("No certificate exists for sessionId {0}", authToken)); //$NON-NLS-1$
throw new StrolchNotAuthenticatedException(
MessageFormat.format("No certificate exists for sessionId {0}", authToken)); //$NON-NLS-1$
return validate(certificate);
}
@Override
public Certificate validate(Certificate certificate) {
this.privilegeHandler.isCertificateValid(certificate);
certificate.setLastAccess(new Date());
return certificate;
public Certificate validate(Certificate certificate) throws StrolchNotAuthenticatedException {
try {
this.privilegeHandler.isCertificateValid(certificate);
certificate.setLastAccess(new Date());
return certificate;
} catch (PrivilegeException e) {
throw new StrolchNotAuthenticatedException(e.getMessage(), e);
}
}
@Override

View File

@ -18,6 +18,7 @@ package li.strolch.rest;
import java.util.List;
import java.util.Locale;
import li.strolch.exception.StrolchNotAuthenticatedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.Usage;
@ -30,9 +31,9 @@ public interface StrolchSessionHandler {
public Certificate authenticate(String username, char[] password);
public Certificate validate(String authToken);
public Certificate validate(String authToken) throws StrolchNotAuthenticatedException;
public Certificate validate(Certificate certificate);
public Certificate validate(Certificate certificate) throws StrolchNotAuthenticatedException;
public void invalidate(Certificate certificate);

View File

@ -35,6 +35,8 @@ import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import li.strolch.exception.StrolchAccessDeniedException;
import li.strolch.exception.StrolchNotAuthenticatedException;
import li.strolch.privilege.model.Certificate;
import li.strolch.rest.RestfulStrolchComponent;
import li.strolch.rest.StrolchRestfulConstants;
@ -46,7 +48,7 @@ import li.strolch.utils.helper.StringHelper;
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@Provider
@Priority(Priorities.AUTHENTICATION)
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationRequestFilter implements ContainerRequestFilter {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationRequestFilter.class);
@ -105,6 +107,15 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter {
.getComponent(StrolchSessionHandler.class);
Certificate certificate = sessionHandler.validate(sessionId);
requestContext.setProperty(STROLCH_CERTIFICATE, certificate);
} catch (StrolchNotAuthenticatedException e) {
logger.error(e.getMessage());
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
.entity("User is not authenticated!").build()); //$NON-NLS-1$
} catch (StrolchAccessDeniedException e) {
logger.error(e.getMessage());
requestContext.abortWith(Response.status(Response.Status.FORBIDDEN)
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN).entity("User is not authorized!").build()); //$NON-NLS-1$
} catch (Exception e) {
logger.error(e.getMessage());
requestContext.abortWith(