Spring Security OAuth (separate client on angular2) - java

I have a problem with configuring spring security and oauth2.
I used a tutorial on their page, where there was an angular1 app that was running on the same port and was served from Tomcat.
I want to do it in a different way. What I want to do is put a completely separate angular2 app, running on a different port.
Now the problem is that the app only returns to port 8080 (spring app) and I don't know how to change this behavior.
My whole Java code is:
#SpringBootApplication
#EnableOAuth2Sso
#RestController
public class SocialApplication extends WebSecurityConfigurerAdapter {
#RequestMapping("/user")
public Principal user(Principal principal) {
return principal;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/log**", "/login**", "/webjars/**")
.permitAll()
.anyRequest()
.authenticated()
.and().logout().logoutSuccessUrl("/").permitAll()
.and().csrf().csrfTokenRepository(csrfTokenRepository())
.and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}
}

Solution is here I have create a tutorial.
link to tutorial is here

Related

Spring Security returns only 401 Unauthorized

My application uses Spring Boot 3 with Spring Security and JWT authentication. It is simple REST API. This is my SecurityFilterChain:
#Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// No need for CSRF in this example
http
.cors()
.and()
.csrf().disable()
// No authentication
.authorizeHttpRequests()
.requestMatchers("/login", "/register").permitAll()
// Authentication for other requests
.anyRequest().authenticated()
.and()
// Session is stateless
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
And this is my JwtAuthenticationEntryPoint:
#Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
I prepared exception classes as described in point 3.3 here and here like this:
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public class RecipeNotFoundException extends RuntimeException {
}
I use them like this.
if (recipeFound.isEmpty()) throw new RecipeNotFoundException();
I would like to send appropriate HTTP codes ex. when user tries to edit recipe that does not exist. Unfortunately I always get 401 Unauthorized. It also prevents my app from sending 500 code (I get 401 instead).
Here is my JwtRequestFilter:
#Component
public class JwtRequestFilter extends OncePerRequestFilter {
private final JwtUserDetailsService jwtUserDetailsService;
private final JwtTokenUtil jwtTokenUtil;
public JwtRequestFilter(JwtUserDetailsService jwtUserDetailsService, JwtTokenUtil jwtTokenUtil) {
this.jwtUserDetailsService = jwtUserDetailsService;
this.jwtTokenUtil = jwtTokenUtil;
}
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
if (!request.getRequestURI().equals("/register") && !request.getRequestURI().equals("/login")) {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
// Remove Bearer word from token
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not start with Bearer String");
}
// Validate token
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
// Configure authentication in Spring Security
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// Successful Authentication
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
}
chain.doFilter(request, response);
}
}

AuthenticationProvider not authenticating

I am making custom token authentication in java spring boot, but it doesn't work. Please help.
This is my SecurityConfigurerAdapter :
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled=true)
public class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private BokiAuthenticationProvider bokiAuthenticationProvider;
#Autowired
private MyCredentialsFilter myCredentialsFilter;
#Override
protected void configure(HttpSecurity http) throws Exception {
// request handling
http.authorizeRequests()
.antMatchers(HttpMethod.GET, "/users").hasRole("USER")
.antMatchers(HttpMethod.GET, "/users/*").hasRole("USER")
.antMatchers(HttpMethod.POST, "/users").permitAll()
.antMatchers(HttpMethod.PATCH, "/users/*").hasRole("USER")
.antMatchers(HttpMethod.DELETE, "/users/*").hasRole("USER")
.antMatchers(HttpMethod.POST, "/login").permitAll()
;
// disable csrf
http.csrf().disable();
// app session is stateless
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(myCredentialsFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.eraseCredentials(false)
.authenticationProvider(bokiAuthenticationProvider);
}
}
This is my filter. The request comes into the filter first. The token string is in the request header. I make a UsernamePasswordAuthenticationToken object out of it :
#Component
public class CredentialsFilter extends OncePerRequestFilter{
#Autowired
private MyCriptoService myCriptoService;
public CredentialsFilter(){
super();
}
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
if(request.getRequestURI().contains("login")){
chain.doFilter(request, response);
}else{
String token = request.getHeader("MyTokenHeader");
String username = myCriptoService.getUsernameFromToken(token);
if (username!=null && SecurityContextHolder.getContext().getAuthentication()==null){
UsernamePasswordAuthenticationToken
authentication = new UsernamePasswordAuthenticationToken(
username,
myCriptoService.getPasswordFromToken(token),
myCriptoService.getAuthoritiesFromToken(token));
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
}
}
}
And this is my AuthenticationProvider :
#Component
public class BokiAuthenticationProvider implements AuthenticationProvider {
#Autowired
private MyUserRepository myUserRepository;
#Autowired
private MyCriptoService myCryptoService;
#Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
String username = auth.getName();
if(username!=null && !"".equals(username)){
MyUserJPA jpa = myUserRepository.findByUsername(username);
if(jpa!=null){
String password = auth.getCredentials().toString();
if(myCryptoService.checkPasswords(password, jpa.getPassword())){
#SuppressWarnings("unchecked")
List<SimpleGrantedAuthority> authorities = (List<SimpleGrantedAuthority>) auth.getAuthorities();
return new UsernamePasswordAuthenticationToken(
jpa.getUsername(),
null,
authorities);
}
throw new MyBadCredentialsException("Passwords is missing or invalid.");
}
throw new MyBadCredentialsException("There is no user with username = "+username);
}
throw new MyBadCredentialsException("You did not provide a username.");
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
I did debugging. The filter fires and does the .doFilter(request,response), but the AuthenticationProvider doesn't even start.
What am i doing wrong ?
It turns out that authentication provider was authenticating, but there was a problem with the database. I recreated the database, and now it works.
Also, it is impossible for debugging to enter the authenticate-method in the authentication provider once the program is running. That was why my debug was failing.
The source of my confusion was also that my fiddler was not displaying me the JSON from the GET request, but that was an issue with the Fiddler which i solved.
Now I have tested it in more detail now, and everything is working.

Redirect loop when x509 authentication fails

I have spring boot application with x509 authentication. My problem is that when authentication fails i get redirect loop instead of error screen.
When authentication fails i throw UsernameNotFoundException loadUserDetails from method in ArhivX509UserDetailsService.java
My code is as follows:
SecurityConfiguration.java
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("x509UserDetailsService")
private AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> iX509UserDetailsService;
#Override
protected void configure(HttpSecurity pHttp) throws Exception {
//#formatter:off
pHttp
.authorizeRequests()
.antMatchers("/webjars/**").permitAll()
.antMatchers("/error").permitAll()
.antMatchers("/error401").permitAll()
.anyRequest().authenticated()
.and()
.x509()
.subjectPrincipalRegex("(.*)")
.authenticationUserDetailsService(iX509UserDetailsService)
.and()
.addFilterAfter(new X509ErrorCheckerFilter(), X509AuthenticationFilter.class)
.addFilterBefore(new LoggerMDCFilter(), X509ErrorCheckerFilter.class)
.exceptionHandling()
.authenticationEntryPoint(unauthorizedEntryPoint())
.accessDeniedPage(AppUrls.ERROR_401)
.and()
.requiresChannel()
.anyRequest()
.requiresSecure()
.and()
.sessionManagement()
.maximumSessions(1)
.and()
.and()
.logout()
.invalidateHttpSession(true)
.deleteCookies("SESSION", "JSESSIONID")
.logoutSuccessUrl("http://www.google.com")
.permitAll();
//#formatter:on
}
#Bean
public AuthenticationEntryPoint unauthorizedEntryPoint() {
return new AuthenticationEntryPoint() {
#Override
public void commence(HttpServletRequest pRequest, HttpServletResponse pResponse,
AuthenticationException pAuthException) throws IOException, ServletException {
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
};
}
}
ArhivX509UserDetailsService.java
#Service("x509UserDetailsService")
public class ArhivX509UserDetailsService
implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
#Autowired
private IUserProfileService iUserProfileService;
#Autowired
private ICheckCertificateService iCheckCertService;
#Override
public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken pToken) throws UsernameNotFoundException {
X509Certificate tCertificate = (X509Certificate) pToken.getCredentials();
String tSubjectDN = tCertificate.getSubjectDN().toString().toUpperCase();
ProfilKorisnika tProfilKorisnika = iUserProfileService.getUserProfile(tSubjectDN);
if (tProfilKorisnika == null) {
throw new UsernameNotFoundException("Pogreška kod prijave korisnika.");
}
return tProfilKorisnika;
}
}
X509ErrorCheckerFilter.java
public class X509ErrorCheckerFilter extends GenericFilterBean {
private static final String DEFAULT_REDIRECT_URL = "/error401";
private static final String[] UNAUTHENTICATED_URLS = { "/webjars/**", "/error", "/error401", "/login",
"/logout" };
#Override
public void doFilter(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain)
throws IOException, ServletException {
HttpServletRequest tHttpRequest = (HttpServletRequest) pRequest;
HttpServletResponse tHttpResponse = (HttpServletResponse) pResponse;
String tContextRoot = tHttpRequest.getSession().getServletContext().getContextPath();
String tUri = tHttpRequest.getRequestURI().replaceFirst(tContextRoot, "");
if (isUriSecured(tUri)) {
Authentication tAuthentication = SecurityContextHolder.getContext().getAuthentication();
AuthenticationException tException = (AuthenticationException) tHttpRequest
.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
if (tException != null || tAuthentication == null) {
RequestDispatcher tRd = tHttpRequest.getRequestDispatcher(DEFAULT_REDIRECT_URL);
tRd.forward(tHttpRequest, tHttpResponse);
return;
}
}
pChain.doFilter(pRequest, pResponse);
}
private boolean isUriSecured(String pRequestURI) {
boolean tResult = true;
for (String tUrl : UNAUTHENTICATED_URLS) {
if (pRequestURI.startsWith(tUrl)) {
tResult = false;
break;
}
}
return tResult;
}
}
If you need more details please ask.
Applying permitAll() to /error401 means that when the security filterchain is finished executing, the request will be processed normally, regardless of whether or not there is an Authentication in the current SecurityContext.
X509ErrorCheckerFilter is forwarding all unauthenticated requests to /error401 from within the filterchain, so permitAll() is never applied. Instead, the forwarded request goes through the filterchain again and fails authentication, causing the circular redirect.
To resolve this, you have several options. Here are a couple:
1. Disable Security for error endpoints
you can disable security for endpoints using web.ignoring() in your SecurityConfiguration class. This is the simplest option.
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/error*");
}
2. Implement the ErrorController interface
The security filterchain will not be called for request mappings included in a controller that implements ErrorController.
See Spring's own BasicErrorController for reference(source).
This second option is preferable as it removes any requirement for a redirect in your filter. Instead, it lets Spring Security do the heavy lifting for routing requests through the auth process. As long as there's no authenticated Authentication in the session's SecurityContext when the security filterchain has finished processing, spring security will return a 401 and return the error page specified by your ErrorController.

Spring Boot Security Context return null when using a JWT token

I have created a REST API that require a authentication with JWT.
My implementation is very similar with the code found on https://auth0.com/blog/securing-spring-boot-with-jwts/
When I try to return the current user, I always receive a null return.
My code:
Websecurity:
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
// login
.antMatchers(HttpMethod.POST, "/login")
.permitAll()
.anyRequest()
.authenticated()
.and()
.addFilterBefore(new JWTLoginFilter(
"/login", authenticationManager(), logService), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
JWTAuthenticationFilter:
public class JWTAuthenticationFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest req,
ServletResponse res,
FilterChain filterChain) throws IOException, ServletException {
Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest)req);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(req, res);
}
}
I don't included all the code of JWT authentication, because JWT is working ok, user access too.
I believe the problem is in the filter or some configuration.
Then, I made a facade to get the current user on a service or controller, with the following code (method 4 on http://www.baeldung.com/get-user-in-spring-security):
public Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
but this don't worked.
- SecurityContextHolder.getContext() returned org.springframework.security.core.context.SecurityContextImpl#ffffffff: Null authentication.
- SecurityContextHolder.getContext().getAuthentication() returned null object.
Update (and solution):
In my controller, if I use this code:
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
I can get the current user, but, in my service, the exact same code don't work.
But then, I remember that SecurityContext is "lost" on another thread (source: https://docs.spring.io/spring-security/site/docs/current/reference/html/concurrency.html), and my service is async
#Async
public CompletableFuture<Optional<ViewUserDto>> findByLogin(String login) throws InterruptedException {
...
}
So, using the code found here: https://stackoverflow.com/a/40347437/4794469, everything works correctly.
I don't known if this can bring any side effects for my code yet (all unit tests worked)
I have worked in an application that has a similar authorization flow as yours:
WebSecurityConfigurerAdapter
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationProvider provider;
#Autowired
private TokenAuthenticationService tokenService;
#Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.authenticationProvider(provider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().disable();
http.csrf().disable();
http.authorizeRequests().antMatchers(HttpMethod.POST, "/v1/users", "/v1/oauth/token").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new OAuthTokenFilter("/v1/oauth/token", authenticationManager(), tokenService), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new AuthorizationFilter(tokenService), UsernamePasswordAuthenticationFilter.class);
}
}
AbstractAuthenticationProcessingFilter
public class OAuthTokenFilter extends AbstractAuthenticationProcessingFilter {
private final ObjectMapper MAPPER = new ObjectMapper();
private TokenAuthenticationService service;
public OAuthTokenFilter(String url, AuthenticationManager manager, TokenAuthenticationService service) {
super(new AntPathRequestMatcher(url));
setAuthenticationManager(manager);
this.service = service;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
Login login = MAPPER.readValue(request.getInputStream(), Login.class);
UsernamePasswordAuthenticationToken token =
new UsernamePasswordAuthenticationToken(login.getUsername(), login, Arrays.asList());
return getAuthenticationManager().authenticate(token);
}
#Override
protected void successfulAuthentication(
HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authentication) throws IOException, ServletException {
User credentials = (User) authentication.getPrincipal();
String token = service.jwt(credentials);
String json = MAPPER.writeValueAsString(new AuthorizationToken(token, "Bearer"));
response.addHeader("Content-Type", "application/json");
response.getWriter().write(json);
response.flushBuffer();
}
}
GenericFilterBean
public class AuthorizationFilter extends GenericFilterBean {
private TokenAuthenticationService service;
public AuthorizationFilter(TokenAuthenticationService service) {
this.service = service;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Authentication authentication = service.getAuthentication((HttpServletRequest)request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
}
TokenAuthenticationService
#Service
public class TokenAuthenticationService {
public static final String JWT_SECRET_ENV = "JWT_SECRET";
public static final String ISSUER = "my issuer";
public static final String ROLE_CLAIM = "role";
public static final String THIRDY_PARTY_ID_CLAIM = "thirdy_party_id";
public static final String TOKEN_PREFIX = "Bearer";
public static final String HEADER = "Authorization";
#Autowired
private Environment environment;
public Authentication getAuthentication(HttpServletRequest request) {
String token = request.getHeader(HEADER);
String secret = environment.getProperty(JWT_SECRET_ENV);
if (token != null) {
try {
String bearer = token.replace(TOKEN_PREFIX, "").trim();
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer(ISSUER)
.build();
DecodedJWT jwt = verifier.verify(bearer);
User user = new User();
user.setId(jwt.getSubject());
user.setThirdPartyId(jwt.getClaim(THIRDY_PARTY_ID_CLAIM).asString());
user.setRole(jwt.getClaim(ROLE_CLAIM).asString());
List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRole());
return new UsernamePasswordAuthenticationToken(user, null, authorities);
} catch (Exception e){
e.printStackTrace(System.out);
}
}
return null;
}
}
And then, the controller:
#RestController
public class UserController {
#ResponseBody
#GetMapping("/v1/users/{id}")
#PreAuthorize("hasAuthority('USER')")
public User get(#PathVariable("id") String id, Authentication authentication) {
User user = (User) authentication.getPrincipal();
return user;
}
}
I faced similar issue when i was enabling JWT on my web app.
You need: "Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files".
Please download the this package from the below URL and replace US_export_policy.jar, local_policy.jar (\jre\lib\security)
If it is still not working, then you need to replace the above jar files in the location \lib\security
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

How to disable spring security for particular url

I am using stateless spring security,but in case of signup i want to disable spring security.I disabled using
antMatchers("/api/v1/signup").permitAll().
but it is not working,i am getting error below:
message=An Authentication object was not found in the SecurityContext, type=org.springframework.security.authentication.AuthenticationCredentialsNotFoundException
I think this means spring security filters are working
My url's order always will be "/api/v1"
My spring config is
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
csrf().disable().
sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).
and().
authorizeRequests().
antMatchers("/api/v1/signup").permitAll().
anyRequest().authenticated().
and().
anonymous().disable();
http.addFilterBefore(new AuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class);
}
My authentication filter is
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = asHttp(request);
HttpServletResponse httpResponse = asHttp(response);
String username = httpRequest.getHeader("X-Auth-Username");
String password = httpRequest.getHeader("X-Auth-Password");
String token = httpRequest.getHeader("X-Auth-Token");
String resourcePath = new UrlPathHelper().getPathWithinApplication(httpRequest);
try {
if (postToAuthenticate(httpRequest, resourcePath)) {
processUsernamePasswordAuthentication(httpResponse, username, password);
return;
}
if(token != null){
processTokenAuthentication(token);
}
chain.doFilter(request, response);
} catch (InternalAuthenticationServiceException internalAuthenticationServiceException) {
SecurityContextHolder.clearContext();
logger.error("Internal authentication service exception", internalAuthenticationServiceException);
httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (AuthenticationException authenticationException) {
SecurityContextHolder.clearContext();
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage());
} finally {
}
}
private HttpServletRequest asHttp(ServletRequest request) {
return (HttpServletRequest) request;
}
private HttpServletResponse asHttp(ServletResponse response) {
return (HttpServletResponse) response;
}
private boolean postToAuthenticate(HttpServletRequest httpRequest, String resourcePath) {
return Constant.AUTHENTICATE_URL.equalsIgnoreCase(resourcePath) && httpRequest.getMethod().equals("POST");
}
private void processUsernamePasswordAuthentication(HttpServletResponse httpResponse,String username, String password) throws IOException {
Authentication resultOfAuthentication = tryToAuthenticateWithUsernameAndPassword(username, password);
SecurityContextHolder.getContext().setAuthentication(resultOfAuthentication);
httpResponse.setStatus(HttpServletResponse.SC_OK);
httpResponse.addHeader("Content-Type", "application/json");
httpResponse.addHeader("X-Auth-Token", resultOfAuthentication.getDetails().toString());
}
private Authentication tryToAuthenticateWithUsernameAndPassword(String username,String password) {
UsernamePasswordAuthenticationToken requestAuthentication = new UsernamePasswordAuthenticationToken(username, password);
return tryToAuthenticate(requestAuthentication);
}
private void processTokenAuthentication(String token) {
Authentication resultOfAuthentication = tryToAuthenticateWithToken(token);
SecurityContextHolder.getContext().setAuthentication(resultOfAuthentication);
}
private Authentication tryToAuthenticateWithToken(String token) {
PreAuthenticatedAuthenticationToken requestAuthentication = new PreAuthenticatedAuthenticationToken(token, null);
return tryToAuthenticate(requestAuthentication);
}
private Authentication tryToAuthenticate(Authentication requestAuthentication) {
Authentication responseAuthentication = authenticationManager.authenticate(requestAuthentication);
if (responseAuthentication == null || !responseAuthentication.isAuthenticated()) {
throw new InternalAuthenticationServiceException("Unable to authenticate Domain User for provided credentials");
}
logger.debug("User successfully authenticated");
return responseAuthentication;
}
My controller is
#RestController
public class UserController {
#Autowired
UserService userService;
/**
* to pass user info to service
*/
#RequestMapping(value = "api/v1/signup",method = RequestMethod.POST)
public String saveUser(#RequestBody User user) {
userService.saveUser(user);
return "User registerted successfully";
}
}
I am totally new to spring,please help me how to do it ?
When using permitAll it means every authenticated user, however you disabled anonymous access so that won't work.
What you want is to ignore certain URLs for this override the configure method that takes WebSecurity object and ignore the pattern.
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/v1/signup");
}
And remove that line from the HttpSecurity part. This will tell Spring Security to ignore this URL and don't apply any filters to them.
I have a better way:
http
.authorizeRequests()
.antMatchers("/api/v1/signup/**").permitAll()
.anyRequest().authenticated()
<http pattern="/resources/**" security="none"/>
Or with Java configuration:
web.ignoring().antMatchers("/resources/**");
Instead of the old:
<intercept-url pattern="/resources/**" filters="none"/>
for exp . disable security for a login page :
<intercept-url pattern="/login*" filters="none" />
This may be not the full answer to your question, however if you are looking for way to disable csrf protection you can do:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/web/admin/**").hasAnyRole(ADMIN.toString(), GUEST.toString())
.anyRequest().permitAll()
.and()
.formLogin().loginPage("/web/login").permitAll()
.and()
.csrf().ignoringAntMatchers("/contact-email")
.and()
.logout().logoutUrl("/web/logout").logoutSuccessUrl("/web/").permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("admin").roles(ADMIN.toString())
.and()
.withUser("guest").password("guest").roles(GUEST.toString());
}
}
I have included full configuration but the key line is:
.csrf().ignoringAntMatchers("/contact-email")
As #M.Deinum already wrote the answer.
I tried with api /api/v1/signup. it will bypass the filter/custom filter but an additional request invoked by the browser for /favicon.ico, so, I add this also in web.ignoring() and it works for me.
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/v1/signup", "/favicon.ico");
}
Maybe this is not required for the above question.
If you want to ignore multiple API endpoints you can use as follow:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests()
.antMatchers("/api/v1/**").authenticated()
.antMatchers("api/v1/authenticate**").permitAll()
.antMatchers("**").permitAll()
.and().exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
I faced the same problem here's the solution:(Explained)
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.POST,"/form").hasRole("ADMIN") // Specific api method request based on role.
.antMatchers("/home","/basic").permitAll() // permited urls to guest users(without login).
.anyRequest().authenticated()
.and()
.formLogin() // not specified form page to use default login page of spring security.
.permitAll()
.and()
.logout().deleteCookies("JSESSIONID") // delete memory of browser after logout.
.and()
.rememberMe().key("uniqueAndSecret"); // remember me check box enabled.
http.csrf().disable(); **// ADD THIS CODE TO DISABLE CSRF IN PROJECT.**
}

Categories

Resources