How to disable fallback to NTLM on Spring Security configured with Kerberos? - spring

I have a Spring App configured with Kerberos and it's working fine for users joined to the AD domain. There are other users who access to the app outside the domain, so Kerberos will not work and they should be prompted for user and password (html form).
If found that in some cases (depending on the browser) this procedure fails with a GSSException: Defective token detected (Mechanism level: GSSHeader did not find the right tag).
It seems that the browser fails to use kerberos (that's ok because the user is not joined to the domain) and tries to send NTLM token to the App (SpnegoAuthenticationProcessingFilter:149 - Negotiate Header was invalid: Negotiate TlRMTVNTUAABAAAAl4II4gAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==) which is not recognized as a Kerberos valid token so it fails with the GSSException.
There are lot of references to this issue in Internet (here, here, and here) and most of them suggest to fix the kerberos issue, but in my case this is not a kerberos issue because there are users that are not joined to the domain.
So, is there any way to force the kerberos fallback to the html form instead of sending the NTLM token ?
This is my configuration block on the spring-security.xml
<http entry-point-ref="spnegoEntryPoint" use-expressions="true">
<intercept-url pattern="/logout" access="permitAll"/>
<intercept-url pattern="/login" access="permitAll"/>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<form-login login-page="/login"/>
<custom-filter ref="spnegoAuthenticationProcessingFilter" before="BASIC_AUTH_FILTER" />
<csrf disabled="true"/>
</http>

Related

Spring OAuth2 token without ClientId and ClientSecret for External Clients

We have OAuth token generation using Spring which accepts Username/Password/ClientId/Secret, which works perfect. For External Client we just need input as username and password and generate OAuth Token.
<security:http pattern="/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<security:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<security:anonymous enabled="false" />
<security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request parameters -->
<security:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>
Below is the new code that we need to add, but it is asking for username and password in browser.
<security:http pattern="/**external**/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<security:intercept-url pattern="/external/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<security:anonymous enabled="false" />
<security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<security:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>
Please guide if we can generate OAuth without clientId and internally pass clientId to generate OAuth.
You can never generate an OAuth token without a clientId! Oauth2 has 3 ways of creating a token, Implicit, Code, and user/pass. The last should be avoided, since it means that the Oauth client will get access to the user's credentials, and OAuth was built to prevent exactly that. Implicit token are granted using only the user's credentials (typically involving only the browser). In Code-mode the OAuth client received a code (should not be in a browser), which is then exchanged to a Token. The code to Token exchange require that the Oauth client authenticates, using it's clientId and a secret, this is typically done using Basic Authentication.
I think what you need is Resource Owner Password grant type which is explained in https://www.rfc-editor.org/rfc/rfc6749#section-1.3.3
Resource Owner Password grant type should only be used with the trusted clients. So if the external client you are talking about is a trusted client (Like a native mobile app developed by the same company. ex. Facebook Mobile App), this can be used.
Flow is explained in https://www.rfc-editor.org/rfc/rfc6749#section-4.3.1
The most important aspect of Resource Owner grant type is client should not store user name and password.

Configuring HTTP pages and HTTPS pages with Spring Security

I have successfully setup an application using Spring Security. When users request the secured pages, Spring automatically redirects these users to a HTTPS page.
<http auto-config="true" use-expressions="true" once-per-request="true" >
<intercept-url pattern="/login" access="permitAll" requires-channel="https"/>
<intercept-url pattern="/my-account" access="isAuthenticated()" requires-channel="https"/>
<logout />
<form-login login-page="/login" />
<port-mappings>
<port-mapping http="8080" https="8443"/>
<port-mapping http="80" https="443"/>
</port-mappings>
</http>
But when the users navigate, the next other pages that does not have sensitive information are still using HTTPS. I would like these normal pages accessed using just HTTP.
Is any intelligent way to do that? All the other pages that I do not configured as HTTPS channel I would like to be accessed using just HTTP. I tried to use some wildcards but without success.
Extra detail:
HTTPS uses more server CPU. I have a lot of requests on some pages and I would like to avoid this extra cost.
Make your entire site HTTPS. Performance change is minimal these days and you won't screw over your users by exposing their session cookies over HTTP.
https://istlsfastyet.com/
In Spring-Security, you can do this way -
<http auto-config="true" use-expressions="true" once-per-request="true" >
<intercept-url pattern="/login" access="permitAll" requires-channel="https"/>
<intercept-url pattern="/my-account" access="isAuthenticated()" requires-channel="https"/>
<intercept-url pattern="/**" access="permitAll" requires-channel="http"/>
All other url's besides "/login" and "/my-account" will be served over http.
In addition to this, you must set the secure flag for the cookie.
By setting the secure flag, the browser will prevent the transmission of a cookie over an unencrypted channel.
https://www.owasp.org/index.php/SecureFlag

Is it possible to use HTTPS only for login in Spring security?

My requirement is to secure only the login page to protect user credentials. After successful login, the user can access to the restricted pages but in http mode.
It is a requirement because of SSL overload. Users need to access to protected pages which contains a lot of data.
I would like to know whether it is possible to do although it isn't as secure as maintain https context.
This is my config:
<security:http auto-config="true">
<security:intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
<security:intercept-url pattern="/welcome*" access="ROLE_USER, ROLE_ADMIN" />
<security:form-login login-page="/login" authentication-failure-handler-ref="customAuthenticationFailureHandler" default-target-url="/welcome" />
<security:access-denied-handler ref="openIdAuthFailureHandler"/>
</security:http>
If I try to set /login as https, everything is in https mode. How can I manage to do that?
Edit:
As s.kwiotek suggested I added requires-channel="http" to the other url patterns:
<security:http auto-config="true">
<security:intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
<security:intercept-url pattern="/welcome*" access="ROLE_USER, ROLE_ADMIN" requires-channel="http"/>
<security:intercept-url pattern="/user/*" access="ROLE_USER, ROLE_ADMIN" requires-channel="http" />
<security:intercept-url pattern="/rest/*" access="ROLE_USER, ROLE_ADMIN" requires-channel="http" />
<security:intercept-url pattern="/admin/*" access="ROLE_ADMIN" requires-channel="http" />
<security:session-management session-fixation-protection="none"/>
<security:port-mappings>
<security:port-mapping http="8080" https="8443"/>
</security:port-mappings>
<security:form-login login-page="/login" authentication-failure-handler-ref="customAuthenticationFailureHandler" always-use-default-target="true" default-target-url="/user/home" />
<security:logout logout-success-url="/" />
<security:access-denied-handler ref="openIdAuthFailureHandler"/>
</security:http>
I added the session-fixation-protection="none" because If I only include requires-channel="http" it doesn't go further from the login. I try to log in but I come back to the login.
If I add the session-fixation-protection it goes to the user's home but at the second login attempt. When you access to /myapp/login two jsessionid are created:
JSESSIONID=5B37413F33DF0AA45F31D711754C3704; path=/myapp; domain=localhost
JSESSIONID=658F9F8669AF6B296A77D448C1A64B71; path=/myapp/; domain=localhost; HttpOnly
Then I try to log in and I come back to the log in but the url is different:
https://myapp/login;jsessionid=C1EC352C42D6AC379DB1B65A9295E8A1
When the jsessionid is in the URL, I try to log in and I'm successfully redirected to the users'home (/user/home). If I remove the session-fixation-protection, the jessesionid is in the URL but I'm not successfully redirected to the user's home.
I don't know who creates the two first jsessionid and how to explain this behaviour. The only thing I want to do is to secure the login by ssl and then access by http.
(This should have been a comment. But my account is limited in reputation.)
You may want to reconsider allowing access to the restricted pages in http mode.
According to http://www.troyhunt.com/2011/11/owasp-top-10-for-net-developers-part-9.html,
Many people think of TLS as purely a means of encrypting sensitive user data in transit. For example, you’ll often see login forms posting credentials over HTTPS then sending the authenticated user back to HTTP for the remainder of their session. The thinking is that once the password has been successfully protected, TLS no longer has a role to play. The example above shows that entire authenticated sessions need to be protected, not just the credentials in transit. This is a lesson taught by Firesheep last year and is arguably the catalyst for Facebook implementing the option of using TLS across authenticated sessions.
Try for Example:
<security:intercept-url pattern="/**" access="ROLE_USER" requires-channel="http"/>

Force SSL based on url pattern in Spring security 3.2?

I am trying to configure my SS3.2 to do something quite simple: reject any HTTP request that's not directed at my login service; and allow access to the login service without authorization.
I have the following in my security.xml:
<http pattern="/login/**" security="none" />
<!--
<intercept-url pattern="/login/**" access="permitAll" requires-channel="https"/>
-->
<http auto-config="true" use-expressions="true">
<custom-filter ref="myCustomFilter" before="BASIC_AUTH_FILTER" />
</http>
Now since the login service will transport authentication information, it obviously needs to be secured by SSL/TLS. But I can't figure out how to force it to use SSL/TLS, while still letting it skip the custom filter.
Any suggestions?

Support SAML SSO and normal login

I have an application which is accessed by two types of users, internal and external.
I need to authenticate external users using SAML.
I need to authenticate internal users with the normal form-based login. My application need to support both types of users. I use spring security frame work.
Is it possible to support both types of users? if so can you suggest the approach at high level? Thanks.
You can easily enable support for both form and SAML authentication with configuration similar to this:
<http entry-point-ref="authenticationEntryPoint" authentication-manager-ref="authenticationManager">
<intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY"/>
<form-login login-page="/login" />
<custom-filter before="FIRST" ref="metadataGeneratorFilter"/>
<custom-filter after="BASIC_AUTH_FILTER" ref="samlFilter"/>
</http>
Make sure that your AuthenticationManager contains the samlAuthenticationProvider. And of course include other configuration parts from the Spring SAML sample application.
You can then create your custom login page which presents user with username+password fields for form-based authentication and a link/picture (or multiple of them) which initialize authentication with the IDP (by redirecting user to scheme://host:port/saml/login?idp=selectedIdpEntityId).
Your users then decide which one to use - depending on whether they's internal or external.
The part of Spring SAML documentation touching on this subject is in chapter Spring Security integration.

Resources