Spring Security - securing REST API - spring

I am using Spring Security to secure a REST API.
I use a custom filter which checks if requests contain a valid JWT Token in the header. If the request contains a valid token, an authentication object is added to the security context, otherwise i add null to the security context.
I have also defined an AuthenticationEntryPoint which simply returns 401 when there is an Authentication Exception.
In my security xml, i define a series of intercept-urls. Some of them have access set to "isAuthenticated()" and some have access set to "permitAll".
When i make a request to a URL that has access set to "isAuthenticated()" with a valid JWT token in the header, that works fine. However, when i make a request with no token to a URL with access set to 'permitAll', an exception is thrown and 401 is returned.
What i want to achieve is a 401 response only being made when an unauthenticated request tries to access a URL with access set to 'isAuthenticated()'. When a request is made to a URL with access set to 'permitAll', i dont want 401 to be returned, whether the request is authenticated or not.

Related

Authenticate opaque token in the spring security oauth server

Using the old authorization server, the user request an opaque token using the Client credentials grant and then use it inside an Authorization Header when calling APIs. On our resource server, we would contact the authorization server to authenticate this token and retrieve client information.
On the new server, we have no problem generating this opaque token but I don't understand how we can authenticate this token ?
When calling the introspection endpoint, we have always an Unauthorized result due to using AnonymousAuthenticationToken: obviously since the user is already logged in, we don't ask him to give his client_id and client_secret for each call.
Is it possible to allow this behavior ?
Calling the introspection endpoint and having a success with the decrypted token metadata and not a 401.

Securing rest and actuator endpoints using custom token and http session

I have a spring boot app where the API #Controller endpoints are secured using a token that is contained in the http header. The token needs to be extracted from the header and validated against an internal cache to make sure it is valid. If the token is valid then the request can proceed to the controller and if it is not valid then it should return a 401 to the caller.
I also have another requirement to secure some of the actuator end points. When the user tries to use the browser to access the respective actuator endpoint, it will check for a user session if no session exists then the request is redirected to the spring login page. When they login I need to extract the username and password and validate using an external service. If valid a session can be created for the user and they can then use the hawtio endpoint. The session needs to store role based information so that when the user tries to perform JMX operations it will only allow them to perform the appropriate read only / write if they have the requisite role.
Any pointers regarding how you'd try and tackle this would be most welcome. I am unsure whether this is achieved by specifying addFilterBefore or addFilter and I don't understand how having authenticated the user for the actuator I go about creating a session that can be stored in the context and checked later on for subsequent requests.
Thanks

Spring security - CSRF with REST methods

I have a rest api where I have exposed get, post, put and delete methods. I am using spring security and implementing basic authentication. I am allowing the GET request to be made by a user with the role USER whereas the other requests can only be made by a user with role ADMIN. I see that if I don't add the crsf().disable() line only the GET method works correctly, whereas I get a 403 Forbidden for other methods. However when I add csrf().disable() all the methods work fine. Is this expected or am I doing something wrong?
When csrf is enabled , springboot expects you to send the csrf token with every request that is made to the endpoint. If that is not included then the request is denied and you get the 403 response code. It is like an HTTP session. But rest endpoints are stateless so it's better not to use csrf with it . Rest endpoints are essentially immune to csrf attacks as they are stateless.Read doc.

How to make OAuth2/Zuul redirect user to login page when refresh token expires?

How does one makes spring/zuul proxy redirect to the OAuth2 authentication endpoint when the refresh token has expired?
Currently what happens is that I get a BadCredentialsException in OAuth2TokenRelayFilter:getAccessToken() because the refresh token has expired and that gets returned as a HTTP 500 to the browser.
Architecture
edge service with #EnableZuulProxy, #EnableOAuth2Sso performs authentication with Keycloak and proxy calls to the services below
UI service that serves the user interface, not protected
main service with #EnableResourceServer, expects OAuth2 access token
Current implementation status
Requesting any Zuul proxy endpoint triggers the authentiation and redirect the browser to Keycloak. Upon successful authentication Keycloak redirect back to the proxy which retrieve both access token and refresh tokens. Then Zuul fulfils the initial endpoint call.
When the access token expires, a new token is retrieved using the refresh token before proxying to services.
In the main service the OAuth2 token is validated before processing API requests.
Everything works apart from that "refresh token expired" condition. This is such a standard case that I must be missing something obvious.

Missing CSRF token in REST request

I'm writing a REST API using Spring MVC. I'm trying to access a controller method via a POST request.
I always receive a 403error:
Invalid CSRF Token '' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.
How can I deliver a CSRF token within my REST request?
I tried to use the default security password which is displayed during application startup as the value for _csrf but it wasn't successful.
How can I retrieve the CSRF token and is it correct to send the token in the _csrf parameter?
You will need to provide the correct header and CSRF token when making the request e.g.
request.setRequestHeader('${_csrf.headerName}', '${_csrf.token}');
You can also send the token as a request parameter using _csrf.parameterName.

Resources