From d2d8a75a23b91fab96fe3b21a7b40cdcf1f79c5a Mon Sep 17 00:00:00 2001 From: andreibogus Date: Mon, 8 Apr 2024 14:15:21 +0200 Subject: [PATCH] chore: add custom entrypoint --- .../config/BpnValidator.java | 15 ++- .../CustomAuthenticationEntryPoint.java | 104 ++++++++++++++++++ .../config/security/SecurityConfig.java | 3 +- 3 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/CustomAuthenticationEntryPoint.java diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/BpnValidator.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/BpnValidator.java index 1e21218a7..314ca0150 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/BpnValidator.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/BpnValidator.java @@ -22,8 +22,8 @@ package org.eclipse.tractusx.managedidentitywallets.config; import org.eclipse.tractusx.managedidentitywallets.constant.StringPool; -import org.eclipse.tractusx.managedidentitywallets.exception.ForbiddenException; -import org.eclipse.tractusx.managedidentitywallets.utils.Validate; +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.core.OAuth2ErrorCodes; import org.springframework.security.oauth2.core.OAuth2TokenValidator; import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; import org.springframework.security.oauth2.jwt.Jwt; @@ -31,15 +31,22 @@ import java.util.Map; import java.util.TreeMap; +import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.BPN_NOT_FOUND; + public class BpnValidator implements OAuth2TokenValidator { + OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, BPN_NOT_FOUND, null); + @Override public OAuth2TokenValidatorResult validate(Jwt jwt) { //this will misbehave if we have more then one claims with different case // ie. BPN=123456 and bpn=789456 Map claims = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); claims.putAll(jwt.getClaims()); - Validate.isFalse(claims.containsKey(StringPool.BPN)).launch(new ForbiddenException("Invalid token, BPN not found")); - return OAuth2TokenValidatorResult.success(); + if (claims.containsKey(StringPool.BPN)) { + return OAuth2TokenValidatorResult.success(); + } else { + return OAuth2TokenValidatorResult.failure(error); + } } } diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/CustomAuthenticationEntryPoint.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/CustomAuthenticationEntryPoint.java new file mode 100644 index 000000000..a9153dfd1 --- /dev/null +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/CustomAuthenticationEntryPoint.java @@ -0,0 +1,104 @@ +/* + * ******************************************************************************* + * Copyright (c) 2021,2024 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + * ****************************************************************************** + */ + +package org.eclipse.tractusx.managedidentitywallets.config.security; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.Setter; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2Error; +import org.springframework.security.oauth2.server.resource.BearerTokenError; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.util.StringUtils; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.BPN_NOT_FOUND; + +@Setter +public final class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { + + private String realmName; + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) { + HttpStatus status = HttpStatus.UNAUTHORIZED; + Map parameters = new LinkedHashMap(); + + if (this.realmName != null) { + parameters.put("realm", this.realmName); + } + + if (authException instanceof OAuth2AuthenticationException) { + OAuth2Error error = ((OAuth2AuthenticationException) authException).getError(); + parameters.put("error", error.getErrorCode()); + if (StringUtils.hasText(error.getDescription())) { + parameters.put("error_description", error.getDescription()); + } + + if (StringUtils.hasText(error.getUri())) { + parameters.put("error_uri", error.getUri()); + } + + if (error instanceof BearerTokenError) { + BearerTokenError bearerTokenError = (BearerTokenError) error; + if (StringUtils.hasText(bearerTokenError.getScope())) { + parameters.put("scope", bearerTokenError.getScope()); + } + + status = ((BearerTokenError) error).getHttpStatus(); + } + } + + if (authException.getMessage().contains(BPN_NOT_FOUND)) { + status = HttpStatus.FORBIDDEN; + } + + String wwwAuthenticate = computeWWWAuthenticateHeaderValue(parameters); + response.addHeader("WWW-Authenticate", wwwAuthenticate); + response.setStatus(status.value()); + } + + private static String computeWWWAuthenticateHeaderValue(Map parameters) { + StringBuilder wwwAuthenticate = new StringBuilder(); + wwwAuthenticate.append("Bearer"); + if (!parameters.isEmpty()) { + wwwAuthenticate.append(" "); + int i = 0; + + for (Iterator var3 = parameters.entrySet().iterator(); var3.hasNext(); ++i) { + Map.Entry entry = (Map.Entry) var3.next(); + wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\""); + if (i != parameters.size() - 1) { + wwwAuthenticate.append(", "); + } + } + } + + return wwwAuthenticate.toString(); + } + +} diff --git a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java index 8ac66da94..54c2caa7c 100644 --- a/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java +++ b/src/main/java/org/eclipse/tractusx/managedidentitywallets/config/security/SecurityConfig.java @@ -128,7 +128,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { //error .requestMatchers(new AntPathRequestMatcher("/error")).permitAll() ).oauth2ResourceServer(resourceServer -> resourceServer.jwt(jwt -> - jwt.jwtAuthenticationConverter(new CustomAuthenticationConverter(securityConfigProperties.clientId())))) + jwt.jwtAuthenticationConverter(new CustomAuthenticationConverter(securityConfigProperties.clientId()))) + .authenticationEntryPoint(new CustomAuthenticationEntryPoint())) .addFilterAfter(new PresentationIatpFilter(validationService), BasicAuthenticationFilter.class); return http.build();