Spring Security - Secure Remote Password protocol - SRP - Authentication Provider
Asked Answered
R

2

7

When asking this question I am looking for guidance with implementation of my own AuthenticationProvider. By that I mean the following:

Till now I have learned that Spring Security ask the AuthenticationProvider object if the user is authenticated or not. Currently I am using the DaoAuthenticationProvider which process the username and the password that is being returned by my own custom UserDetailService. All works great! Spring support a lot of different AuthenticationProvider's for example there is one for LDAP, Jdbc, DAO (as mentioned above) and i was even able to find one for Kerberos. However there is no authentication provider for SRP, thus the need to write one.

My question is here the following:

When we use the DaoAuthenticationProvider i.e. user/password authentication, we have a html form where the username and password are entered and then a button is responsible for submitting those 2 parameters. Both parameters are transferred over some transport channel to the server i.e. with one click we are able to send all of the data within the same http request i.e. all that is needed for the authentication. That can be seen in the UsernamePasswordAuthenticationFilter. Here the method "attemptAuthentication" takes "HttpServletRequest request" which includes username and password. Till now all good.

 public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        ...
        }
    

Well, in the simple in SRP we have also a form that has a username and password, except the password !!!MUST!!! not be transferred over the network. In order to achieve that constrain a "discussion" between the client and the server has to take place i.e. the following parameters must be exchanged.

  1. username (I),

  2. a value called "A"

  3. a value called "B"

  4. a value called "M1"

  5. a value called "M2"

Well, let us assume that there is a filter called "SrpAuthenticationProcessingFilter" how should the filter look like if the new authentication protocol was more like a conversation by that I mean from the RFC 5054.

   Client                                            Server

   Client Hello (I)        -------->
                                               Server Hello
                                               Certificate*
                                        Server Key Exchange (N, g, s, B)
                           <--------      Server Hello Done
   Client Key Exchange (A) -------->
   [Change cipher spec]
   Finished                -------->
                                       [Change cipher spec]
                           <--------               Finished

   Application Data        <------->       Application Data

Here we have a client that needs to

  • a) send first his username (I)
  • b) then the server needs to respond with a value B. (N,g,s are not really necessary in this case)
  • c) the client sends it's "value A"
  • d) the the client uses that value B from the server and based on that value calculates a key.
  • e) the server calculates the key as well based on the value A.
  • f) the client sends value M1 to the server.
  • g) the server gets the M1 value and based on a formula which has the M1 value as argument, he is able to verify if the keys match, if the calculated keys of the bought sides match then the user is authenticated, and the product i.e. the shared key could be used further for other processing.

In a contrast to username and password authentication those are 7 steps not one. And 3 of those needs to happen before the SrpAuthenticationProcessingFilter. Now I am aware that there is a possibility to send the username together with the "value A" thus shortening the number of steps, but I would like to strictly follow the RFC. Never take the easy way right?

The question really is where do I place that code which is responsible for the ping pong (conversation) between the client and the server i.e. the first 3 steps a, b and c mentioned above. Should it place them in a SrpEntryPoint object, or somewhere else. if else then were in the context of SpringSecurity?

One way I can thing of solving this is using websockets, but I would also like to make that authentication independent from any layer 5-7 protocol such as websockets, http, spdy etc. . That means that the first implementation should be be through simple http request/response and then with any other protocol.

So the structure that could be the right one in order to implement SRP currently is:

  • SRPAuthenticationEntryPoint implements org.springframework.security.web.AuthenticationEntryPoint - this basically says what should be done if a request for a protected resource gets in, but the user is not authenticated yet. Here we can place a redirect in the case the resource has not been authenticated. Maybe this is also the place which is responsible for the steps a,b,c not sure if that is the right place. Request guidance and information!!

  • SrpAuthenticationProcessingFilter extends GenericFilterBean. SrpAuthenticationProcessingFilter exists to make partial validation for example to check if the srp parameters received a correct and corresponding to the srp parameters that the server sets. Here it is important to mention that SrpAuthenticationProcessingFilter is not doing any username validation i.e. that needs to happen in one step before the SrpAuthenticationProcessingFilter is being called, maybe that is the SrpEntryPoint or some other step that I do not know how to call it yet. SrpAuthenticationProcessingFilter has a method "doFilter" in which the second structure is being created i.e. SrpAuthenticationToken.

  • SrpAuthenticationToken extend org.springframework.security.authentication.AbstractAuthenticationToken. That token in my understanding is something similar to the DAO object, the token maps all field needed for successful authentication. When partially validated parameters are populated into the SrpAuthenticationToken that SrpAuthenticationToken is passed to the authenticate method of the org.springframework.security.authentication.AuthenticationManager interface i.e. something like that

    myAuthentication = authenticationManager.authenticate(SrpAuthenticationToken);

depending on which Authentication Provider is configured in the Spring Security config then the SrpAuthentication provider is called in our case i.e.:

@Autowired
public void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth
          .authenticationProvider(sRPAuthenticationProvider);
}
  • SRPAuthenticationProvider - implements org.springframework.security.authentication.AuthenticationProvider. Over here the steps d,e,f and g are being validated and compared. If something wrong happens then throw new BadCredentialsException("Invalid username/password/Verifiere") exception.

  • SrpSessionValidator - this one is responsible only for validating particular parameters of the Srp session and would be called from SrpAuthenticationProcessingFilter as well as in one step before the SrpAuthenticationProcessingFilter in order to validate if the username exists in the database at all.

I only have a general idea how to implement that Srp authentication, and thus I would like some comments if that makes sense at all and if SRPAuthenticationEntryPoint is the right place for the steps a,b and c. It does not feel like the right place to me.

Any feedback is greatly appreciated.

Addition1 (21 November 2014) -> As an answer to the question "where to place that code which is responsible for the ping pong (conversation) between the client and the server i.e. the first 3 steps a,b and c " the answer to that would be most likely a standard (I will call it negotiation) filter which will take that job.

Now I would like to rephrase the question i.e. before the authentication is complete and before the M1 and M2 messages are received i.e. steps 1 2 and 3. Where do I place that object? I.e. it should be a place where the object should live for example for 60 seconds and then be automatically deleted in case no M1 and M2 messages has been received. I mean some object before the "SecurityContextHolder" object. I just do not know what is the name of that object/context related to spring security, also I do not know if such construct exists at all?

Rumormonger answered 20/10, 2014 at 8:42 Comment(1)
I know it's been a lot of time but what's the current state of your implementation? Were you able to finish it? Do you have any repositories that I can look at?Videogenic
L
2

My approach would be to use AJAX to run the first parts of the protocol up to the creation of A and M1 at the client then post those to the server as the login credentials and check those using Spring Security.

To see how this works there is a junit-js test which runs mutual authentication between a javascript client object and a java server object using Thinbus over at TestSRP6JavascriptClientSessionSHA256.js (note the maven build runs this unit test using the JDK javascript runtime):

    // note the following exchange is written in javascript calling client js and invoking server java which is run by JUnit-JS using the JDK javascript runtime so it shows both sides of the full authentication in one unit test method

    // normal login flow step1a client: browser starts with username and password given by user at the browser
    client.step1(username,password);

    // normal login flow step1b server: server starts with username from browser plus salt and verifier saved to database on user registration. 
    var B = server.step1(username, salt, v);

    // normal login flow step2a client: server sends users salt from user registration and the server ephemeral number
    var credentials = client.step2(salt, B);

    // normal login flow step2b server: client sends its client ephemeral number and proof of a shared session key derived from both ephermal numbers and the password
    var M2 = server.step2(credentials.A, credentials.M1);

    // normal login flow step3 client: client verifies that the server shows proof of the shared session key which demonstrates that it knows actual verifier
    client.step3(M2);

Clearly the javascript client starts with only username and password. The server uses the username to resolve the salt and generates a random B. The client is given salt and B from the server and generates its random A and the M1 which is the password proof. The server step2 which takes M1 as a parameter is the server checking the user password proof and it will throw an exception if the proof is bad. The server then sends M2 which is the server proof that it has the user verifier v which is done to prevent a fake server spoofing the real server.

There is a demo of a browser doing SRP to a Java server over AJAX using Thinbus over at thinbus-srp-js-demo. You could re-use the JAX RS with AJAX approach (e.g. Spring MVC AJAX) to perform the first steps up to the creation of A+M1 at the client then post those to Spring Security using the login form post and have Spring Security verify A+M1 by running step2 on the server object as shown in the junit-js test. Then your AuthenticationManager could resolve the server object created by AJAX from a concurrent map keyed by username.

One minor note is that I would consider checking the server proof M2 as optional if you are using HTTPS to a server. If you are not using HTTPS then server spoofing means they can give the user a page which sends the password and ignores a bad M2; so the M2 proof doesn't provide security in the context of webpages. A mobile app which packages the html/js into a native app using something like phone gap would benefit from an M2 check; it can be added into the page after the user is logged in to be checked by the trusted code.

Leucite answered 20/12, 2014 at 21:29 Comment(9)
Simon, thank you for your post. Thinbus is a good example for tests and for making the live easier on the client side however there is one problem with it. The source of randomness i.e. the small "a" and small "b". i.e. those one time ephemeral keys. Those are not really as much random as required in Thinbus. That is the reason why i decided to go with another java script srp implementation. Nevertheless i agree with your sгggestion up to the last paragraph.Rumormonger
Thus those checks must be mandatory in any implementation and nothing else. My question was more about the spring implementation of the SRP (which does not exists yet) i.e. about the "ping pong (conversation) between the client and the server i.e. the first 3 steps a,b and c " but related to the server side not on the client side. However i believe we will have the opportunity to discuss that with you, some other time :).Rumormonger
I think if you read the SRP papers again you will find that M2 is different from M1: so that the server says something the client can verify. If the server said the same thing the client said it wouldn't prove anything to the client. Give that s, A, B are shared that the server can prove is that it knows V and the client can prove it knows the password.Leucite
you are completely right and i made a mistake. What i needed to write here is that the key "K" needs to be verified that it is the same key on bought sides. I am deleting the message above in order to avoid confusion of other users i.e. the correct version is K (alice) must be equal to K (bob) i.e. Ka == Kb. That verification is done trough M1 and M2 message exchange. Thank you for that catch.Rumormonger
nevertheless i still strongly believe that the need of validating the server proof i.e. M2 must be mandatory in any implementation.Rumormonger
You are looking at an older RFC for TSL. Use srp.stanford.edu/design.html instead. You are replacing a spring security plain text password proof so you only need a password proof which is M1. Checking M2 only shows the server knows the verifier which can happen with a man-in-the-middle attack which you can counter with HTTPS. With HTTPS the M2 check is redundant as the server is assured. You should also reuse peer reviewed code as bugs and knowledge gaps in your security code may be exploited.Leucite
Simbo Thank you for your responce. Well that is not completelly true. You can have man in the middle with completelly valid certificate. Lets suppose that you are using a DH key exchange and someone with a valid certаicate, does man in the middle, without you even noticing that (except certificate pinning is implemented on the client side, here i am not talking about CA Notary etc. ).Rumormonger
number of such attacks occurred in the past, just search wikipedia for comodo, DigiNotar and RSA etc. i.e. all those cases where one of those CA which comes pre installed in your browser gets nailed. Then https becomes just one of those nice empty phrases. Yup. Do you now agree that we do need to check M2, or do you still believe that if you see the lock in your web browser all seems to be normal and well.Rumormonger
My answer pertains to password proofs with srp and spring security. The rest of the discussion I find confusing and will end. Good luck with your implementation.Leucite
Y
2

There is a spring security SRP implimentation at https://bitbucket.org/simon_massey/thinbus-srp-spring-demo

The readme page says:

A salient feature of the integration is that there are no changes to the standard spring security authentication path other than to configure the custom SrpAuthenticationProvider.

It also says:

Spring Security does not expose the user HTTPSession to the AuthenticationProvider. So demo code uses a Guava cache with a timeout to hold the SRP6JavascriptServerSession for the brief period of the login exchange. As of Thinbus 1.2.1 the session is serialisable so an alternative approach for a large stateless website would be to hold the SRP6JavascriptServerSession object in the DB rather than in an in-memory cache.

Yuk answered 5/10, 2015 at 21:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.