adaptive.adoc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. = Adaptive Authentication
  2. Since authentication needs can vary from person-to-person and even from one login attempt to the next, Spring Security supports adapting authentication requirements to each situation.
  3. Some of the most common applications of this principal are:
  4. 1. *Re-authentication* - Users need to provide authentication again in order to enter an area of elevated security
  5. 2. *Multi-factor Authentication* - Users need more than one authentication mechanism to pass in order to access secured resources
  6. 3. *Authorizing More Scopes* - Users are allowed to consent to a subset of scopes from an OAuth 2.0 Authorization Server.
  7. Then, if later on a scope that they did not grant is needed, consent can be re-requested for just that scope.
  8. 4. *Opting-in to Stronger Authentication Mechanisms* - Users may not be ready yet to start using MFA, but the application wants to allow the subset of security-minded users to opt-in.
  9. 5. *Requiring Additional Steps for Suspicious Logins* - The application may notice that the user's IP address has changed, that they are behind a VPN, or some other consideration that requires additional verification
  10. [[re-authentication]]
  11. == Re-authentication
  12. The most common of these is re-authentication.
  13. Imagine an application configured in the following way:
  14. include-code::./SimpleConfiguration[tag=httpSecurity,indent=0]
  15. By default, this application has two authentication mechanisms that it allows, meaning that the user could use either one and be fully-authenticated.
  16. If there is a set of endpoints that require a specific factor, we can specify that in `authorizeHttpRequests` as follows:
  17. include-code::./RequireOttConfiguration[tag=httpSecurity,indent=0]
  18. <1> - States that all `/profile/**` endpoints require one-time-token login to be authorized
  19. Given the above configuration, users can log in with any mechanism that you support.
  20. And, if they want to visit the profile page, then Spring Security will redirect them to the One-Time-Token Login page to obtain it.
  21. In this way, the authority given to a user is directly proportional to the amount of proof given.
  22. This adaptive approach allows users to give only the proof needed to perform their intended operations.
  23. [[multi-factor-authentication]]
  24. == Multi-Factor Authentication
  25. You may require that all users require both One-Time-Token login and Username/Password login to access any part of your site.
  26. To require both, you can state an authorization rule with `anyRequest` like so:
  27. include-code::./ListAuthoritiesConfiguration[tag=httpSecurity,indent=0]
  28. <1> - This states that both `FACTOR_PASSWORD` and `FACTOR_OTT` are needed to use any part of the application
  29. Spring Security behind the scenes knows which endpoint to go to depending on which authority is missing.
  30. If the user logged in initially with their username and password, then Spring Security redirects to the One-Time-Token Login page.
  31. If the user logged in initially with a token, then Spring Security redirects to the Username/Password Login page.
  32. [[authorization-manager-factory]]
  33. === Requiring MFA For All Endpoints
  34. Specifying all authorities for each request pattern could be unwanted boilerplate:
  35. include-code::./ListAuthoritiesEverywhereConfiguration[tag=httpSecurity,indent=0]
  36. <1> - Since all authorities need to be specified for each endpoint, deploying MFA in this way can create unwanted boilerplate
  37. This can be remedied by publishing an `AuthorizationManagerFactory` bean like so:
  38. include-code::./UseAuthorizationManagerFactoryConfiguration[tag=authorizationManagerFactoryBean,indent=0]
  39. This yields a more familiar configuration:
  40. include-code::./UseAuthorizationManagerFactoryConfiguration[tag=httpSecurity,indent=0]
  41. [[enable-global-mfa]]
  42. === @EnableGlobalMultiFactorAuthentication
  43. You can simplify the configuration even further by using `@EnableGlobalMultiFactorAuthentication` to create the `AuthorizationManagerFactory` for you.
  44. include-code::./EnableGlobalMultiFactorAuthenticationConfiguration[tag=enable-global-mfa,indent=0]
  45. [[obtaining-more-authorization]]
  46. == Authorizing More Scopes
  47. You can also configure exception handling to direct Spring Security on how to obtain a missing scope.
  48. Consider an application that requires a specific OAuth 2.0 scope for a given endpoint:
  49. include-code::./ScopeConfiguration[tag=httpSecurity,indent=0]
  50. If this is also configured with an `AuthorizationManagerFactory` bean like this one:
  51. include-code::./MissingAuthorityConfiguration[tag=authorizationManagerFactoryBean,indent=0]
  52. Then the application will require an X.509 certificate as well as authorization from an OAuth 2.0 authorization server.
  53. In the event that the user does not consent to `profile:read`, this application as it stands will issue a 403.
  54. However, if you have a way for the application to re-ask for consent, then you can implement this in an `AuthenticationEntryPoint` like the following:
  55. include-code::./MissingAuthorityConfiguration[tag=authenticationEntryPoint,indent=0]
  56. Then, your filter chain declaration can bind this entry point to the given authority like so:
  57. include-code::./MissingAuthorityConfiguration[tag=httpSecurity,indent=0]
  58. [[custom-authorization-manager-factory]]
  59. == Programmatically Decide Which Authorities Are Required
  60. `AuthorizationManager` is the core interface for making authorization decisions.
  61. Consider an authorization manager that looks at the logged in user to decide which factors are necessary:
  62. include-code::./CustomAuthorizationManagerFactory[tag=authorizationManager,indent=0]
  63. In this case, using One-Time-Token is only required for those who have opted in.
  64. This can then be enforced by a custom `AuthorizationManagerFactory` implementation:
  65. include-code::./CustomAuthorizationManagerFactory[tag=authorizationManagerFactory,indent=0]