Untitled

mail@pastecode.io avatar
unknown
plain_text
4 months ago
16 kB
2
Indexable
package com.kosign.webill.config;

import com.kosign.webill.components.CustomJwtAuthenticationConverter;
import com.kosign.webill.components.security.AccessDeniedHandler;
import com.kosign.webill.components.security.UnauthorizedHandler;
import com.kosign.webill.properties.RsaKeysProperties;
import com.kosign.webill.service.auth.ClientAuthServiceImpl;
import com.kosign.webill.service.auth.PayerAuthServiceImpl;
import com.kosign.webill.service.auth.UserAuthServiceImpl;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;

import java.util.List;
import java.util.stream.Collectors;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig {
    private final PasswordEncoder passwordEncoder;
    private final UnauthorizedHandler unauthorizedHandler;
    private final AccessDeniedHandler accessDeniedHandler;
    private final RsaKeysProperties rsaKeysProperties;
    private final CustomJwtAuthenticationConverter customJwtAuthenticationConverter;
    private final SessionFilter sessionFilter;

    @Primary
    @Bean("userAuthProvider")
    public AuthenticationManager userAuthProvider(UserAuthServiceImpl userDetailsService) {
        var authProvider = new DaoAuthenticationProvider();
        authProvider.setPasswordEncoder(passwordEncoder);
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setHideUserNotFoundExceptions(false);
        return new ProviderManager(authProvider);
    }

    @Bean("clientAuthProvider")
    public AuthenticationManager clientAuthProvider(ClientAuthServiceImpl clientAuthServiceImpl) {
        var clientProvider = new DaoAuthenticationProvider();
        clientProvider.setPasswordEncoder(passwordEncoder);
        clientProvider.setUserDetailsService(clientAuthServiceImpl);
        clientProvider.setHideUserNotFoundExceptions(false);
        return new ProviderManager(clientProvider);
    }

    @Bean("payerAuthProvider")
    public AuthenticationManager payerAuthProvider(PayerAuthServiceImpl payerAuthServiceImpl) {
        var payerProvider = new DaoAuthenticationProvider();
        payerProvider.setPasswordEncoder(passwordEncoder);
        payerProvider.setUserDetailsService(payerAuthServiceImpl);
        payerProvider.setHideUserNotFoundExceptions(false);
        return new ProviderManager(payerProvider);
    }

//    @Bean
//    @Order(1)
//    public WebSecurityCustomizer webSecurityCustomizer() {
//        return (web) -> web.ignoring().requestMatchers("/api/wb/v1/auth/login", "/test", "/api/bo/wb/v1/auth/login");
//    }

    /**
     * List of APIs that require authentication
     */
    public static final List<String> AUTH_APIS = List.of(
            "/api/wbi/client/v1/auth/token",
            "/api/wb/v1/auth/otp/**",
            "/api/client/wb/v1/token",
            "/api/wb/v1/auth/login",
            "/api/wbi/mb/payer/v1/auth/**",
            "/api/wbi/mb/payer/v1/otps/**",
            "/api/bo/wb/v1/auth/login",
            "/api/wb/v1/otp/send",
            "/api/wb/v1/otp/send-reset",
            "/api/wb/v1/otp/verify",
            "/api/wb/v1/common/codes",
            "/api/wb/v1/auth/signup",
            "/api/wb/v1/auth/reset-password",
            "/websocket/**",
            "/api/wb/v1/bills/{bill_id}/information",
            "/api/wb/v1/quick-bills/{bill_id}/information",
            "/api/v1/image/**",
            "/images/**",
            "/api/wb/v1/landing-page/get-in-touch",
            "/api/wb/v1/bills/slug/{slug_id}",
            "/api/wb/v1/landing-page/get-in-touch",
            "/api/cm/v1/service-plans",
            "/api/cm/v1/otp/**",
            "/api/cm/v1/auth/**",
            "/api/cm/v1/common/codes"
    );

    /**
     * List of public APIs
     */
    public static final List<String> PUBLIC_APIs = List.of(
            "/api/wb/v1/apartments",
            "/api/wb/v1/utility/**",
            "/api/wb/v1/wabooks/items",
            "/api/wb/v1/service-plans/check-subscribe",
            "/api/wb/v1/employees/permissions",
            "/api/bo/wb/v1/employees/permissions",
            "/api/bo/wb/v1/payments/**",
            "/api/wb/v1/bill/**",
            "/api/wb/v1/profile/**",
            "/api/wb/v1/roles",
            "/api/wb/v1/settings/e-filings/**",
            "/api/wb/v1/settings/user-settings/**",
            "/api/wb/v1/profile/**",
            "/api/wb/v1/groups",
            "/api/wb/v1/groups/**",
            "/api/wb/v1/permissions",
            "/api/wb/v1/notifications",
            "/api/wb/v1/files/upload-image",
            "/api/wb/v1/notifications/**",
            "/api/wb/v1/quick-bills/**",
            "/api/wb/v1/bills/receipts",
            "/api/wb/v1/bills/invoices",
            "/api/wb/v1/exchange-rate/**",
            "/api/wb/v1/reminders/templates",
            "/api/mb/v1/dashboard",
            "/api/cm/v1/settings/**"
    );

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{

//        for (var m : securityProperties.privateApis()) {
//            http.authorizeHttpRequests(authorize ->
//                    authorize.requestMatchers(m.patterns().toArray(String[]::new))
//                            .hasAnyAuthority(StringUtils.tokenizeToStringArray(m.roles(), ",")));
//        }

        return http
                .csrf(AbstractHttpConfigurer::disable)
                .cors(httpSecurityCorsConfigurer ->
                        httpSecurityCorsConfigurer
                                .configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues())
                )
                .authorizeHttpRequests(authorize ->
                        authorize
                                .requestMatchers(
                                    "/api/wbi/client/v1/auth/token",
                                    "/api/wb/v1/auth/otp/**",
                                    "/api/client/wb/v1/token",
                                    "/api/wb/v1/auth/login",
                                    "/api/wbi/mb/payer/v1/auth/**",
                                    "/api/wbi/mb/payer/v1/otps/**",
                                    "/api/bo/wb/v1/auth/login",
                                    "/api/wb/v1/otp/send",
                                    "/api/wb/v1/otp/send-reset",
                                    "/api/wb/v1/otp/verify",
                                    "/api/wb/v1/common/codes",
                                    "/api/wb/v1/auth/signup",
                                    "/api/wb/v1/auth/reset-password",
                                    "/websocket/**",
                                    "/api/wb/v1/bills/{bill_id}/information",
                                    "/api/wb/v1/quick-bills/{bill_id}/information",
                                    "/api/v1/image/**",
                                    "/images/**",
                                    "/api/wb/v1/landing-page/get-in-touch",
                                    "/api/wb/v1/bills/slug/{slug_id}",
                                    "/api/wb/v1/landing-page/get-in-touch",
                                    "/api/cm/v1/service-plans",
                                    "/api/cm/v1/otp/**",
                                    "/api/cm/v1/auth/**",
                                    "/api/cm/v1/common/codes"
                                ).permitAll()

                                .requestMatchers(
                                    "/api/wb/v1/apartments",
                                    "/api/wb/v1/utility/**",
                                    "/api/wb/v1/wabooks/items",
                                    "/api/wb/v1/service-plans/check-subscribe",
                                    "/api/wb/v1/employees/permissions",
                                    "/api/bo/wb/v1/employees/permissions",
                                    "/api/bo/wb/v1/payments/**",
                                    "/api/wb/v1/bill/**",
                                    "/api/wb/v1/profile/**",
                                    "/api/wb/v1/roles",
                                    "/api/wb/v1/settings/e-filings/**",
                                    "/api/wb/v1/settings/user-settings/**",
                                    "/api/wb/v1/profile/**",
                                    "/api/wb/v1/groups",
                                    "/api/wb/v1/groups/**",
                                    "/api/wb/v1/permissions",
                                    "/api/wb/v1/notifications",
                                    "/api/wb/v1/files/upload-image",
                                    "/api/wb/v1/notifications/**",
                                    "/api/wb/v1/quick-bills/**",
                                    "/api/wb/v1/bills/receipts",
                                    "/api/wb/v1/bills/invoices",
                                    "/api/wb/v1/exchange-rate/**",
                                    "/api/wb/v1/reminders/templates",
                                    "/api/mb/v1/dashboard",
                                    "/api/cm/v1/settings/**"
                                ).authenticated()

                                .requestMatchers(HttpMethod.GET,"/api/wb/v1/payers/**", "/api/wb/v1/bills").hasAnyAuthority("BILLER", "CUSTOMER:view", "BILLING:view")
                                .requestMatchers(HttpMethod.DELETE,"/api/wb/v1/payers/**").hasAnyAuthority("BILLER", "CUSTOMER:delete")
                                .requestMatchers(HttpMethod.DELETE,"/api/wb/v1/payers/upload").hasAnyAuthority("BILLER", "CUSTOMER:upload")
                                .requestMatchers(HttpMethod.DELETE,"/api/wb/v1/payers/upload").hasAnyAuthority("BILLER", "CUSTOMER:c_group")
                                .requestMatchers("/api/wb/v1/payers/**").hasAnyAuthority("BILLER", "CUSTOMER:edit")

                                .requestMatchers(HttpMethod.GET, "/api/wb/v1/bills/**").hasAnyAuthority("BILLER", "BILLING:view")
                                .requestMatchers(HttpMethod.POST, "/api/wb/v1/bills/**").hasAnyAuthority("BILLER", "BILLING:create")
                                .requestMatchers(HttpMethod.PATCH, "/api/wb/v1/bills/**").hasAnyAuthority("BILLER", "BILLING:edit")
                                .requestMatchers(HttpMethod.DELETE, "/api/wb/v1/bills/**").hasAnyAuthority("BILLER", "BILLING:delete")
                                . requestMatchers(HttpMethod.GET, "/api/wb/v1/payment-history/**").hasAnyAuthority("BILLER", "PAYMENT:view", "BILLING:view")
                                . requestMatchers(HttpMethod.GET, "/api/wb/v1/payments/**").hasAnyAuthority("BILLER", "PAYMENT:view", "BILLING:view")

                                .requestMatchers(HttpMethod.GET, "/api/wb/v1/quick-bills/**").hasAnyAuthority("BILLER", "QUICKBILL:view")
                                .requestMatchers(HttpMethod.POST, "/api/wb/v1/quick-bills/**").hasAnyAuthority("BILLER", "QUICKBILL:create")
                                .requestMatchers(HttpMethod.PATCH, "/api/wb/v1/quick-bills/**").hasAnyAuthority("BILLER", "QUICKBILL:edit")
                                .requestMatchers(HttpMethod.DELETE, "/api/wb/v1/quick-bills/**").hasAnyAuthority("BILLER", "QUICKBILL:delete")

                                .requestMatchers(HttpMethod.GET, "/api/bo/wb/v1/billers/**").hasAnyAuthority("ADMIN", "BILLER_ADM:view")
                                .requestMatchers(HttpMethod.PUT, "/api/bo/wb/v1/billers/**").hasAnyAuthority("ADMIN", "BILLER_ADM:biller", "BILLER_ADM:trust_acct")

                                .requestMatchers(HttpMethod.GET, "/api/bo/wb/v1/cs-activity").hasAnyAuthority("ADMIN", "DASH_ADM:view")


                                .requestMatchers("/api/wb/v1/payments/**").hasAnyAuthority("BILLER", "PAYMENT:view")

                                .requestMatchers("/api/wb/v1/reports/**").hasAnyAuthority("BILLER", "REPORT:view")

                                .requestMatchers("/api/wb/**").hasAnyAuthority("BILLER","ADMIN")
                                .requestMatchers("/api/client/**").hasAuthority("CLIENT")
                                .requestMatchers("/api/bo/**").hasAuthority("ADMIN")
                                .requestMatchers("/api/wbi/mb/**").hasAuthority("PAYER")
                                .requestMatchers("/api/wbi/**").hasAuthority("WBI_CLIENT")
                                .anyRequest()
                                .authenticated()
                )
                .exceptionHandling(exceptionHandling ->
                        exceptionHandling
                                .accessDeniedHandler(accessDeniedHandler)
                                .authenticationEntryPoint(unauthorizedHandler)
                )
                .sessionManagement(sessionManagement ->
                        sessionManagement
                                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .oauth2ResourceServer(oauth2 -> oauth2
                        .authenticationEntryPoint(unauthorizedHandler)
                        .accessDeniedHandler(accessDeniedHandler)
                        .jwt(jwtConfigurer -> jwtConfigurer
                                .jwtAuthenticationConverter(customJwtAuthenticationConverter)
                        )
                )
                .addFilterAfter(
                        sessionFilter,
                        BearerTokenAuthenticationFilter.class
                )
                .build();
    }

    @Bean
    JwtDecoder jwtDecoder(){
        return NimbusJwtDecoder.withPublicKey(rsaKeysProperties.publicKey()).build();
    }

    @Bean
    JwtEncoder jwtEncoder() {
        JWK jwk= new RSAKey.Builder(rsaKeysProperties.publicKey()).privateKey(rsaKeysProperties.privateKey()).build();
        JWKSource<SecurityContext> jwkSource= new ImmutableJWKSet<>(new JWKSet(jwk));
        return new NimbusJwtEncoder(jwkSource);
    }

//    @Bean
//    public JWKSet jwkSet(){
//        var rsaKey= new RSAKey.Builder(rsaKeysProperties.publicKey())
//                .privateKey(rsaKeysProperties.privateKey())
//
//                .keyUse(KeyUse.SIGNATURE)
//                .algorithm(JWSAlgorithm.RS256)
//                .build();
//        return new JWKSet(rsaKey);
//    }

}
Leave a Comment