I'm using
spring-session-1.3.1
spring-boot-1.5.9
jax-rs for my REST API
I did the following to enable SpringSession
aplication.properties
### Spring Session
spring.session.store-type=jdbc
HttpSessionConfig.java
#Configuration
public class HttpSessionConfig
{
#Bean
public HttpSessionStrategy httpSessionStrategy() {
return new HeaderHttpSessionStrategy();
}
}
Database tables are being created and everything works fine. Now I want to login through my API by calling /login. What I don't understand now is, how do I access the x-auth-token sent by spring session in the response. In the chrome dev tools I can clearly see that the x-auth-token is included in the response header.
But when I try to access the header using angulars httpclient I cant even see it.
this.http.post(this.apiBaseURL + "api/session/login", {
username: username,
password: password,
platform: 'webapp',
platformVersion: '0.1',
apiLevel: 1
}, { observe: 'response' })
.subscribe(data => {
console.log(data.headers.keys());
});
Console output:
This can be resolved by allowing Access-Control-Expose-Headers in header. x-auth-token is a custom header, which need to expose to outside world by allowing above tag. You can use below code to get this resolve.
#Configuration
public class WebSecurityCorsFilter extends OncePerRequestFilter {
#Override
public void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
res.setHeader("Access-Control-Allow-Credentials", "x-auth-token");
}
}
Related
I am using a spring boot application and I have a web security config adapter set up to authenticate each request using the jwt.
I want to expand my service to allow a different api end point to be authenticated using the header. One of the services I am integrating with sends a web hook and all it sends is the request with the custom header I set it up to include. How can I set up a specific endpoint to only authenticate using a custom header?
You could use a OncePerRequestFilter to filter the requests to that endpoint and return a 401 if they are do not contain your header with the right value.
You would define your filter:
public class HeaderSecurityFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String value = request.getHeader("Token");
if(value == null || !value.equals("Secret")) {
response.sendError(401);
return;
}
chain.doFilter(request, response);
}
}
And then register it:
#Configuration
public class HeaderSecurityConfiguration {
#Bean
FilterRegistrationBean<HeaderSecurityFilter> filterRegistration() {
FilterRegistrationBean<HeaderSecurityFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new HeaderSecurityFilter());
registration.addUrlPatterns("/some/path/*");
return registration;
}
}
Which would require the header of Token be present with a value of Secret for anything under /some/path/*.
You would also need to ensure through your oauth configuration that you open up access to /some/path/*.
I have an exception handler in Spring. The goal is for this exception handler to just add some additional headers to the response.
If I set the status to 404 using response.setStatus, the headers get overwritten it seems like and I do not see the "something_random" header on the client side. It works fine if I omit the setStatus(404), but then the client gets a 200 with the header. Is there a way to ensure that the 404 response has the custom headers set?
Spring version: 4.3.25
What I've tried:
#ExceptionHandler(CustomNotFoundException.class)
public void handleFailure(Exception ex, HttpServletResponse response) {
response.setHeader("something_random", "bob");
reseponse.setStatus(404);
}
Also tried (not sure if different):
#ExceptionHandler(CustomNotFoundException.class)
public ResponseEntity<Object> handleFailure(Exception ex, HttpServletResponse response) {
// Initialize 'headers'
return new ResponseEntity<>(headers, HttpStatus.NOT_FOUND);
}
I have tried the following with Spring Boot 2.4.2 (Spring Framework 5.3.3) and the custom header is present in the response:
#ExceptionHandler(InvalidResponseException.class)
public ResponseEntity<String> handleOpenApiResponseValidationExceptions(InvalidResponseException ex, HttpServletResponse response) {
return ResponseEntity.status(INTERNAL_SERVER_ERROR)
.header("custom", "value")
.body(ex.getMessage());
}
I Know this is old question but here is one way that can fit into this.
#EnableWebMvc
#Configuration
public class ExceptionHandlingConfig {
#Autowired
private DispatcherServlet dispatcherServlet;
#PostConstruct
private void configureDispatcherServlet() {
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
}
}
I am doing a pure backend project with REST APIs (not MVC) and would like to use SpringSecurity with JWT token to project these APIs. The implementation is good and all APIs are successfully protected with the token, and I can post a JSON string with username and password to "/login" path to get token
My problem is:
The SpringSecurity will return the response with token directly in successfulAuthentication() rather than keep forwarding to RestController (RestController's "/login" path gets no data)
And my question is:
What should I do, after a successful authentication, to allow SpringSecurity can keep forwarding the request to RestController's "/login" path so that I can do something else on the request and the newly built token beside the security in the path?
Appreciate any helps, Thank you!
My code:
#Component
public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {
// ...
#Override
protected void configure(HttpSecurity http) throws Exception {
// ...
http.authorizeRequests()
.antMatchers("/registry").permitAll() // allow path /registry
.antMatchers("/login").permitAll() // allow path /login
.antMatchers("/verify").permitAll() // allow path /verify
.anyRequest().authenticated();
// ...
}
}
#RestController
public class EntranceEndpoint {
#RequestMapping(path = "/login", method = RequestMethod.POST)
public RestResponse<String> login(LoginMetaInfo login) {
System.out.println(login); // no output here when login
// some further operations for a successful login, and return a REST response
}
}
And this is what the SpringSecurity do on a successful login
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
// ...
/**
* on login success
*/
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException {
// here build the token and insert into response for commitment
// - the SpringSecurity soon returns the response directly, rather then keep forwarding to RestController
String token = xxxx;
response.setStatus(StatusCode.SUCCESS().getCode());
RestResponse<String> body = RestResponse.succeeded(StatusCode.SUCCESS().withMsg(LoginResponseCode.LOGIN), token);
response.setContentType(MediaType.APPLICATION_JSON);
response.setCharacterEncoding(MediaType.CHARSET);
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getWriter(), body );
}
}
What about simply using HttpServletResponse's sendRedirect instead of writing to the response?
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException {
// do what you want here
response.sendRedirect("/login");
// response.sendRedirect("https://yoururl");
}
Dev. enviroment: Angular 6.0.9 - Spring boot 2.0.7 - Spring 5.0.7
I have a boring problem. My angular application can not see the token that comes in the request header. my backend is spring and by postman I usually get the token. it is worth noting that in the (chrome) browser, the status code is 200.
Token generetor:
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication auth) throws IOException, ServletException {
String login = ((UsuarioSS) auth.getPrincipal()).getUsername();
String token = jwtUtil.generateToken(login);
response.addHeader("Access-Control-Expose-Headers", "Authorization");
response.addHeader("Authorization", "Bearer " + token);
}
Service login:
export class LoginService {
constructor(public http: HttpClient) { }
authenticate(credential: Credential) {
return this.http.post(`${API_URL}/sge/login`,credential,{observe:'response',responseType:'text'});
}
}
Component:
onSubmit(){
this.credential = this.loginForm.value;
this.loginService.authenticate(this.credential).subscribe(
response => {
console.log(response)
},
error => {console.log(error)}
)
CONSOLE CHROME:
CONSOLE POSTMAN:
Solution: I was not realizing that the custom headers were coming as LazyInit. After that I was able to access my header with the token.
I have an application, where user is pre-authorized by SSO and lands to my page, now I need to make a call to another rest api to get some data, which is running on another server, but it will be use the same authentication. So I just wanted to know, how I can provide the authentication process? Do I need to set the cookie what I am getting from the incoming request.
When the request lands on your page it should have a token or key, in the http AUTHORIZATION header, this should be used with a filter
public class AuthFilter extends OncePerRequestFilter {
private String failureUrl;
private SimpleUrlAuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
try {
// check your SSO token here
chain.doFilter(request, response);
} catch (OnlineDriverEnquiryException ode) {
failureHandler.setDefaultFailureUrl(failureUrl);
failureHandler.onAuthenticationFailure(request, response, new BadCredentialsException("Captcha invalid!"));
}
}
public String getFailureUrl() {
return failureUrl;
}
public void setFailureUrl(String failureUrl) {
this.failureUrl = failureUrl;
}
}
Also read this post on how to set up the auto config. Spring security without form login