// Path: spring/spring-security/src/main/java/org/juiser/spring/security/core/ForwardedUserAuthentication.java
// public class ForwardedUserAuthentication implements Authentication {
// 
//     private final UserDetails details;
// 
//     public ForwardedUserAuthentication(UserDetails details) {
//         Assert.notNull(details, "details argument cannot be null.");
//         this.details = details;
//     }
// 
//     @SuppressWarnings("unchecked")
//     @Override
//     public Collection<? extends GrantedAuthority> getAuthorities() {
//         return details.getAuthorities();
//     }
// 
//     @Override
//     public Object getCredentials() {
//         return null;
//     }
// 
//     @Override
//     public Object getDetails() {
//         return details;
//     }
// 
//     @Override
//     public Object getPrincipal() {
//         return details;
//     }
// 
//     @Override
//     public boolean isAuthenticated() {
//         return true;
//     }
// 
//     @Override
//     public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
//         throw new IllegalArgumentException(getClass().getName() + " instances are immutable.");
//     }
// 
//     @Override
//     public String getName() {
//         return details.getUsername();
//     }
// }


import io.jsonwebtoken.JwtException;
import org.juiser.spring.security.core.ForwardedUserAuthentication;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.function.Function;
    public boolean supports(Class<?> authentication) {
        return HeaderAuthenticationToken.class.isAssignableFrom(authentication);
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        HeaderAuthenticationToken token = (HeaderAuthenticationToken) authentication;

        Object creds = token.getCredentials();
        if (!(creds instanceof String)) {
            throw new BadCredentialsException("HeaderAuthenticationToken credentials must be a String.");
        }

        String value = (String) creds;
        if (!StringUtils.hasText(value)) {
            throw new BadCredentialsException("HeaderAuthenticationToken credentials String cannot be null or empty.");
        }

        UserDetails details;
        try {
            details = converter.apply(value);
        } catch (JwtException e) {
            String msg = "Invalid or unsupported request header JWT: " + e.getMessage();
            throw new BadCredentialsException(msg, e);
        } catch (Exception e) {
            String msg = "Unexpected exception during authentication header parsing: " + e.getMessage();
            throw new InternalAuthenticationServiceException(msg, e);
        }

// Path: spring/spring-security/src/main/java/org/juiser/spring/security/core/ForwardedUserAuthentication.java
// public class ForwardedUserAuthentication implements Authentication {
// 
//     private final UserDetails details;
// 
//     public ForwardedUserAuthentication(UserDetails details) {
//         Assert.notNull(details, "details argument cannot be null.");
//         this.details = details;
//     }
// 
//     @SuppressWarnings("unchecked")
//     @Override
//     public Collection<? extends GrantedAuthority> getAuthorities() {
//         return details.getAuthorities();
//     }
// 
//     @Override
//     public Object getCredentials() {
//         return null;
//     }
// 
//     @Override
//     public Object getDetails() {
//         return details;
//     }
// 
//     @Override
//     public Object getPrincipal() {
//         return details;
//     }
// 
//     @Override
//     public boolean isAuthenticated() {
//         return true;
//     }
// 
//     @Override
//     public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
//         throw new IllegalArgumentException(getClass().getName() + " instances are immutable.");
//     }
// 
//     @Override
//     public String getName() {
//         return details.getUsername();
//     }
// }


// Path: spring/spring-security/src/main/java/org/juiser/spring/security/authentication/HeaderAuthenticationProvider.java
import io.jsonwebtoken.JwtException;
import org.juiser.spring.security.core.ForwardedUserAuthentication;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.util.function.Function;

    public boolean supports(Class<?> authentication) {
        return HeaderAuthenticationToken.class.isAssignableFrom(authentication);
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        HeaderAuthenticationToken token = (HeaderAuthenticationToken) authentication;

        Object creds = token.getCredentials();
        if (!(creds instanceof String)) {
            throw new BadCredentialsException("HeaderAuthenticationToken credentials must be a String.");
        }

        String value = (String) creds;
        if (!StringUtils.hasText(value)) {
            throw new BadCredentialsException("HeaderAuthenticationToken credentials String cannot be null or empty.");
        }

        UserDetails details;
        try {
            details = converter.apply(value);
        } catch (JwtException e) {
            String msg = "Invalid or unsupported request header JWT: " + e.getMessage();
            throw new BadCredentialsException(msg, e);
        } catch (Exception e) {
            String msg = "Unexpected exception during authentication header parsing: " + e.getMessage();
            throw new InternalAuthenticationServiceException(msg, e);
        }

        return new ForwardedUserAuthentication(details);