Skip to content

Commit

Permalink
chore: add custom entrypoint
Browse files Browse the repository at this point in the history
  • Loading branch information
andreibogus authored and borisrizov-zf committed Jun 4, 2024
1 parent 1394c1c commit d2d8a75
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,31 @@
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;

import java.util.Map;
import java.util.TreeMap;

import static org.eclipse.tractusx.managedidentitywallets.constant.StringPool.BPN_NOT_FOUND;

public class BpnValidator implements OAuth2TokenValidator<Jwt> {

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<String, Object> 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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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<String, String> 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<String, String> 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<String, String> entry = (Map.Entry) var3.next();
wwwAuthenticate.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
if (i != parameters.size() - 1) {
wwwAuthenticate.append(", ");
}
}
}

return wwwAuthenticate.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit d2d8a75

Please sign in to comment.