Untitled
unknown
plain_text
2 years ago
10 kB
8
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_pKhfXQU56Editor is loading...
Leave a Comment