basic-and-digest-auth.xml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="basic">
  2. <info>
  3. <title>Basic and Digest Authentication</title>
  4. </info>
  5. <para>Basic and digest authentiation are alternative authentication mechanisms which are popular
  6. in web applications. Basic authentication is often used with stateless clients which pass
  7. their credentials on each request. It's quite common to use it in combination with
  8. form-based authentication where an application is used through both a browser-based user
  9. interface and as a web-service. However, basic authentication transmits the password as
  10. plain text so it should only really be used over an encrypted transport layer such as
  11. HTTPS.</para>
  12. <section xml:id="basic-processing-filter">
  13. <info>
  14. <title><classname>BasicAuthenticationFilter</classname></title>
  15. </info>
  16. <para><literal>BasicAuthenticationFilter</literal> is responsible for processing basic
  17. authentication credentials presented in HTTP headers. This can be used for
  18. authenticating calls made by Spring remoting protocols (such as Hessian and Burlap), as
  19. well as normal browser user agents (such as Firefox and Internet Explorer). The standard
  20. governing HTTP Basic Authentication is defined by RFC 1945, Section 11, and
  21. <literal>BasicAuthenticationFilter</literal> conforms with this RFC. Basic
  22. Authentication is an attractive approach to authentication, because it is very widely
  23. deployed in user agents and implementation is extremely simple (it's just a Base64
  24. encoding of the username:password, specified in an HTTP header).</para>
  25. <section xml:id="basic-config">
  26. <info>
  27. <title>Configuration</title>
  28. </info>
  29. <para>To implement HTTP Basic Authentication, you need to add a
  30. <literal>BasicAuthenticationFilter</literal> to your filter chain. The application
  31. context should contain <literal>BasicAuthenticationFilter</literal> and its required
  32. collaborator:</para>
  33. <para> <programlisting language="xml"><![CDATA[
  34. <bean id="basicAuthenticationFilter"
  35. class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
  36. <property name="authenticationManager" ref="authenticationManager"/>
  37. <property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
  38. </bean>
  39. <bean id="authenticationEntryPoint"
  40. class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
  41. <property name="realmName" value="Name Of Your Realm"/>
  42. </bean>]]>
  43. </programlisting> </para>
  44. <para>The configured <interfacename>AuthenticationManager</interfacename> processes each
  45. authentication request. If authentication fails, the configured
  46. <interfacename>AuthenticationEntryPoint</interfacename> will be used to retry the
  47. authentication process. Usually you will use the filter in combination with a
  48. <literal>BasicAuthenticationEntryPoint</literal>, which returns a 401 response with
  49. a suitable header to retry HTTP Basic authentication. If authentication is
  50. successful, the resulting <interfacename>Authentication</interfacename> object will
  51. be placed into the <classname>SecurityContextHolder</classname> as usual.</para>
  52. <para>If the authentication event was successful, or authentication was not attempted
  53. because the HTTP header did not contain a supported authentication request, the
  54. filter chain will continue as normal. The only time the filter chain will be
  55. interrupted is if authentication fails and the
  56. <interfacename>AuthenticationEntryPoint</interfacename> is called.</para>
  57. </section>
  58. </section>
  59. <section xml:id="digest-processing-filter">
  60. <title><classname>DigestAuthenticationFilter</classname></title>
  61. <para><classname>DigestAuthenticationFilter</classname> is capable of processing digest
  62. authentication credentials presented in HTTP headers. Digest Authentication attempts to
  63. solve many of the weaknesses of Basic authentication, specifically by ensuring
  64. credentials are never sent in clear text across the wire. Many user agents support
  65. Digest Authentication, including FireFox and Internet Explorer. The standard governing
  66. HTTP Digest Authentication is defined by RFC 2617, which updates an earlier version of
  67. the Digest Authentication standard prescribed by RFC 2069. Most user agents implement
  68. RFC 2617. Spring Security's <classname>DigestAuthenticationFilter</classname> is
  69. compatible with the "<literal>auth</literal>" quality of protection
  70. (<literal>qop</literal>) prescribed by RFC 2617, which also provides backward
  71. compatibility with RFC 2069. Digest Authentication is a more attractive option if you
  72. need to use unencrypted HTTP (i.e. no TLS/HTTPS) and wish to maximise security of the
  73. authentication process. Indeed Digest Authentication is a mandatory requirement for the
  74. WebDAV protocol, as noted by RFC 2518 Section 17.1.</para>
  75. <para>Digest Authentication is definitely the most secure choice between Form
  76. Authentication, Basic Authentication and Digest Authentication, although extra security
  77. also means more complex user agent implementations. Central to Digest Authentication is
  78. a "nonce". This is a value the server generates. Spring Security's nonce adopts the
  79. following format:</para>
  80. <para>
  81. <programlisting language="txt">
  82. base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
  83. expirationTime: The date and time when the nonce expires, expressed in milliseconds
  84. key: A private key to prevent modification of the nonce token
  85. </programlisting> </para>
  86. <para>The <classname>DigestAuthenticatonEntryPoint</classname> has a property specifying the
  87. <literal>key</literal> used for generating the nonce tokens, along with a
  88. <literal>nonceValiditySeconds</literal> property for determining the expiration time
  89. (default 300, which equals five minutes). Whist ever the nonce is valid, the digest is
  90. computed by concatenating various strings including the username, password, nonce, URI
  91. being requested, a client-generated nonce (merely a random value which the user agent
  92. generates each request), the realm name etc, then performing an MD5 hash. Both the
  93. server and user agent perform this digest computation, resulting in different hash codes
  94. if they disagree on an included value (eg password). In Spring Security implementation,
  95. if the server-generated nonce has merely expired (but the digest was otherwise valid),
  96. the <classname>DigestAuthenticationEntryPoint</classname> will send a
  97. <literal>"stale=true"</literal> header. This tells the user agent there is no need to
  98. disturb the user (as the password and username etc is correct), but simply to try again
  99. using a new nonce.</para>
  100. <para>An appropriate value for <classname>DigestAuthenticationEntryPoint</classname>'s
  101. <literal>nonceValiditySeconds</literal> parameter will depend on your application.
  102. Extremely secure applications should note that an intercepted authentication header can
  103. be used to impersonate the principal until the <literal>expirationTime</literal>
  104. contained in the nonce is reached. This is the key principle when selecting an
  105. appropriate setting, but it would be unusual for immensely secure applications to not be
  106. running over TLS/HTTPS in the first instance.</para>
  107. <para>Because of the more complex implementation of Digest Authentication, there are often
  108. user agent issues. For example, Internet Explorer fails to present an
  109. "<literal>opaque</literal>" token on subsequent requests in the same session. Spring
  110. Security filters therefore encapsulate all state information into the
  111. "<literal>nonce</literal>" token instead. In our testing, Spring Security's
  112. implementation works reliably with FireFox and Internet Explorer, correctly handling
  113. nonce timeouts etc.</para>
  114. <section xml:id="digest-config">
  115. <title>Configuration</title>
  116. <para>Now that we've reviewed the theory, let's see how to use it. To implement HTTP
  117. Digest Authentication, it is necessary to define
  118. <literal>DigestAuthenticationFilter</literal> in the filter chain. The application
  119. context will need to define the <literal>DigestAuthenticationFilter</literal> and
  120. its required collaborators:</para>
  121. <para> <programlisting language="xml"><![CDATA[
  122. <bean id="digestFilter" class=
  123. "org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
  124. <property name="userDetailsService" ref="jdbcDaoImpl"/>
  125. <property name="authenticationEntryPoint" ref="digestEntryPoint"/>
  126. <property name="userCache" ref="userCache"/>
  127. </bean>
  128. <bean id="digestEntryPoint" class=
  129. "org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
  130. <property name="realmName" value="Contacts Realm via Digest Authentication"/>
  131. <property name="key" value="acegi"/>
  132. <property name="nonceValiditySeconds" value="10"/>
  133. </bean>]]>
  134. </programlisting> </para>
  135. <para>The configured <interfacename>UserDetailsService</interfacename> is needed because
  136. <literal>DigestAuthenticationFilter</literal> must have direct access to the clear
  137. text password of a user. Digest Authentication will NOT work if you are using
  138. encoded passwords in your DAO <footnote><para>It is possible to encode the password in the
  139. format HEX( MD5(username:realm:password) ) provided the
  140. <code>DigestAuthenticationFilter.passwordAlreadyEncoded</code> is set to <code>true</code>.
  141. However, other password encodings will not work with digest authentication.</para></footnote>.
  142. The DAO collaborator, along with the <literal>UserCache</literal>, are typically shared directly
  143. with a <classname>DaoAuthenticationProvider</classname>. The
  144. <literal>authenticationEntryPoint</literal> property must be
  145. <classname>DigestAuthenticationEntryPoint</classname>, so that
  146. <classname>DigestAuthenticationFilter</classname> can obtain the correct
  147. <literal>realmName</literal> and <literal>key</literal> for digest
  148. calculations.</para>
  149. <para>Like <literal>BasicAuthenticationFilter</literal>, if authentication is successful
  150. an <interfacename>Authentication</interfacename> request token will be placed into
  151. the <classname>SecurityContextHolder</classname>. If the authentication event was
  152. successful, or authentication was not attempted because the HTTP header did not
  153. contain a Digest Authentication request, the filter chain will continue as normal.
  154. The only time the filter chain will be interrupted is if authentication fails and
  155. the <interfacename>AuthenticationEntryPoint</interfacename> is called, as discussed
  156. in the previous paragraph.</para>
  157. <para>Digest Authentication's RFC offers a range of additional features to further
  158. increase security. For example, the nonce can be changed on every request. Despite
  159. this, Spring Security implementation was designed to minimise the complexity of the
  160. implementation (and the doubtless user agent incompatibilities that would emerge),
  161. and avoid needing to store server-side state. You are invited to review RFC 2617 if
  162. you wish to explore these features in more detail. As far as we are aware, Spring
  163. Security's implementation does comply with the minimum standards of this RFC.</para>
  164. </section>
  165. </section>
  166. </chapter>