io.inverno.mod.security.http.AccessControlInterceptor Maven / Gradle / Ivy
Show all versions of inverno-security-http Show documentation
/*
* Copyright 2022 Jeremy Kuhn
*
* 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 io.inverno.mod.security.http;
import io.inverno.mod.http.base.ForbiddenException;
import io.inverno.mod.http.base.UnauthorizedException;
import io.inverno.mod.http.server.Exchange;
import io.inverno.mod.http.server.ExchangeInterceptor;
import io.inverno.mod.security.accesscontrol.AccessController;
import io.inverno.mod.security.authentication.Authentication;
import io.inverno.mod.security.http.context.SecurityContext;
import io.inverno.mod.security.identity.Identity;
import java.util.function.Function;
import reactor.core.publisher.Mono;
/**
*
* An access control interceptor verifies that the access to a resource is authorized.
*
*
*
* This interceptor must be executed after the {@link SecurityInterceptor} once the {@link SecurityContext} has been created. It is basically used to verify that the requester has access to
* the resource being intercepted based on the security context and more specifically the authentication, the identity and the access controller.
*
*
* @author Jeremy Kuhn
* @since 1.5
*
* @param the identity type
* @param the access controller type
* @param the security context type
* @param the exchange type
*/
public class AccessControlInterceptor, D extends Exchange> implements ExchangeInterceptor {
/**
* The access verifier.
*/
private final Function, Mono> accessVerifier;
/**
*
* Creates an access control interceptor with the specified access verifier.
*
*
* @param accessVerifier an access verifier
*/
private AccessControlInterceptor(Function, Mono> accessVerifier) {
this.accessVerifier = accessVerifier;
}
/**
*
* Returns an access control interceptor that verifies the requester is anonymous (i.e. not authenticated).
*
*
* @param the identity type
* @param the access controller type
* @param the security context type
* @param the exchange type
*
* @return an access control interceptor
*/
public static , D extends Exchange> AccessControlInterceptor anonymous() {
return new AccessControlInterceptor<>(context -> Mono.fromSupplier(() -> {
Authentication authentication = context.getAuthentication();
return authentication.isAuthenticated();
}));
}
/**
*
* Returns an access control interceptor that verifies the requester is authenticated.
*
*
* @param the identity type
* @param the access controller type
* @param the security context type
* @param the exchange type
*
* @return an access control interceptor
*/
public static , D extends Exchange> AccessControlInterceptor authenticated() {
return new AccessControlInterceptor<>(context -> Mono.fromSupplier(() -> {
Authentication authentication = context.getAuthentication();
if(!authentication.isAuthenticated()) {
throw authentication.getCause()
.map(UnauthorizedException::new)
.orElseGet(() -> new UnauthorizedException());
}
return true;
}));
}
/**
*
* Returns an access control interceptor that uses the specified access verifier to verify access.
*
*
*
* The access verifier shall return false to deny the access to the resource resulting in a {@link ForbiddenException} being thrown by the interceptor but it can also throw an
* {@link UnauthorizedException} or a {@link ForbiddenException} directly to get a different behaviour or provide more details about the error (e.g. a message).
*
*
* @param the identity type
* @param the access controller type
* @param the security context type
* @param the exchange type
* @param accessVerifier an access verifier
*
* @return an access control interceptor
*/
public static , D extends Exchange> AccessControlInterceptor verify(Function, Mono> accessVerifier) {
return new AccessControlInterceptor<>(accessVerifier);
}
@Override
public Mono extends D> intercept(D exchange) {
return this.accessVerifier.apply(exchange.context()).map(granted -> {
if(!granted) {
throw new ForbiddenException("Access denied");
}
return exchange;
});
}
}