Spring Boot RestController DELETE request fails without .csrf().disable() - spring-boot

I have a Spring Boot Rest Service proof of concept.
I have this for my security: (obviously a poor real implmentation).
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
/* not production grade quality */
httpSecurity.authorizeRequests().anyRequest().permitAll();
}
// #Override
// public void configure(WebSecurity web) throws Exception {
// web.debug(true);
// }
}
Using Postman:
All of my GETs were working fine. Then I added a DELETE request. and got
{
"timestamp": "blah blah blah",
"status": 403,
"error": "Forbidden",
"message": "Forbidden",
"path": "/v1/mything/1"
}
Postman setup: (not rocket science)
DELETE
http://localhost:8080/v1/mythings/1
So I added the ".csrf().disable()", and my DELETE works.
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
/* not production grade quality */
httpSecurity.csrf().disable(); /* had to add this "Cross Site Request Forgery" disable for DELETE operations */
httpSecurity.authorizeRequests().anyRequest().permitAll();
}
// #Override
// public void configure(WebSecurity web) throws Exception {
// web.debug(true);
// }
}
But my question is WHY does .csrf().disable() .. allow DELETE requests? Seems somewhat unrelated.
Thanks.
My full rest controller below:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.inject.Inject;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
#RestController
#RequestMapping("/v1")
public class MyThingController {
private final Logger logger;
private final IMyThingManager mythingManager;
/* The Inject annotation is the signal for which constructor to use for IoC when there are multiple constructors. Not needed in single constructor scenarios */
#Inject
public MyThingController(IMyThingManager mythingManager) {
this(LoggerFactory.getLogger(MyThingController.class), mythingManager);
}
public MyThingController(Logger lgr, IMyThingManager mythingManager) {
if (null == lgr) {
throw new IllegalArgumentException("Logger is null");
}
if (null == mythingManager) {
throw new IllegalArgumentException("IMyThingManager is null");
}
this.logger = lgr;
this.mythingManager = mythingManager;
}
#RequestMapping(value = "/mythings", method = RequestMethod.GET)
Collection<MyThingDto> getAllMyThings() {
Collection<MyThingDto> returnItems = this.mythingManager.getAll();
return returnItems;
}
#RequestMapping(method = RequestMethod.GET, value = "mythings/{mythingKey}")
ResponseEntity<MyThingDto> getMyThingById(#PathVariable Long mythingKey) {
this.logger.info(String.format("Method getMyThingById called. (mythingKey=\"%1s\")", mythingKey));
Optional<MyThingDto> foundItem = this.mythingManager.getSingle(mythingKey);
ResponseEntity<MyThingDto> responseEntity = new ResponseEntity<>(HttpStatus.NOT_FOUND);
if (foundItem.isPresent()) {
responseEntity = new ResponseEntity<>(foundItem.get(), HttpStatus.OK);
}
return responseEntity;
}
#RequestMapping(value = "mythings/{mythingKey}", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Integer> deleteUser(#PathVariable("mythingKey") Long mythingKey) {
this.logger.info(String.format("Method deleteUser called. (mythingKey=\"%1s\")", mythingKey));
int rowCount = this.mythingManager.deleteByKey(mythingKey);
int rowCount = 1; /* use this to "fake it" */
ResponseEntity<Integer> responseEntity = new ResponseEntity<>(HttpStatus.NOT_FOUND);
if (rowCount > 0) {
responseEntity = new ResponseEntity<>(rowCount, HttpStatus.OK);
}
return responseEntity;
}
}

CSRF protection checks for a CSRF token on changing methods like POST, PUT, DELETE. And as a REST API is stateless you don't have a token in a cookie. That's why you have to disable it for REST APIs.
References
https://security.stackexchange.com/questions/166724/should-i-use-csrf-protection-on-rest-api-endpoints
Spring Security Reference: https://docs.spring.io/spring-security/site/docs/current/reference/html5/#csrf
Guide to CSRF Protection in Spring https://www.baeldung.com/spring-security-csrf

The guide to CSRF Protection says: "However, if our stateless API uses a session cookie authentication, we need to enable CSRF protection as we'll see next."
For this case the solution is not to disable csrf. Is there another possibility to use CSRF Protection with DELETE

Related

Spring Security with multiple security models configured with SecurityFilterChain ignores authentication configuration

I am trying to build a Spring Boot application, that has different security models for different URLs. So I try to avoid creating a global AuthenticationManager bean, but instead configure it in the Spring Security DSL as described here: https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter
However MyAuthProvider does not get called in either a/ or b/.
I would expect it to be called in both examples.
Surprisingly a/ returns 403 Access Denied and b/ returns 200 OK
What am I doing wrong?
Complete example provided here as a single class Spring Boot application (2.7.3)
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Set;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public SecurityFilterChain secureA(HttpSecurity http) throws Exception {
http.authorizeRequests(auth ->
auth.antMatchers("/a").hasRole("a")
);
http.authenticationProvider(new MyAuthProvider("a"));
return http.build();
}
#Bean
public SecurityFilterChain secureB(HttpSecurity http) throws Exception {
http.authorizeRequests(auth ->
auth.antMatchers("/b").hasRole("b")
);
http.authenticationManager(new ProviderManager(new MyAuthProvider("b")));
return http.build();
}
#RestController
public class RestService {
#GetMapping("/a")
public String a() {
return "hello a";
}
#GetMapping("/b")
public String b() {
return "hello b";
}
#GetMapping("/c")
public String c() {
return "hello c";
}
}
class MyAuthProvider implements AuthenticationProvider {
private String cfg;
public MyAuthProvider(String cfg) {
this.cfg = cfg;
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
System.out.println("authenticate " + cfg);
var roles = Set.of(new SimpleGrantedAuthority("ROLE_" + cfg));
return new UsernamePasswordAuthenticationToken("user", "pass", roles);
}
#Override
public boolean supports(Class<?> authentication) {
System.out.println("supports " + cfg);
return true;
}
}
}

AuthenticationManager.authenticate method not getting called

I am trying to follow the API Key authentication code from this answer:
https://stackoverflow.com/a/48448901
I created my filter class:
package com.propfinancing.CADData.web;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.LoggerFactory;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
public class PullAPIKeyFromHeaderFilter extends AbstractPreAuthenticatedProcessingFilter {
private String apiKeyHeaderName;
public PullAPIKeyFromHeaderFilter(String apiKeyHeaderName) {
this.apiKeyHeaderName = apiKeyHeaderName;
}
#Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
String headerValue = request.getHeader(apiKeyHeaderName);
return request.getHeader(headerValue);
}
#Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return apiKeyHeaderName;
}
}
And then I implemented my security configuration:
package com.propfinancing.CADData.web;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
#Configuration
#EnableWebSecurity
#Order(1)
public class APIKeySecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${caddata.apiKey.header.name}")
private String apiKeyHeaderName;
#Value("${caddata.apiKey}")
private String apiKey;
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
PullAPIKeyFromHeaderFilter pullAPIKeyFromHeaderfilter = new PullAPIKeyFromHeaderFilter(apiKeyHeaderName);
AuthenticationManager authManager = new AuthenticationManager() {
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
String principal = (String) authentication.getPrincipal();
if (!apiKey.equals(principal))
throw new BadCredentialsException("Invalid API key");
authentication.setAuthenticated(true);
return authentication;
}
};
pullAPIKeyFromHeaderfilter.setAuthenticationManager(authManager);
httpSecurity.antMatcher("/**");
httpSecurity.addFilter(pullAPIKeyFromHeaderfilter);
httpSecurity.requiresChannel().anyRequest().requiresSecure();
httpSecurity.csrf().disable();
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry urlAuthConfigurer = httpSecurity.authorizeRequests();
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.AuthorizedUrl authorizedUrl = urlAuthConfigurer.anyRequest();
authorizedUrl.authenticated();
}
}
When I do an external call to the application with the header as part of the request, I get a 403 Forbidden response.
I can see the filter pulling the key from the header. That part is working.
But, the authenticate() method is not being called to check if the header is valid.
I am not sure what I missed, the code looks the same to me.
Any ideas?
Looks like the wrong base class, per https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/web/authentication/preauth/AbstractPreAuthenticatedProcessingFilter.html :
The purpose is then only to extract the necessary information on the
principal from the incoming request, rather than to authenticate them.
Try extending https://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html instead.
I was not able to get the code above to work, but I changed it to use the second answer on the thread (Using a Filter) https://stackoverflow.com/a/63852212 It works as expected.

Spring Boot: "relaying" basic auth from REST controller to RestTemplate

I'm working with two Spring Boot applications, let's call them ServiceA and ServiceB, both exposing a REST API.
ServiceA is called by end users from the browser via a frontend app (we use #RestController classes). On some calls, ServiceA has to call ServiceB (using RestTemplate). We've got authentication and authorization sorted out for our target environment, but for testing locally we are relying on Basic Auth instead, and that's where we're hitting a snag: we would like ServiceA to re-use the Basic Auth credentials the user provided when calling Service B.
Is there an easy way to pass the Basic Auth credentials used on the call to our REST controller to the RestTemplate call?
Quick and dirty solution
The easiest way to do this would be:
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
#RestController
class SomeController {
private final RestTemplate restTemplate = new RestTemplate();
#PostMapping("/delegate/call")
public void callOtherService(#RequestHeader(HttpHeaders.AUTHORIZATION) String authorization) {
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.AUTHORIZATION, authorization);
restTemplate.postForEntity("other-service.com/actual/call", new HttpEntity<Void>(null, headers), Void.class);
// handling the response etc...
}
}
Using interceptors and RestTemplateCustomizer
I didn't want to change to add an extra parameter on each controller method, and I wanted a way to enable or disable this behavior depending on the environment, so here is a slightly more complicated solution that can be enabled using Spring profiles, and doesn't touch the controllers:
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class BasicAuthPropagationInterceptor implements HandlerInterceptor, ClientHttpRequestInterceptor {
private final ThreadLocal<String> cachedHeader = new ThreadLocal<>();
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
final String header = request.getHeader(HttpHeaders.AUTHORIZATION);
cachedHeader.set(header);
return true;
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
cachedHeader.remove();
}
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
String ch = cachedHeader.get();
if (!request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION) && ch != null) {
request.getHeaders().add(HttpHeaders.AUTHORIZATION, ch);
}
return execution.execute(request, body);
}
}
This stores the received header in a ThreadLocal and adds it with an interceptor for RestTemplate.
This can then be configured as such:
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
#Profile("LOCAL")
class LocalConfiguration implements WebMvcConfigurer {
private final BasicAuthPropagationInterceptor basicAuthPropagationInterceptor
= new BasicAuthPropagationInterceptor();
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(basicAuthPropagationInterceptor);
}
#Bean
RestTemplateCustomizer restTemplateCustomizer() {
return restTemplate -> restTemplate.getInterceptors().add(basicAuthPropagationInterceptor);
}
}
RestTemplate obtained by using the default RestTemplateBuilder bean will then automatically set the Authorization HTTP header if it's available in the current thread.

Spring Boot Keycloak Multi Tenant Configuration

I have a Keycloak instance and created two realms and one user for each realm.
Realm1 (Tenant1) -> User 1
Realm2 (Tenant2) -> User 2
And i have my spring boot application.yml (resource server - API) for one specific realm and fixed in my code.
keycloak:
realm: Realm1
auth-server-url: https://localhost:8443/auth
ssl-required: external
resource: app
bearer-only: true
use-resource-role-mappings: true
It's working and validate for Realm1.
but now i can receive requests from user2 (tenant2) and the token will not be valid because the public key (realm1) is not valid for the signed request jwt token (realm2).
What is the best way to allow multi tenancy and dynamically configuration for multi realms?
thanks,
There's a whole chapter on it: 2.1.18: Multi-Tenanacy
Instead of defining the keycloak config in spring application.yaml, keep multiple keycloak.json config files, and use a custom KeycloakConfigResolver:
public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
#Override
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
if (request.getPath().startsWith("alternative")) { // or some other criteria
InputStream is = getClass().getResourceAsStream("/tenant1-keycloak.json");
return KeycloakDeploymentBuilder.build(is); //TODO: cache result
} else {
InputStream is = getClass().getResourceAsStream("/default-keycloak.json");
return KeycloakDeploymentBuilder.build(is); //TODO: cache result
}
}
}
I'm not sure if this works well with the keycloak-spring-boot-starter, but I think it's enough to just wire your custom KeycloakConfigResolver in the KeycloakWebSecurityConfigurerAdapter:
#Configuration
#EnableWebSecurity
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new PathBasedKeycloakConfigResolver();
}
[...]
}
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
#DependsOn("keycloakConfigResolver")
#KeycloakConfiguration
#EnableGlobalMethodSecurity(jsr250Enabled = true)
#ConditionalOnProperty(name = "keycloak.enabled", havingValue = "true", matchIfMissing = true)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider authenticationProvider = new KeycloakAuthenticationProvider();
authenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(authenticationProvider);
}
/**
* Defines the session authentication strategy.
*/
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.cors()
.and()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS)
.permitAll()
.antMatchers("/api-docs/**", "/configuration/ui",
"/swagger-resources/**", "/configuration/**", "/v2/api-docs",
"/swagger-ui.html/**", "/webjars/**", "/swagger-ui/**")
.permitAll()
.anyRequest().authenticated();
}
}
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.keycloak.adapters.OIDCHttpFacade;
import java.io.InputStream;
import java.util.concurrent.ConcurrentHashMap;
public class PathBasedConfigResolver implements KeycloakConfigResolver {
private final ConcurrentHashMap<String, KeycloakDeployment> cache = new ConcurrentHashMap<>();
#Override
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
String path = request.getURI();
String realm = "realmName";
if (!cache.containsKey(realm)) {
InputStream is = getClass().getResourceAsStream("/" + realm + "-keycloak.json");
cache.put(realm, KeycloakDeploymentBuilder.build(is));
}
return cache.get(realm);
}
}
import org.keycloak.adapters.KeycloakConfigResolver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.context.annotation.Bean;
#SpringBootApplication()
public class Application {
public static void main(String[] args) {
SpringApplication.run(DIVMasterApplication.class, args);
}
#Bean
#ConditionalOnMissingBean(PathBasedConfigResolver.class)
public KeycloakConfigResolver keycloakConfigResolver() {
return new PathBasedConfigResolver();
}
}

Returning a cookie or token with LDAP authentication in Spring security

All:
I have a basic program for Ldap authentication which returns a "Principal User "
package com.bpm.cbl.premium.controller;
import java.security.Principal;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
#RestController
#RequestMapping("custom")
public class LDAPAuthController {
public static String domain;
public static String URL;
#Value("${activedirectory.domain}")
private String adDomain;
#Value("${activedirectory.url}")
private String adURL;
#PostConstruct
public void init(){
domain = adDomain;
URL = adURL;
}
#GetMapping("/user-login")
#ResponseBody
public Principal user(Principal user) {
return user;
}
#Configuration
#Order(SecurityProperties.BASIC_AUTH_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().and()
.logout().and()
.authorizeRequests()
.antMatchers("/index.html", "/", "/home", "/login", "/assets/**").permitAll()
.anyRequest().authenticated()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
#Bean
public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider = new
ActiveDirectoryLdapAuthenticationProvider(domain, URL);
return activeDirectoryLdapAuthenticationProvider;
}
}
}
I dont know how to return a cookie or token instead of a object .. Iam new to spring security..Can someone help pls
I have reference to another post but not sure whether it will work how to achieve Ldap Authentication using spring security(spring boot)
Can someone pls provide some inputs pls
Ok I got a solution; Posting for the benefit of all..
There are lot of confusing articles in the internet and many forums but it is very simple
Replace the function under #GetMapping("/user-login") above with a function that returns the cookie in the respose body.. Pass httpserveletresponse as argument for the function along with any other arguments needed.. Thats it the cookie will be returned in the response header;

Resources