I am new to spring. We are building a Mobile-app for our client. The mobile-app will interact with our rest services. But initially, the user should login to the mobile app and then will be able to access the other services.
I have built a Login service which will validate the user credentials with ldap and create the session and the subsequent requests to other services could be consumed.
But if the services are requested anonymously, a specific response object need to be returned.
Currently with below configuration, I am able to return the response code 403.
<beans:bean id="preAuthenticatedProcessingFilterEntryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<security:http use-expressions="true" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint">
<security:intercept-url pattern="/scheduling/**" access="isAuthenticated()" />
</security:http>
But what would be required to respond with a error message in the response body.
I tried to implement the re-direct url, in EntryPoints. But I am not comfortable as the request should not be redirected.
I have a default error Response, which I would need to implement if the anonymous user tries to access services
<ErrorInfo>
<message>Access Denied</message>
<status>403</status>
<url>requested URL</url>
</ErrorInfo>
If I get it right, you want to adjust the response that is currently returned in case of unauthenticated access. In such case you need to implement and register your own AuthenticationEntryPoint or extend Http403ForbiddenEntryPoint you are currently using and override commence method to return response containing also required body.
<beans:bean id="yourCustomEntryPoint" class="com.example.YourCustomEntryPoint" />
<security:http use-expressions="true" entry-point-ref="yourCustomEntryPoint">
<security:intercept-url pattern="/scheduling/**" access="isAuthenticated()" />
</security:http>
Related
The issue I'm having has been discussed several times on this site, however most posts are quite old. Here is something similar to what I'm experiencing. I'm using WSO2 IS 5.2 as my IdP and I have 2 java based web applications hosted on difference servers that participate in SSO. Each webapp (SP) has implemented the Spring-SAML extension. Single Sign-On works perfectly but Single Logout only partially works. Here is the test case:
Access secure resource on webapp1
Login page from Idp (WSO2) is presented and user logs in
Secure resource from webapp1 is presented
Access secure resource on webapp2
SAML request is sent to Idp, Idp responds and user is authenticated
Secure resource from webapp2 is presented, end SSO
Initiate single log out from webapp2
Webapp2 send saml request (through browser) to Idp and saml response is returned
User is logged off locally on webapp2 and Idp session is terminated
The IdP directly sends logout request to webapp1 (back-channel type)
Logout request fails to webapp1 (log indicate SamlStatusException: No user is logged in)
So the end result is that I still have a local session on webapp1. If I change the order and initiate SLO from webapp1, then webapp1 will be logged out and webapp2's local session will continue to exist. The WSO2 server is able to determine the 2nd session participant during SLO, however the HTTP request sent from the Idp to the 2nd session participant does not have a Spring security context. This would be a stateless HTTP request so there wouldn't be a logged in user. This is why I believe it is failing.
I found this discussion. Its about 2 years old. Is there anything new on this issue? Maybe a configuration step missed by me on WSO2 or in the Spring-saml config.
Here is a relevant piece of my SP metadata:
<md:SingleLogoutService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"/>
<md:SingleLogoutService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SingleLogout" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</md:NameIDFormat>
<md:AssertionConsumerService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" isDefault="true" index="0"/>
<md:AssertionConsumerService Location="https://tpap10-wwwdev04.arbfile.org:443/webapp/saml/SSO" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" index="1"/>
Some relevant Spring-Saml config on the SP:
<bean id="metadataGeneratorFilter" class="org.springframework.security.saml.metadata.MetadataGeneratorFilter">
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.MetadataGenerator">
<property name="entityId" value="urn:webapp1:mycity"/>
<property name="entityBaseURL" value="https://wwwdev04.domain.org:443/webapp" />
<property name="extendedMetadata">
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<!-- <property name="signMetadata" value="false"/> -->
<property name="idpDiscoveryEnabled" value="false"/>
</bean>
</property>
</bean>
</constructor-arg>
</bean>
WSO2 was not implementing the SAML 2.0 specification correctly. The specification requires that Single Logout with HTTP-* bindings is done using front-end channel (= through user's browser) - which makes the HTTP session available and allows Spring SAML to terminate it correctly. I believe that this issue was never fixed in WSO2.
Spring SAML uses HttpSession for storage of user's state by default. This is also the reason why Spring SAML doesn't support Single Logout with SOAP binding out of the box. It would be possible to implement an application-wide storage of Spring Security sessions which could be invalidated independently from the HttpSession (and therefore work-around the WSO2's limitation), but this is not configured by default (and I have never tried it).
I made a mvc web app based on this example:
https://github.com/OfficeDev/PnP/tree/master/Samples/MicrosoftGraph.Office365.Generic/OfficeDevPnP.MSGraphAPIDemo
Strange thing is when I work from localhost then all the auth2 authentication works. When I deploy on Azure this happens:
On first page call on Azure I get the response:
An invalid request URI was provided. The request URI must either be an absolute URI or BaseAddress must be set.
On second page call the message:
IDX10803: Unable to create to obtain configuration from: '__AADInstance____AuthenticationContext__/.well-known/openid-configuration'.
I've already seen this post on SO, but I've already set the tenant GUID in the configuration and the AAD privileges are "read directory data" and "sign in and read user profile"
Are there any configuration options on Azure maybe in the new management portal that I should grant?
I have a single tenant addin and this keys in web.config:
<add key="ida:AADInstance" value="https://login.microsoftonline.com/" />
<add key="ida:AuthenticationContext" value="https://login.microsoftonline.com/common" />
<add key="ida:TenantId" value="GUID..." />
<add key="ida:PostLogoutRedirectUri" value="https://localhost:44300/" />
<add key="ida:MicrosoftGraphResourceId" value="https://graph.microsoft.com" />
I tried the section authorization/authentication in the new management portal to enable app service authentication with aad
and could enter the first site of the addin, but the authorization code from my addin was not called and specific file functions don't work if you rely on the portal authorization.
The web site contextPath is root, http://localhost:8080, use Spring security SAML implemented single sign on. Whatever the url enter under the localhost:8080 root path, it will direct to IDP provider for authentication which is correct so far.
What I want is under localhost:8080/unsecure directory, users can access without need to redirect to IDP for authentication. I don't know where to configure to tell SAML skip certain path.
In your security-applicationContext.xml file you must have mapped urls something like this while configuring spring-security-saml:
<!-- Unsecured pages -->
<security:http security="none" pattern="/favicon.ico"/>
<security:http security="none" pattern="/images/**"/>
<security:http security="none" pattern="/css/**"/>
<security:http security="none" pattern="/logout.jsp"/>
<!-- Security for the administration UI -->
<security:http pattern="/saml/web/**" use-expressions="false">
<security:access-denied-handler error-page="/saml/web/metadata/login"/>
<security:form-login login-processing-url="/saml/web/login" login-page="/saml/web/metadata/login" default-target-url="/saml/web/metadata"/>
<security:intercept-url pattern="/saml/web/metadata/login" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<security:intercept-url pattern="/saml/web/**" access="ROLE_ADMIN"/>
<security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
</security:http>
<!-- Secured pages with SAML as entry point -->
<security:http entry-point-ref="samlEntryPoint" use-expressions="false">
<security:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<security:custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
<security:custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
</security:http>
Here we have allowed images, css, favicon etc to be available without login. So add more URLs to the unsecured mapping list if you want it to be available without authentication.
I have spring security implemented in my application, and you can logged with twitter facebook o normal, if you sign in with your email and password there aren't any problem, but if you logged with twitter,the url interceptor don't let see that page.
I have this code when you logged with twitter in my controller in java.
Authentication authentication = new UsernamePasswordAuthenticationToken(userRegister.getEmail(), "ROLE_USER");
SecurityContextHolder.getContext().setAuthentication(authentication);
And this is my url:interceptor in my spring-security.xml
<security:intercept-url pattern="/member/**" access="hasRole('ROLE_USER')" />
Anybody can help me?
Thanky yoU!
I am developing two web applications where one is a server app and the other is a client app, both are using Spring Security. My use case is such that after a user logs into the server app, the user can then access the client app from links within the server app. Since the user should not have to log in again when they click on these links (part of my requirements), I decided to use a strategy similar to Single SignOn in order to forward their authentication information from the server app to the client app.
On the client app, I am using Spring Security's RequestHeaderAuthenticationFilter to look for a custom request header that is set by the server app.
If this custom header is found, do I have to do any further validation that this request is trustworthy? In Spring's Pre-Authentication doc, RequestHeaderAuthenticationFilter does not perform any authentication and will assume the request to be from the user specified in the SM_USER attribute. How do I ensure that the request is genuine?
How do I send the user from one app to another with a custom header in the http request? Redirecting the request does not work as the header information will be lost. Forwarding does not work as the forwarded request does not go through the configured Spring Security filters on the client app, thus the request is never "authenticated" and no session is created.
Since I didn't receive any responses, I changed my approach slightly in order to achieve the same SSO behavior. I am answering my own question here to close this issue.
Instead of using the RequestHeaderAuthenticationFilter, I subclassed Spring's AbstractPreAuthenticatedProcessingFilter which retrieves the Principal and Credentials from the HttpRequest. I then implemented a custom preAuthenticatedUserDetailsService that will validate the Credentials with the server app before loading the UserDetails.
As for #2, I am no longer using custom headers in the initial pre-authenticated login request. I am simply appending the principal (username) and credentials as url parameters to the initial pre-authenticated "login" request to the client app. Since the communicated between the two apps are secured via SSL, I figured that should be safe.
This is what my security configuration looks like now:
<b:bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<b:bean id="navigatorPreAuthFilter" class="com.example.NavigatorPreAuthenticatedProcessingFilter">
<b:property name="authenticationManager" ref="authenticationManager" />
</b:bean>
<http auto-config="false" entry-point-ref="http403EntryPoint">
<custom-filter position="PRE_AUTH_FILTER" ref="navigatorPreAuthFilter" />
<session-management session-fixation-protection="newSession" />
<logout logout-success-url="/logout" delete-cookies="JSESSIONID" />
<intercept-url pattern="/index.jsp" access="ROLE_QUESTIONNAIRE_ASSIGNEE"/>
</http>
<b:bean id="preAuthenticatedUserDetailsService" class="com.example.NavigatorPreAuthenticatedUserDetailsService" />
<b:bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<b:property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService" />
</b:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="preauthAuthProvider"/>
</authentication-manager>