Securing REST endpoint using spring security - spring-security

I am trying to provide security to the REST endpoints. I am following instructions from this page. In my case I don't have view hence I haven't created controller to specify the views and haven't added viewResolver in my AppConfig.java
After implementation it correctly shows the access denied error upon calling a secured REST endpoint. But even though I specify username/password in the request header I get the access denied error. I am testing in postman setting username/password in Basic Auth. What am I missing any idea?

The example you have followed is implementing a form-based authentication. In order to change it to http auth (which is more suitable for REST services) you need to look for the following form-login tag in your security.xml:
<form-login
login-page="/login"
default-target-url="/welcome"
authentication-failure-url="/login?error"
username-parameter="username"
password-parameter="password" />
And just change it to an empty http-basic tag:
<http-basic />
If you did not change anything else, then it supposed to work perfectly. You can also test your setup from your browser, by trying to access your page. If you configured everything properly you will get a popup this time, not a form. That will be HTTP-basic authentication welcoming you.
Since likely you are using the Java-based configuration, the equivalent of this change would be to replace:
http.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.antMatchers("/dba/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_DBA')")
.and().formLogin();
with:
http.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.antMatchers("/dba/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_DBA')")
.and().httpBasic();

Related

Listing several authentication providers within the same authentication manager

I came across this code snippet while debugging an authentication problem :
<security:authentication-manager>
<security:authentication-provider user-service-ref="userDetailsService">
<security:password-encoder hash="sha-256">
<security:salt-source user-property="dateCreated" />
</security:password-encoder>
</security:authentication-provider>
<security:authentication-provider ref="ldapAuthProvider" />
</security:authentication-manager>
What I have noticed while debugging and playing around with the user credentials is that if the first authentication-provider (i.e. userDetailsService) fails to authenticate my user, a remote call is then made to my LDAP server to try to authenticate my user. However if the first authentication-provider manages to authenticate my user successfully, the second authentication-provider is never called.
My question is does the listing of these authentication providers work in a way that if one fails we should jump to the next? I also wonder if the order of them authentication providers listed within the authentication manager plays a role (from a priority standpoint)? An extra reference from Spring Security's official documentation will be more than appreciated.
From the Spring Security reference documentation:
Each AuthenticationProvider has an opportunity to indicate that authentication should be successful, fail, or indicate it cannot make a decision and allow a downstream AuthenticationProvider to decide. If none of the configured AuthenticationProviders can authenticate, then authentication will fail (...)
In practice each AuthenticationProvider knows how to perform a specific type of authentication. For example, one AuthenticationProvider might be able to validate a username/password, while another might be able to authenticate a SAML assertion.
When multiple AuthenticationProviders are defined, they will be queried in the order they are declared.
If the first AuthenticationProvider cannot come to a conclusion it will allow the next AuthenticationProvider to try.

How to pass token while calling EWS endpoint using proxy generated classes (ExchangeServicePortTypeClient) not through EWSManagedAPI

I am having a console application which uses Exchange Web Services OnPrem using proxy generated classes like below
var client = new ExchangeServicePortTypeClient("EndPointConfigName", ".XXXXX.asmx");
It works fine. Now I want to do the same for Exchange Online but with that it's OAuth authentication and requires token to pass.
I am generating token using registered application id, tenant id and certificate however, not sure how exactly I can add it with "ExchangeServicePortTypeClient" object.
I see ExchangeServicePortTypeClient has some token specific properties but not getting how exactly I can do.
Due to that I am getting exception "The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Basic Realm=""'".
I believe i would need some changes in my binding(tried both basichhttpbinding and wshttpbinding) as well but not getting what would work for OAuth authentication.
Just sample. I tried with all the possible options like Windows, Basic, None, Certificate...
<security mode="Transport">
<transport clientCredentialType="Windows" proxyCredentialType="Basic" realm="*" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
Can you please suggest how I can achieve this ?
Please note I am able to do this using EWSManagedAPI as well as Service call using "HttpWebRequest" [passing token like getFolderRequest.Headers.Add("Authorization", "Bearer " + accessToken);]
However, my requirement is to do using proxy generated classes.

Orbeon make Authorization header optional

I have a single, embedded orbeon instance, behind a spring gateway with JWT security. This works well, for the orbeon builder, I need to forward the Authorization header to make the things working properly.
But for the form-runner, now I have a requirement: for some forms the authentication is required, for some others it is not.
It is possible to configure the Orbeon in the following way: if the Authorization header is present, forward it, if not, do nothing (just load the form and let it fill)?
This is the settings for header forwarding in my properties-local-prod.xml
<property
as="xs:string"
name="oxf.http.forward-headers"
value="Authorization"/>
<property
as="xs:string"
name="oxf.xforms.forward-submission-headers"
value="Authorization token allowDraft"/>
<property
as="xs:string"
name="oxf.fr.authentication.method"
value="header"/>
At now I got the default Orbeon unauthorized page.
I got 401 when I am trying to open the embedded from-runner without authentication (obviously there is nothing to send towards to orbeon). I found this in orbeon log:
HTTP status code 401 {controller: "oxf:/apps/fr/page-flow.xml", method: "GET", path:
"/fr/app/form/edit/myforminstanceid", status-code: "401"}
A possible solution would be if it would be possible to define some kind of run context that can be applied per form definition basis, like prod-auth, prod-public (unfortunately these should be active parallelly as we have a single Orbeon instance). (Further thinking the already available run modes, e.g. for the same set of forms I should be able to define that the save-draft is visible for autenticated users, but not for the anonymous users... although I have already solved this with some not-that-nice javascript magic.)
Orbeon itself does not do anything when one put a similar config to the properties-prod.xml, just forwards the given headers.
Albeit the default Orbeon Forms logging could be better (about the further HTTP calls to be aware what is happening in the background), there was that single line in the log what it did when the request arrived. As it turned out, my custom backend (persistence layer) expected the Authorization header.
I had to put to my spring security config a (/contextRoot/orbeon).permitAll() and it started to work.

How to load custom CSRF token repository in Spring 5.2?

Our application using spring framework need to implement request based CSRF token in order to meet security requirements. Currently we have session based CSRF token provided by HttpSessionCsrfTokenRepository as Spring default. According to instruction I found, by configuring xml like this
<security:csrf token-repository-ref="customRequestCsrfTokenRepository"/>
<bean id="customRequestCsrfTokenRepository" class="com.dev.common_web.security.configuration.CustomCsrfTokenRepository"/>
Custom token repository which implements CsrfTokenRepository interface will be loaded to handle token request.
However when application starts, and running in debug mode, I can see it is spring default HttpSessionCsrfTokenRepository is used to handle loading and generating of token. I have also tried using spring CookieCsrfTokenRepository in xml config like
<security:csrf token-repository-ref="cookieCsrfTokenRepository"/>
<bean id="cookieCsrfTokenRepository" class="org.springframework.security.web.csrf.CookieCsrfTokenRepository"/>
And when application is running, it is again HttpSessionCsrfTokenRepository which is loaded to handle token request. Seems it doesn't matter what is configured as value of "token-repository-ref" in xml, it is always HttpSessionCsrfTokenRepository in use.
How to configure spring to use other csrf token repository instead of the default HttpSessionCsrfTokenRepository? We are using Spring 5.2.
I managed to figure this out :-).
In security.xml of our application, we have also customized csrf request matcher defined in order to disable csrf checking for some of the pages. When now adding customized csrf token repository, these two have to be defined in the same line inside <security:csrf ... />. If they are defined in two lines like this, only one is loaded.
<security:csrf token-repository-ref="customRequestCsrfTokenRepository"/>
<security:csrf request-matcher-ref="customCsrfRequestMatcher"/>
It has to be like this
<security:csrf token-repository-ref="customRequestCsrfTokenRepository" request-matcher-ref="customCsrfRequestMatcher" />

Spring security based application having both form login and SSO

I have searched enough but I haven't got a clear answer and thus posting this question.
I have an existing application which uses spring security for authentication.
Current implementation uses a custom implementation of UsernamePasswordAuthenticationFilter for doing this.
Thus the flow is something like below(in very simple terms):
inputrequest>DelegatingFilterProxy>LoginUrlAuthenticationEntryPoint>CustomUsernamePasswordAuthenticationFilter>AuthenticationManager>CustomAuthenticationProvider
Now I have a requirement to implement SSO (since the user is already asusmed to be authenticated) in some scenarios.
The requirement states that if I have a specific request parameter present then I need to automatically authenticate the request without bothering about user/password.
So it is same set of resources and I do not have to authenticate user/password if the specific SSO related request parameter is present.
e.g
suppose a resource \test\bus is a secure resource.
if I come from normal way then we need to check if the user is authenticated or nor and force user to put valid user/password
if I come from SSO channel then I need to show the \test\bus resource as the user is already authenticated.
currently all the access restrictions are put through <http> element
e.g the snippet of security-config.xml is as follows:
Query: What options do I have in this case. I can think of below options:
Pre-authenticate the user before spring security framework kicks in. This will mean creating an authentication token and putting in spring context before spring security filter is called. This can be done through another filter which is called before spring security filter chain. I have tested it and it works.
Create another custom security filter which set-up the authentication token. I am not clear if this is correct approach as not sure when do we create multiple custom security filter
Create another custom authentication provider e.g SSOCustomAuthenticationProvider. This provider will be called in the existing current flow as we can have multiple authentication providers to a authentication manager. The only issue is that in order to achieve this I have to change the request url to authentication filter's target url so that spring security doesn't check for authentication.
to explain more,
let's say request uri is /test/bus, I will write a filter which will intercept the request and change it to /test/startlogin. This is currently my CustomUsernamePasswordAuthenticationFilter's target url i.e
<property name="filterProcessesUrl" value="/test/startlogin"/>
The flow will be
inputrequest>DelegatingFilterProxy>LoginUrlAuthenticationEntryPoint>CustomUsernamePasswordAuthenticationFilter>AuthenticationManager>SSOCustomAuthenticationProvider
I have tested this and this works. Is this a valid approach or a hack.
Is there any other viable option available with me.
Thanks for reading this.

Resources