Untitled
unknown
plain_text
a year ago
10 kB
6
Indexable
package com.kotak.collection.reporting.filter; import com.kotak.collection.reporting.client.TokenRefreshAuthClient; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.http.ResponseEntity; import org.springframework.web.filter.GenericFilterBean; import org.springframework.web.util.WebUtils; /** The type Refresh access token filter. */ @Configuration @Log4j2 public class RefreshAccessTokenFilter extends GenericFilterBean { @Value("${httpOnly.cookie.key}") private String cookieKey; @Autowired private TokenRefreshAuthClient tokenRefreshAuthClient; /* Custom filter to return same access token if it is found valid else continue the request */ @Override public void doFilter( final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { try { chain.doFilter(request, response); switch (((HttpServletResponse) response).getStatus()) { case 401: { String token = WebUtils.getCookie((HttpServletRequest) request, cookieKey).getValue(); ResponseEntity refreshTokenResponse = tokenRefreshAuthClient.refreshAccessToken(cookieKey, token); HttpServletResponse finalResponse = (HttpServletResponse) response; int status = refreshTokenResponse.getStatusCode().is2xxSuccessful() ? finalResponse.getStatus() : 401; finalResponse.setStatus(status); finalResponse.addHeader( "Set-Cookie", refreshTokenResponse.getHeaders().getFirst("Set-Cookie")); } break; default: return; } } catch (Exception e) { log.error("Error occurred while refreshing access token {}", e); } } } package com.kotak.collection.reporting.client; import java.util.HashMap; import java.util.Map; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; /** * The type Token refresh auth client. */ @Component @Log4j2 public class TokenRefreshAuthClient { @Value("${refresh.token.endpoint}") private String refreshTokenEndpoint; @Value("${auth.server.clientid}") private String clientId; @Value("${auth.server.domain}") private String domain; /** * Refresh access token response entity. * * @param cookieKey the cookie key * @param token the token * @return the response entity */ public ResponseEntity refreshAccessToken(final String cookieKey, final String token) { HttpHeaders tokenHeaders = new HttpHeaders(); tokenHeaders.setContentType(MediaType.APPLICATION_JSON); Map<String, String> requestBody = new HashMap<>(); requestBody.put("clientId", clientId); requestBody.put("domain", domain); tokenHeaders.add("Cookie", cookieKey + "=" + token + "; Max-Age=7776000; Path=/; HttpOnly;"); RestTemplate restTemplate = new RestTemplate(); HttpEntity renewTokenRequest = new HttpEntity<>(requestBody, tokenHeaders); return restTemplate.postForEntity(refreshTokenEndpoint, renewTokenRequest, String.class); } } package com.kotak.collection.reporting.configuration; import com.kotak.collection.reporting.filter.RefreshAccessTokenFilter; import com.nimbusds.jose.jwk.source.JWKSource; import com.nimbusds.jose.jwk.source.JWKSourceBuilder; import com.nimbusds.jose.proc.JWSAlgorithmFamilyJWSKeySelector; import com.nimbusds.jose.proc.JWSKeySelector; import com.nimbusds.jose.proc.SecurityContext; import com.nimbusds.jose.util.DefaultResourceRetriever; import com.nimbusds.jwt.proc.DefaultJWTProcessor; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import java.net.URL; import java.util.Collection; import java.util.List; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; import org.springframework.security.oauth2.core.OAuth2TokenIntrospectionClaimNames; import org.springframework.security.oauth2.core.OAuth2TokenValidator; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtClaimValidator; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.JwtIssuerValidator; import org.springframework.security.oauth2.jwt.JwtTimestampValidator; import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.web.util.WebUtils; /** The type Security config. */ @EnableWebSecurity @Configuration @Log4j2 public class SecurityConfig { @Value("${spring.security.oauth2.resourceserver.jwt.jwks-uri}") private String keyUri; @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}") private String iss; @Value("${auth.server.clientid}") private String clientId; /* * Need to place [clientId]_Token (eg. 19kungvqs1dmi21234nfjgta7l_Token) in properties file */ @Value("${httpOnly.cookie.key}") private String cookieKey; private Collection<OAuth2TokenValidator<Jwt>> validators; @Autowired private ApplicationContext applicationContext; @Autowired private RefreshAccessTokenFilter refreshAccessTokenFilter; /** * Filter requests for authentication and authorization. * * @param http HttpSecurity * @return SecurityFilterChain */ @Bean public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception { return http.csrf((csrf) -> csrf.disable()) .authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated()) .oauth2ResourceServer( oauth2 -> oauth2.jwt(jwt -> jwt.decoder(jwtDecoder())).bearerTokenResolver(this::resolver)) .build(); } /** * Resolver string. * * @param request the request * @return the string */ public String resolver(final HttpServletRequest request) { final Cookie cookie = WebUtils.getCookie(request, cookieKey); if (cookie != null) { int delimiterIndex = cookie.getValue().lastIndexOf("#"); return cookie.getValue().substring(0, delimiterIndex); } return null; } /* */ /** * Calling custom filter in case of /token/refresh API to check validity of access token. * * @return FilterRegistrationBean */ @Bean public FilterRegistrationBean<RefreshAccessTokenFilter> expirationCheckFilter() { FilterRegistrationBean<RefreshAccessTokenFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(refreshAccessTokenFilter); registrationBean.addUrlPatterns("*"); registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); return registrationBean; } /** * Client validator o auth 2 token validator. * * @return the o auth 2 token validator */ public OAuth2TokenValidator<Jwt> clientValidator() { return new JwtClaimValidator<>( OAuth2TokenIntrospectionClaimNames.CLIENT_ID, clientID -> clientID.equals(clientId)); } /** * Token validator o auth 2 token validator. * * @return the o auth 2 token validator */ public OAuth2TokenValidator<Jwt> tokenValidator() { this.validators = List.of(new JwtTimestampValidator(), new JwtIssuerValidator(iss), clientValidator()); return new DelegatingOAuth2TokenValidator<>(this.validators); } /** * Jwt decoder jwt decoder. * * @return the jwt decoder */ @Bean public JwtDecoder jwtDecoder() { JWSKeySelector<SecurityContext> jwsKeySelector = null; DefaultJWTProcessor<SecurityContext> jwtProcessor = null; try { URL jwksUrl = new URL(keyUri); DefaultResourceRetriever resourceRetriever = new DefaultResourceRetriever(5000, 5000); /* Schedule public key refresh in (TTL - (refresh timeout + refresh ahead timeout)) */ JWKSource<SecurityContext> jwkSource = JWKSourceBuilder.create(jwksUrl, resourceRetriever) .cache(360000, 60000) .rateLimited(30000) .refreshAheadCache(60000, true) .build(); jwsKeySelector = JWSAlgorithmFamilyJWSKeySelector.fromJWKSource(jwkSource); jwtProcessor = new DefaultJWTProcessor<>(); jwtProcessor.setJWSKeySelector(jwsKeySelector); } catch (Exception e) { log.error("Error while refreshing jwks cache {}", e); } return new NimbusJwtDecoder(jwtProcessor); } } refresh.token.endpoint=https://dev-ums.collection.kotak.internal/ra-uams/api/token/refresh auth.server.clientid=2bj0pg2s2kggjsoa18g1dc2rto auth.server.domain=collectionuamsdev httpOnly.cookie.key=2bj0pg2s2kggjsoa18g1dc2rto_Token spring.security.oauth2.resourceserver.jwt.jwks-uri=https://cognito-idp.ap-south-1.amazonaws.com/ap-south-1_pKhfXQU56/.well-known/jwks.json spring.security.oauth2.resourceserver.jwt.issuer-uri=https://cognito-idp.ap-south-1.amazonaws.com/ap-south-1_pKhfXQU56
Editor is loading...
Leave a Comment