All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.inverno.mod.security.http.AccessControlInterceptor Maven / Gradle / Ivy

The newest version!
/*
 * 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 intercept(D exchange) { return this.accessVerifier.apply(exchange.context()).map(granted -> { if(!granted) { throw new ForbiddenException("Access denied"); } return exchange; }); } }