diff --git a/docs/manual/src/docs/asciidoc/_includes/about/authentication/password-storage.adoc b/docs/manual/src/docs/asciidoc/_includes/about/authentication/password-storage.adoc index b961ca5a12..6c512d1c04 100644 --- a/docs/manual/src/docs/asciidoc/_includes/about/authentication/password-storage.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/about/authentication/password-storage.adoc @@ -146,15 +146,15 @@ All of the original passwords are `password`. ---- ==== -<1> The first password has a `PasswordEncoder` id of `bcrypt` and an encoded password value of `$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG`. +<1> The first password has a `PasswordEncoder` id of `bcrypt` and an `encodedPassword` value of `$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG`. When matching, it would delegate to `BCryptPasswordEncoder` -<2> The second password has a `PasswordEncoder` id of `noop` and encoded password value of `password`. +<2> The second password has a `PasswordEncoder` id of `noop` and `encodedPassword` value of `password`. When matching, it would delegate to `NoOpPasswordEncoder` -<3> The third password has a `PasswordEncoder` id of `pbkdf2` and encoded password value of `5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc`. +<3> The third password has a `PasswordEncoder` id of `pbkdf2` and `encodedPassword` value of `5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc`. When matching, it would delegate to `Pbkdf2PasswordEncoder` -<4> The fourth password has a `PasswordEncoder` id of `scrypt` and encoded password value of `$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=` +<4> The fourth password has a `PasswordEncoder` id of `scrypt` and `encodedPassword` value of `$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=` When matching, it would delegate to `SCryptPasswordEncoder` -<5> The final password has a `PasswordEncoder` id of `sha256` and encoded password value of `97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0`. +<5> The final password has a `PasswordEncoder` id of `sha256` and `encodedPassword` value of `97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0`. When matching, it would delegate to `StandardPasswordEncoder` [NOTE] @@ -487,4 +487,8 @@ fun passwordEncoder(): PasswordEncoder { ---- ==== -NOTE: XML Configuration requires the `NoOpPasswordEncoder` bean name to be `passwordEncoder`. + +[NOTE] +==== +XML Configuration requires the `NoOpPasswordEncoder` bean name to be `passwordEncoder`. +==== diff --git a/docs/manual/src/docs/asciidoc/_includes/about/exploits/csrf.adoc b/docs/manual/src/docs/asciidoc/_includes/about/exploits/csrf.adoc index 67728e135b..ad290d6ba9 100644 --- a/docs/manual/src/docs/asciidoc/_includes/about/exploits/csrf.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/about/exploits/csrf.adoc @@ -8,8 +8,11 @@ In the following sections, we explore: * <> * <> -NOTE: This portion of the documentation discusses the general topic of CSRF protection. +[NOTE] +==== +This portion of the documentation discusses the general topic of CSRF protection. See the relevant sections for specific information on CSRF protection for <>- and <>-based applications. +==== [[csrf-explained]] == What is a CSRF Attack? @@ -95,7 +98,10 @@ Spring provides two mechanisms to protect against CSRF attacks: * The <> * Specifying the <> on your session cookie -NOTE: Both protections require that <>. +[NOTE] +==== +Both protections require that <>. +==== [[csrf-protection-idempotent]] === Safe Methods Must be Idempotent @@ -172,9 +178,12 @@ The evil website cannot provide the correct value for the `_csrf` parameter (whi An emerging way to protect against <> is to specify the https://tools.ietf.org/html/draft-west-first-party-cookies[SameSite Attribute] on cookies. A server can specify the `SameSite` attribute when setting a cookie to indicate that the cookie should not be sent when coming from external sites. -NOTE: Spring Security does not directly control the creation of the session cookie, so it does not provide support for the SameSite attribute. +[NOTE] +==== +Spring Security does not directly control the creation of the session cookie, so it does not provide support for the SameSite attribute. https://spring.io/projects/spring-session[Spring Session] provides support for the `SameSite` attribute in servlet-based applications. Spring Framework's https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/server/session/CookieWebSessionIdResolver.html[`CookieWebSessionIdResolver`] provides support for the `SameSite` attribute in WebFlux-based applications. +==== An example of an HTTP response header with the `SameSite` attribute might look like: @@ -207,7 +216,10 @@ The user receives an email at https://email.example.org that includes a link to If the user clicks on the link, they would rightfully expect to be authenticated to the social media site. However, if the `SameSite` attribute is `Strict`, the cookie would not be sent and the user would not be authenticated. -NOTE: We could improve the protection and usability of `SameSite` protection against CSRF attacks by implementing https://github.com/spring-projects/spring-security/issues/7537[gh-7537]. +[NOTE] +==== +We could improve the protection and usability of `SameSite` protection against CSRF attacks by implementing https://github.com/spring-projects/spring-security/issues/7537[gh-7537]. +==== Another obvious consideration is that, in order for the `SameSite` attribute to protect users, the browser must support the `SameSite` attribute. Most modern browsers do https://developer.mozilla.org/en-US/docs/Web/HTTP/headers/Set-Cookie#Browser_compatibility[support the SameSite attribute]. @@ -351,8 +363,11 @@ There are two options to using CSRF protection with multipart/form-data: Each option has its trade-offs. -NOTE: Before you integrate Spring Security's CSRF protection with multipart file upload, you should first ensure that you can upload without the CSRF protection. +[NOTE] +==== +Before you integrate Spring Security's CSRF protection with multipart file upload, you should first ensure that you can upload without the CSRF protection. More information about using multipart forms with Spring, see the https://docs.spring.io/spring/docs/5.2.x/spring-framework-reference/web.html#mvc-multipart[1.1.11. Multipart Resolver] section of the Spring reference and the https://docs.spring.io/spring/docs/5.2.x/javadoc-api/org/springframework/web/multipart/support/MultipartFilter.html[`MultipartFilter` Javadoc]. +==== [[csrf-considerations-multipart-body]] ==== Place CSRF Token in the Body diff --git a/docs/manual/src/docs/asciidoc/_includes/about/exploits/headers.adoc b/docs/manual/src/docs/asciidoc/_includes/about/exploits/headers.adoc index 9ebccff448..baed9fe61f 100644 --- a/docs/manual/src/docs/asciidoc/_includes/about/exploits/headers.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/about/exploits/headers.adoc @@ -1,8 +1,11 @@ [[headers]] = Security HTTP Response Headers -NOTE: This portion of the documentation discusses the general topic of Security HTTP Response Headers. +[NOTE] +==== +This portion of the documentation discusses the general topic of Security HTTP Response Headers. See the relevant sections for specific information on Security HTTP Response Headers in <>- and <>-based applications. +==== You can use https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#tab=Headers[HTTP response headers] in many ways to increase the security of web applications. This section is dedicated to the various HTTP response headers for which Spring Security provides explicit support. @@ -11,7 +14,10 @@ If necessary, you can also configure Spring Security to provide <>- and <>-based applications. +[NOTE] +==== +See the relevant sections for how to customize the defaults for both <>- and <>-based applications. +==== Spring Security provides a default set of security related HTTP response headers to provide secure defaults. @@ -31,7 +37,10 @@ X-XSS-Protection: 1; mode=block ---- ==== -NOTE: Strict-Transport-Security is added only on HTTPS requests +[NOTE] +==== +Strict-Transport-Security is added only on HTTPS requests +==== If the defaults do not meet your needs, you can easily remove, modify, or add headers from these defaults. For additional details on each of these headers, see the corresponding sections: @@ -45,7 +54,10 @@ For additional details on each of these headers, see the corresponding sections: [[headers-cache-control]] == Cache Control -NOTE: See the relevant sections for how to customize the defaults for both <>- and <>-based applications. +[NOTE] +==== +See the relevant sections for how to customize the defaults for both <>- and <>-based applications. +==== Spring Security's default is to disable caching to protect the user's content. @@ -70,15 +82,21 @@ This allows for applications to ensure that static resources (such as CSS and Ja [[headers-content-type-options]] == Content Type Options -NOTE: See the relevant sections for how to customize the defaults for both <>- and <>-based applications. +[NOTE] +==== +See the relevant sections for how to customize the defaults for both <>- and <>-based applications. +==== Historically, browsers, including Internet Explorer, would try to guess the content type of a request by using https://en.wikipedia.org/wiki/Content_sniffing[content sniffing]. This let browsers improve the user experience by guessing the content type on resources that had not specified the content type. For example, if a browser encountered a JavaScript file that did not have the content type specified, it would be able to guess the content type and then run it. -NOTE: There are many additional things one should do (such as only display the document in a distinct domain, ensure Content-Type header is set, sanitize the document, and others) when allowing content to be uploaded. +[NOTE] +==== +There are many additional things one should do (such as only display the document in a distinct domain, ensure Content-Type header is set, sanitize the document, and others) when allowing content to be uploaded. However, these measures are out of the scope of what Spring Security provides. It is also important to point out that, when disabling content sniffing, you must specify the content type in order for things to work properly. +==== The problem with content sniffing is that this allowed malicious users to use polyglots (that is, a file that is valid as multiple content types) to perform XSS attacks. For example, some sites may allow users to submit a valid postscript document to a website and view it. @@ -97,7 +115,10 @@ X-Content-Type-Options: nosniff [[headers-hsts]] == HTTP Strict Transport Security (HSTS) -NOTE: Refer to the relevant sections to see how to customize the defaults for both <> and <> based applications. +[NOTE] +==== +Refer to the relevant sections to see how to customize the defaults for both <> and <> based applications. +==== When you type in your bank's website, do you enter `mybank.example.com` or do you enter `https://mybank.example.com`? If you omit the `https` protocol, you are potentially vulnerable to https://en.wikipedia.org/wiki/Man-in-the-middle_attack[Man-in-the-Middle attacks]. @@ -107,8 +128,11 @@ Many users omit the `https` protocol, and this is why https://tools.ietf.org/htm Once `mybank.example.com` is added as a https://tools.ietf.org/html/rfc6797#section-5.1[HSTS host], a browser can know ahead of time that any request to mybank.example.com should be interpreted as https://mybank.example.com. This greatly reduces the possibility of a Man-in-the-Middle attack occurring. -NOTE: In accordance with https://tools.ietf.org/html/rfc6797#section-7.2[RFC6797], the HSTS header is injected only into HTTPS responses. +[NOTE] +==== +In accordance with https://tools.ietf.org/html/rfc6797#section-7.2[RFC6797], the HSTS header is injected only into HTTPS responses. For the browser to acknowledge the header, the browser must first trust the CA that signed the SSL certificate used to make the connection (not just the SSL certificate). +==== One way for a site to be marked as a HSTS host is to have the host preloaded into the browser. Another way is to add the `Strict-Transport-Security` header to the response. @@ -131,7 +155,10 @@ For more details on HSTS preload, see https://hstspreload.org. [[headers-hpkp]] == HTTP Public Key Pinning (HPKP) -NOTE: To remain passive, Spring Security still provides <>. However, for the reasons listed earlier, HPKP is no longer recommended by the Spring Security team. +[NOTE] +==== +To remain passive, Spring Security still provides <>. However, for the reasons listed earlier, HPKP is no longer recommended by the Spring Security team. +==== https://developer.mozilla.org/en-US/docs/Web/HTTP/Public_Key_Pinning[HTTP Public Key Pinning (HPKP)] specifies to a web client which public key to use with a certain web server to prevent Man-in-the-Middle (MITM) attacks with forged certificates. When used correctly, HPKP could add additional layers of protection against compromised certificates. @@ -143,14 +170,20 @@ For additional details around why HPKP is no longer recommended, read https://bl [[headers-frame-options]] == X-Frame-Options -NOTE: See the relevant sections to see how to customize the defaults for both <> and <> based applications. +[NOTE] +==== +See the relevant sections to see how to customize the defaults for both <> and <> based applications. +==== Letting your website be added to a frame can be a security issue. For example, by using clever CSS styling, users could be tricked into clicking on something that they were not intending. For example, a user that is logged into their bank might click a button that grants access to other users. This sort of attack is known as https://en.wikipedia.org/wiki/Clickjacking[Clickjacking]. -NOTE: Another modern approach to dealing with clickjacking is to use <>. +[NOTE] +==== +Another modern approach to dealing with clickjacking is to use <>. +==== There are a number ways to mitigate clickjacking attacks. For example, to protect legacy browsers from clickjacking attacks, you can use https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet#Best-for-now_Legacy_Browser_Frame_Breaking_Script[frame breaking code]. @@ -169,7 +202,10 @@ X-Frame-Options: DENY [[headers-xss-protection]] == X-XSS-Protection -NOTE: See the relevant sections to see how to customize the defaults for both <>- and <>-based applications. +[NOTE] +==== +See the relevant sections to see how to customize the defaults for both <>- and <>-based applications. +==== Some browsers have built-in support for filtering out https://www.owasp.org/index.php/Testing_for_Reflected_Cross_site_scripting_(OWASP-DV-001)[reflected XSS attacks]. This is by no means foolproof but does assist in XSS protection. @@ -190,14 +226,20 @@ X-XSS-Protection: 1; mode=block [[headers-csp]] == Content Security Policy (CSP) -NOTE: See the relevant sections to see how to configure both <>- and <>-based applications. +[NOTE] +==== +See the relevant sections to see how to configure both <>- and <>-based applications. +==== https://www.w3.org/TR/CSP2/[Content Security Policy (CSP)] is a mechanism that web applications can use to mitigate content injection vulnerabilities, such as cross-site scripting (XSS). CSP is a declarative policy that provides a facility for web application authors to declare and ultimately inform the client (user-agent) about the sources from which the web application expects to load resources. -NOTE: Content Security Policy is not intended to solve all content injection vulnerabilities. +[NOTE] +==== +Content Security Policy is not intended to solve all content injection vulnerabilities. Instead, you can use CSP to help reduce the harm caused by content injection attacks. As a first line of defense, web application authors should validate their input and encode their output. +==== A web application can use CSP by including one of the following HTTP headers in the response: @@ -260,7 +302,10 @@ https://www.w3.org/TR/CSP2/[W3C Candidate Recommendation] [[headers-referrer]] == Referrer Policy -NOTE: See the relevant sections to see how to configure both <>- and <>-based applications. +[NOTE] +==== +See the relevant sections to see how to configure both <>- and <>-based applications. +==== https://www.w3.org/TR/referrer-policy[Referrer Policy] is a mechanism that web applications can use to manage the referrer field, which contains the last page the user was on. @@ -280,7 +325,10 @@ The Referrer-Policy response header instructs the browser to let the destination [[headers-feature]] == Feature Policy -NOTE: See the relevant sections to see how to configure both <>- and <>-based applications. +[NOTE] +==== +See the relevant sections to see how to configure both <>- and <>-based applications. +==== https://wicg.github.io/feature-policy/[Feature Policy] is a mechanism that lets web developers selectively enable, disable, and modify the behavior of certain APIs and web features in the browser. @@ -299,7 +347,10 @@ These policies restrict what APIs the site can access or modify the browser's de [[headers-permissions]] == Permissions Policy -NOTE: See the relevant sections to see how to configure both <>- and <>-based applications. +[NOTE] +==== +See the relevant sections to see how to configure both <>- and <>-based applications. +==== https://w3c.github.io/webappsec-permissions-policy/[Permissions Policy] is a mechanism that lets web developers selectively enable, disable, and modify the behavior of certain APIs and web features in the browser. @@ -318,7 +369,10 @@ These policies restrict what APIs the site can access or modify the browser's de [[headers-clear-site-data]] == Clear Site Data -NOTE: See the relevant sections to see how to configure both <> and <> based applications. +[NOTE] +==== +See the relevant sections to see how to configure both <> and <> based applications. +==== https://www.w3.org/TR/clear-site-data/[Clear Site Data] is a mechanism by which any browser-side data (cookies, local storage, and the like) can be removed when an HTTP response contains this header: @@ -335,7 +389,10 @@ This is a nice clean-up action to perform on logout. [[headers-custom]] == Custom Headers -NOTE: See the relevant sections to see how to configure both <> based applications. +[NOTE] +==== +See the relevant sections to see how to configure both <> based applications. +==== Spring Security has mechanisms to make it convenient to add the more common security headers to your application. However, it also provides hooks to enable adding custom headers. diff --git a/docs/manual/src/docs/asciidoc/_includes/about/getting-spring-security.adoc b/docs/manual/src/docs/asciidoc/_includes/about/getting-spring-security.adoc index 464ee567dc..489eed4253 100644 --- a/docs/manual/src/docs/asciidoc/_includes/about/getting-spring-security.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/about/getting-spring-security.adoc @@ -145,8 +145,11 @@ The easiest way to resolve this is to use the `spring-framework-bom` within the The preceding example ensures that all the transitive dependencies of Spring Security use the Spring {spring-core-version} modules. -NOTE: This approach uses Maven's "`bill of materials`" (BOM) concept and is only available in Maven 2.0.9+. +[NOTE] +==== +This approach uses Maven's "`bill of materials`" (BOM) concept and is only available in Maven 2.0.9+. For additional details about how dependencies are resolved, see https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html[Maven's Introduction to the Dependency Mechanism documentation]. +==== [[maven-repositories]] === Maven Repositories diff --git a/docs/manual/src/docs/asciidoc/_includes/about/modules.adoc b/docs/manual/src/docs/asciidoc/_includes/about/modules.adoc index fd0c274581..99d836c420 100644 --- a/docs/manual/src/docs/asciidoc/_includes/about/modules.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/about/modules.adoc @@ -277,7 +277,11 @@ This is the basis of the Spring Security integration. [[spring-security-openid]] == OpenID -- `spring-security-openid.jar` -NOTE: The OpenID 1.0 and 2.0 protocols have been deprecated and users are encouraged to migrate to OpenID Connect, which is supported by spring-security-oauth2. + +[NOTE] +==== +The OpenID 1.0 and 2.0 protocols have been deprecated and users are encouraged to migrate to OpenID Connect, which is supported by spring-security-oauth2. +==== This module contains OpenID web authentication support. It is used to authenticate users against an external OpenID server. diff --git a/docs/manual/src/docs/asciidoc/_includes/reactive/exploits/csrf.adoc b/docs/manual/src/docs/asciidoc/_includes/reactive/exploits/csrf.adoc index b0f8024220..69555a80bb 100644 --- a/docs/manual/src/docs/asciidoc/_includes/reactive/exploits/csrf.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/reactive/exploits/csrf.adoc @@ -63,9 +63,12 @@ fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain ----- ==== -NOTE: The preceding sample explicitly sets `cookieHttpOnly=false`. +[NOTE] +==== +The preceding sample explicitly sets `cookieHttpOnly=false`. This is necessary to let JavaScript (in this case, AngularJS) to read it. If you do not need the ability to read the cookie with JavaScript directly, we recommend to omitting `cookieHttpOnly=false` (by using `new CookieServerCsrfTokenRepository()` instead) to improve security. +==== [[webflux-csrf-configure-disable]] ==== Disable CSRF Protection @@ -344,7 +347,10 @@ For details, see the <> section. We have <> how protecting multipart requests (file uploads) from CSRF attacks causes a https://en.wikipedia.org/wiki/Chicken_or_the_egg[chicken and the egg] problem. This section discusses how to implement placing the CSRF token in the <> and <> within a WebFlux application. -NOTE: For more information about using multipart forms with Spring, see the https://docs.spring.io/spring/docs/5.2.x/spring-framework-reference/web-reactive.html#webflux-multipart[Multipart Data] section of the Spring reference. +[NOTE] +==== +For more information about using multipart forms with Spring, see the https://docs.spring.io/spring/docs/5.2.x/spring-framework-reference/web-reactive.html#webflux-multipart[Multipart Data] section of the Spring reference. +==== [[webflux-csrf-considerations-multipart-body]] ==== Place CSRF Token in the Body diff --git a/docs/manual/src/docs/asciidoc/_includes/reactive/method.adoc b/docs/manual/src/docs/asciidoc/_includes/reactive/method.adoc index 5f6b135c5d..9e54fdadd6 100644 --- a/docs/manual/src/docs/asciidoc/_includes/reactive/method.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/reactive/method.adoc @@ -4,8 +4,11 @@ Spring Security supports method security by using https://projectreactor.io/docs/core/release/reference/#context[Reactor's Context], which is set up by `ReactiveSecurityContextHolder`. The following example shows how to retrieve the currently logged in user's message: -NOTE: For this example to work, the return type of the method must be a `org.reactivestreams.Publisher` (that is, a `Mono` or a `Flux`) or the function must be a Kotlin coroutine function. +[NOTE] +==== +For this example to work, the return type of the method must be a `org.reactivestreams.Publisher` (that is, a `Mono` or a `Flux`) or the function must be a Kotlin coroutine function. This is necessary to integrate with Reactor's `Context`. +==== ==== .Java diff --git a/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/login.adoc b/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/login.adoc index 71c262889d..49a89b9cd2 100644 --- a/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/login.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/login.adoc @@ -5,7 +5,10 @@ The OAuth 2.0 Login feature provides an application with the ability to have use GitHub) or OpenID Connect 1.0 Provider (such as Google). OAuth 2.0 Login implements the "Login with Google" or "Login with GitHub" use cases. -NOTE: OAuth 2.0 Login is implemented by using the *Authorization Code Grant*, as specified in the https://tools.ietf.org/html/rfc6749#section-4.1[OAuth 2.0 Authorization Framework] and https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[OpenID Connect Core 1.0]. +[NOTE] +==== +OAuth 2.0 Login is implemented by using the *Authorization Code Grant*, as specified in the https://tools.ietf.org/html/rfc6749#section-4.1[OAuth 2.0 Authorization Framework] and https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[OpenID Connect Core 1.0]. +==== [[webflux-oauth2-login-sample]] == Spring Boot 2.0 Sample @@ -25,7 +28,10 @@ This section shows how to configure the {gh-samples-url}/boot/oauth2login-webflu To use Google's OAuth 2.0 authentication system for login, you must set up a project in the Google API Console to obtain OAuth 2.0 credentials. -NOTE: https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the https://openid.net/connect/[OpenID Connect 1.0] specification and is https://openid.net/certification/[OpenID Certified]. +[NOTE] +==== +https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the https://openid.net/connect/[OpenID Connect 1.0] specification and is https://openid.net/certification/[OpenID Certified]. +==== Follow the instructions on the https://developers.google.com/identity/protocols/OpenIDConnect[OpenID Connect] page, starting in the "`Setting up OAuth 2.0`" section. @@ -38,12 +44,19 @@ The redirect URI is the path in the application that the end-user's user-agent i In the "`Set a redirect URI`" sub-section, ensure that the *Authorized redirect URIs* field is set to `http://localhost:8080/login/oauth2/code/google`. -TIP: The default redirect URI template is `+{baseUrl}/login/oauth2/code/{registrationId}+`. +[TIP] +==== +The default redirect URI template is `+{baseUrl}/login/oauth2/code/{registrationId}+`. The *_registrationId_* is a unique identifier for the <>. For our example, the `registrationId` is `google`. +==== -IMPORTANT: If the OAuth Client runs behind a proxy server, we recommend checking the <> to ensure the application is correctly configured. +[IMPORTANT] +==== +If the OAuth Client runs behind a proxy server, we recommend checking the <> to ensure the application is correctly configured. Also, see the supported <> for the `redirect-uri`. +==== + [[webflux-oauth2-login-sample-config]] === Configure `application.yml` @@ -111,7 +124,10 @@ spring: The `issuer-uri` instructs Spring Security to query, in series, the following endpoints to discover the configuration: `https://idp.example.com/auth/realms/demo/.well-known/openid-configuration`, `https://idp.example.com/.well-known/openid-configuration/auth/realms/demo`, or `https://idp.example.com/.well-known/oauth-authorization-server/auth/realms/demo`. -NOTE: Spring Security queries the endpoints one at a time, stopping at the first that gives a 200 response. +[NOTE] +==== +Spring Security queries the endpoints one at a time, stopping at the first that gives a 200 response. +==== The `client-id` and `client-secret` are linked to the provider because `keycloak` is used for both the provider and the registration. diff --git a/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/resource-server.adoc b/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/resource-server.adoc index b16fcbe010..cc429e4765 100644 --- a/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/resource-server.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/reactive/oauth2/resource-server.adoc @@ -9,7 +9,10 @@ Spring Security supports protecting endpoints by offering two forms of OAuth 2.0 This is handy in circumstances where an application has delegated its authority management to an https://tools.ietf.org/html/rfc6749[authorization server] (for example, Okta or Ping Identity). Resource serves can consult this authorization server to authorize requests. -NOTE: A complete working example for {gh-samples-url}/boot/oauth2resourceserver-webflux[JWT] is available in the {gh-samples-url}[Spring Security repository]. +[NOTE] +==== +A complete working example for {gh-samples-url}/boot/oauth2resourceserver-webflux[JWT] is available in the {gh-samples-url}[Spring Security repository]. +==== [[webflux-oauth2resourceserver-jwt-minimaldependencies]] == Minimal Dependencies for JWT @@ -42,8 +45,11 @@ spring: Where `https://idp.example.com/issuer` is the value contained in the `iss` claim for JWT tokens that the authorization server issues. This resource server uses this property to further self-configure, discover the authorization server's public keys, and subsequently validate incoming JWTs. -NOTE: To use the `issuer-uri` property, it must also be true that one of `https://idp.example.com/issuer/.well-known/openid-configuration`, `https://idp.example.com/.well-known/openid-configuration/issuer`, or `https://idp.example.com/.well-known/oauth-authorization-server/issuer` is a supported endpoint for the authorization server. +[NOTE] +==== +To use the `issuer-uri` property, it must also be true that one of `https://idp.example.com/issuer/.well-known/openid-configuration`, `https://idp.example.com/.well-known/openid-configuration/issuer`, or `https://idp.example.com/.well-known/oauth-authorization-server/issuer` is a supported endpoint for the authorization server. This endpoint is referred to as a https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Provider Configuration] endpoint or a https://tools.ietf.org/html/rfc8414#section-3[Authorization Server Metadata] endpoint. +==== === Startup Expectations @@ -57,7 +63,10 @@ It achieves this through a deterministic startup process: A consequence of this process is that the authorization server must be receiving requests in order for Resource Server to successfully start up. -NOTE: If the authorization server is down when Resource Server queries it (given appropriate timeouts), then startup fails. +[NOTE] +==== +If the authorization server is down when Resource Server queries it (given appropriate timeouts), then startup fails. +==== === Runtime Expectations @@ -79,7 +88,10 @@ Given a well-formed JWT, Resource Server: 2. Validates the JWTs `exp` and `nbf` timestamps and the JWTs `iss` claim. 3. Maps each scope to an authority with the prefix `SCOPE_`. -NOTE: As the authorization server makes available new keys, Spring Security automatically rotates the keys used to validate the JWT tokens. +[NOTE] +==== +As the authorization server makes available new keys, Spring Security automatically rotates the keys used to validate the JWT tokens. +==== By default, the resulting `Authentication#getPrincipal` is a Spring Security `Jwt` object, and `Authentication#getName` maps to the JWT's `sub` property, if one is present. @@ -106,12 +118,18 @@ spring: ---- ==== -NOTE: The JWK Set uri is not standardized, but you can typically find it in the authorization server's documentation. +[NOTE] +==== +The JWK Set uri is not standardized, but you can typically find it in the authorization server's documentation. +==== Consequently, Resource Server does not ping the authorization server at startup. We still specify the `issuer-uri` so that Resource Server still validates the `iss` claim on incoming JWTs. -NOTE: You can supply this property directly on the <>. +[NOTE] +==== +You can supply this property directly on the <>. +==== [[webflux-oauth2resourceserver-jwt-sansboot]] === Overriding or Replacing Boot Auto Configuration @@ -221,8 +239,11 @@ fun jwtDecoder(): ReactiveJwtDecoder { ---- ==== -NOTE: Calling `{security-api-url}org/springframework/security/oauth2/jwt/ReactiveJwtDecoders.html#fromIssuerLocation-java.lang.String-[ReactiveJwtDecoders#fromIssuerLocation]` invokes the Provider Configuration or Authorization Server Metadata endpoint to derive the JWK Set URI. +[NOTE] +==== +Calling `{security-api-url}org/springframework/security/oauth2/jwt/ReactiveJwtDecoders.html#fromIssuerLocation-java.lang.String-[ReactiveJwtDecoders#fromIssuerLocation]` invokes the Provider Configuration or Authorization Server Metadata endpoint to derive the JWK Set URI. If the application does not expose a `ReactiveJwtDecoder` bean, Spring Boot exposes the above default one. +==== Its configuration can be overridden by using `jwkSetUri()` or replaced by using `decoder()`. @@ -939,8 +960,11 @@ Where `https://idp.example.com/introspect` is the introspection endpoint hosted Resource Server uses these properties to further self-configure and subsequently validate incoming JWTs. -NOTE: When using introspection, the authorization server's word is the law. +[NOTE] +==== +When using introspection, the authorization server's word is the law. If the authorization server responses that the token is valid, it is. +==== ==== Startup Expectations @@ -1796,8 +1820,11 @@ return http { In this case, you construct `JwtIssuerReactiveAuthenticationManagerResolver` with a strategy for obtaining the `ReactiveAuthenticationManager` given to the issuer. This approach lets us add and remove elements from the repository (shown as a `Map` in the preceding snippet) at runtime. -NOTE: It would be unsafe to simply take any issuer and construct an `ReactiveAuthenticationManager` from it. +[NOTE] +==== +It would be unsafe to simply take any issuer and construct an `ReactiveAuthenticationManager` from it. The issuer should be one that the code can verify from a trusted source, such as an allowed list of issuers. +==== [[webflux-oauth2resourceserver-bearertoken-resolver]] == Bearer Token Resolution @@ -1914,5 +1941,8 @@ rest.get() In this case, the filter falls back and forwards the request onto the rest of the web filter chain. -NOTE: Unlike the https://docs.spring.io/spring-security/site/docs/current-SNAPSHOT/api/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.html[OAuth 2.0 Client filter function], this filter function makes no attempt to renew the token, should it be expired. +[NOTE] +==== +Unlike the https://docs.spring.io/spring-security/site/docs/current-SNAPSHOT/api/org/springframework/security/oauth2/client/web/reactive/function/client/ServerOAuth2AuthorizedClientExchangeFilterFunction.html[OAuth 2.0 Client filter function], this filter function makes no attempt to renew the token, should it be expired. To obtain this level of support, use the OAuth 2.0 Client filter. +==== diff --git a/docs/manual/src/docs/asciidoc/_includes/reactive/registered-oauth2-authorized-client.adoc b/docs/manual/src/docs/asciidoc/_includes/reactive/registered-oauth2-authorized-client.adoc index ce98690560..c858b66634 100644 --- a/docs/manual/src/docs/asciidoc/_includes/reactive/registered-oauth2-authorized-client.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/reactive/registered-oauth2-authorized-client.adoc @@ -3,7 +3,10 @@ Spring Security allows resolving an access token by using `@RegisteredOAuth2AuthorizedClient`. -NOTE: You can find a working example in the {gh-samples-url}/boot/oauth2webclient-webflux[OAuth 2.0 WebClient WebFlux sample]. +[NOTE] +==== +You can find a working example in the {gh-samples-url}/boot/oauth2webclient-webflux[OAuth 2.0 WebClient WebFlux sample]. +==== After configuring Spring Security for <> or as an <>, you can resolve an `OAuth2AuthorizedClient` by using the following: diff --git a/docs/manual/src/docs/asciidoc/_includes/reactive/rsocket.adoc b/docs/manual/src/docs/asciidoc/_includes/reactive/rsocket.adoc index d3b7eac685..d7dccd0a69 100644 --- a/docs/manual/src/docs/asciidoc/_includes/reactive/rsocket.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/reactive/rsocket.adoc @@ -82,8 +82,11 @@ This means that individual users can make requests but not make additional conne Spring Security has support for the https://github.com/rsocket/rsocket/blob/5920ed374d008abb712cb1fd7c9d91778b2f4a68/Extensions/Security/Simple.md[Simple Authentication Metadata Extension]. -NOTE: Basic Authentication evolved into Simple Authentication and is only supported for backward compatibility. +[NOTE] +==== +Basic Authentication evolved into Simple Authentication and is only supported for backward compatibility. See `RSocketSecurity.basicAuthentication(Customizer)` for setting it up. +==== The RSocket receiver can decode the credentials by using `AuthenticationPayloadExchangeConverter`, which is automatically setup by using the `simpleAuthentication` portion of the DSL. The following example shows an explicit configuration: diff --git a/docs/manual/src/docs/asciidoc/_includes/reactive/webclient.adoc b/docs/manual/src/docs/asciidoc/_includes/reactive/webclient.adoc index 2ea6b412d2..0f73302b13 100644 --- a/docs/manual/src/docs/asciidoc/_includes/reactive/webclient.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/reactive/webclient.adoc @@ -1,8 +1,11 @@ [[webclient]] = WebClient -NOTE: The documentation in this section is for use within Reactive environments. +[NOTE] +==== +The documentation in this section is for use within Reactive environments. For Servlet environments, see <>. +==== Spring Framework has built-in support for setting a Bearer token: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/faq.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/faq.adoc index e3481e3ab0..d05a263c43 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/faq.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/faq.adoc @@ -259,10 +259,13 @@ This happens because sessions created under HTTPS, for which the session cookie However, Spring Security's https://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-session-fixation[Session Fixation Protection] can interfere with this because it results in a new session ID cookie being sent back to the user's browser, usually with the secure flag. To get around this, you can disable session fixation protection. However, in newer Servlet containers, you can also configure session cookies to never use the secure flag. -IMPORTANT: Switching between HTTP and HTTPS is not a good idea in general, as any application that uses HTTP at all is vulnerable to man-in-the-middle attacks. +[IMPORTANT] +==== +Switching between HTTP and HTTPS is not a good idea in general, as any application that uses HTTP at all is vulnerable to man-in-the-middle attacks. To be truly secure, the user should begin accessing your site in HTTPS and continue using it until they log out. Even clicking on an HTTPS link from a page accessed over HTTP is potentially risky. If you need more convincing, check out a tool such as https://www.thoughtcrime.org/software/sslstrip/[sslstrip]. +==== ==== I am not switching between HTTP and HTTPS, but my session is still lost. What happened? diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc index 5281530d23..ee660da68c 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/appendix/namespace.adoc @@ -554,7 +554,11 @@ The policy value to write for the `Permissions-Policy` header [[nsa-xss-protection]] ==== The `` adds the https://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-iv-the-xss-filter.aspx[X-XSS-Protection header] to the response, to assist in protecting against https://en.wikipedia.org/wiki/Cross-site_scripting#Non-Persistent[reflected / Type-1 Cross-Site Scripting (XSS)] attacks. -NOTE: Full protection against XSS attacks is not possible. + +[NOTE] +==== +Full protection against XSS attacks is not possible. +==== [[nsa-xss-protection-attributes]] @@ -803,8 +807,11 @@ This always takes precedence over other namespace-created entry points. If no attributes are supplied, a login page is generated automatically at the `/login` URL. You can customize this behavior by setting the <` Attributes>>. -NOTE: This feature is provided for convenience and is not intended for production (where a view technology should have been chosen and can be used to render a customized login page). +[NOTE] +==== +This feature is provided for convenience and is not intended for production (where a view technology should have been chosen and can be used to render a customized login page). The class `DefaultLoginPageGeneratingFilter` class is responsible for rendering the login page and provide login forms for both normal form login and OpenID if required. +==== [[nsa-form-login-parents]] @@ -1370,7 +1377,10 @@ If this attribute is present on any `` element, a `ChannelProcess If a `` configuration is added, it is used by the `SecureChannelProcessor` and `InsecureChannelProcessor` beans to determine the ports used for redirecting to HTTP and HTTPS. -NOTE: This property is invalid for <> +[NOTE] +==== +This property is invalid for <> +==== [[nsa-intercept-url-servlet-path]] `servlet-path`:: @@ -1380,7 +1390,10 @@ In addition, the value is only required in the following two use cases: * Two or more `HttpServlet` instances that have mappings starting with `/` and are different are registered in the `ServletContext`. * The pattern starts with the same value of a registered `HttpServlet` path, excluding the default (root) `HttpServlet` `/`. -NOTE: This property is invalid for <> +[NOTE] +==== +This property is invalid for <> +==== [[nsa-jee]] @@ -2316,8 +2329,11 @@ The `` element has the following attributes: [[nsa-password-encoder-hash]] `hash`:: Defines the hashing algorithm for user passwords. -IMPORTANT: We recommend strongly against using MD4, as it is a very weak hashing algorithm. +[IMPORTANT] +==== +We recommend strongly against using MD4, as it is a very weak hashing algorithm. +==== [[nsa-password-encoder-ref]] `ref`:: @@ -2473,9 +2489,13 @@ mode:: You can set this attribute to `aspectj` to specify that AspectJ should be used instead of the default Spring AOP. You must weave secured methods with the `AnnotationSecurityAspect` from the `spring-security-aspects` module. + -NOTE: AspectJ follows Java's rule that annotations on interfaces are not inherited. +[NOTE] +==== +AspectJ follows Java's rule that annotations on interfaces are not inherited. This means that methods that define the Security annotations on the interface are not secured. Instead, you must place the Security annotation on the class when you use AspectJ. +==== + [[nsa-global-method-security-order]] `order`:: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/architecture/exception-translation-filter.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/architecture/exception-translation-filter.adoc index f3c97ed7de..dfe51ef5f6 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/architecture/exception-translation-filter.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/architecture/exception-translation-filter.adoc @@ -25,7 +25,10 @@ For example, it might redirect to a log in page or send a `WWW-Authenticate` hea The `AccessDeniedHandler` is invoked to handle access denied. // FIXME: link to AccessDeniedHandler -NOTE: If the application does not throw an `AccessDeniedException` or an `AuthenticationException`, `ExceptionTranslationFilter` does not do anything. +[NOTE] +==== +If the application does not throw an `AccessDeniedException` or an `AuthenticationException`, `ExceptionTranslationFilter` does not do anything. +==== The pseudocode for `ExceptionTranslationFilter` looks something like this: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/anonymous.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/anonymous.adoc index 16306a3402..428d918d7c 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/anonymous.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/anonymous.adoc @@ -48,11 +48,14 @@ The filter and authentication provider is defined as follows: The `key` is shared between the filter and authentication provider so that tokens created by the former are accepted by the latter -NOTE: The use of the `key` property should not be regarded as providing any real security here. +[NOTE] +==== +The use of the `key` property should not be regarded as providing any real security here. It is merely a book-keeping exercise. If you share a `ProviderManager` that contains an `AnonymousAuthenticationProvider` in a scenario where it is possible for an authenticating client to construct the `Authentication` object (such as with RMI invocations), then a malicious client could submit an `AnonymousAuthenticationToken` that it had created itself (with the chosen username and authority list). If the `key` is guessable or can be found out, the token would be accepted by the anonymous provider. This is not a problem with normal usage. However, if you use RMI, you should use a customized `ProviderManager` that omits the anonymous provider rather than sharing the one you use for your HTTP authentication mechanisms. +==== The `userAttribute` is expressed in the form of `usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]`. The same syntax is used after the equals sign for the `userMap` property of `InMemoryDaoImpl`. diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/cas.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/cas.adoc index 310044eca6..bd4abfcac5 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/cas.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/cas.adoc @@ -15,7 +15,10 @@ While the CAS web site contains documents that detail the architecture of CAS, w Spring Security 3.x (and later) supports CAS 3 (and later). At the time of writing, the CAS server is at version 6.3.3. -NOTE: This section was written about CAS version 3.4, but the material is still current. +[NOTE] +==== +This section was written about CAS version 3.4, but the material is still current. +==== Somewhere in your enterprise, you need to setup a CAS server. The CAS server runs from a standard WAR file. diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/logout.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/logout.adoc index 1b5a3f1893..8c2bf19b67 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/logout.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/logout.adoc @@ -73,8 +73,11 @@ By default, `SecurityContextLogoutHandler` is added as the last `LogoutHandler`. <7> Lets specifying the names of cookies be removed on logout success. This is a shortcut for adding a `CookieClearingLogoutHandler` explicitly. -NOTE: Logouts can also be configured by using the XML Namespace notation. +[NOTE] +==== +Logouts can also be configured by using the XML Namespace notation. See the documentation for the <> in the Spring Security XML Namespace section for further details. +==== Generally, to customize logout functionality, you can add `{security-api-url}org/springframework/security/web/authentication/logout/LogoutHandler.html[LogoutHandler]` diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/openid.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/openid.adoc index c615550bcf..de3ed417ee 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/openid.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/openid.adoc @@ -1,7 +1,10 @@ [[servlet-openid]] == OpenID Support -NOTE: The OpenID 1.0 and 2.0 protocols have been deprecated. You should migrate to OpenID Connect, which is supported by `spring-security-oauth2`. +[NOTE] +==== +The OpenID 1.0 and 2.0 protocols have been deprecated. You should migrate to OpenID Connect, which is supported by `spring-security-oauth2`. +==== The namespace supports https://openid.net/[OpenID] login either instead of or in addition to normal form-based login, with a simple change: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/preauth.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/preauth.adoc index ae6a079912..b62b627d78 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/preauth.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/preauth.adoc @@ -100,8 +100,12 @@ This mechanism is supported by the `RequestHeaderAuthenticationFilter` class, wh It defaults to using a name of `SM_USER` as the header name. See the Javadoc for more details. -TIP: When using a system like this, the framework performs no authentication checks at all, and it is _extremely_ important that the external system is configured properly and protects all access to the application. +[TIP] +==== +When using a system like this, the framework performs no authentication checks at all, and it is _extremely_ important that the external system is configured properly and protects all access to the application. If an attacker is able to forge the headers in their original request without this being detected, they could potentially choose any username they wished. +==== + ===== Siteminder Example Configuration The following example shows a typical configuration that uses this filter: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/session-management.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/session-management.adoc index 0916bd138f..fe251a4aec 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/session-management.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/session-management.adoc @@ -127,8 +127,11 @@ See the <> chapter for additional information. === SessionManagementFilter The `SessionManagementFilter` checks the contents of the `SecurityContextRepository` against the current contents of the `SecurityContextHolder` to determine whether a user has been authenticated during the current request, typically by a non-interactive authentication mechanism, such as pre-authentication or remember-me -NOTE: Authentication by mechanisms that perform a redirect after authenticating (such as form-login) are not detected by `SessionManagementFilter`, as the filter is not invoked during the authenticating request. +[NOTE] +==== +Authentication by mechanisms that perform a redirect after authenticating (such as form-login) are not detected by `SessionManagementFilter`, as the filter is not invoked during the authenticating request. Session-management functionality has to be handled separately in these cases. +==== If the repository contains a security context, the filter does nothing. If it does not and the thread-local `SecurityContext` contains a (non-anonymous) `Authentication` object, the filter assumes they have been authenticated by a previous filter in the stack. @@ -179,10 +182,13 @@ Sometimes, though, you need to customize things. The implementation uses a specialized version of `SessionAuthenticationStrategy`, called `ConcurrentSessionControlAuthenticationStrategy`. -NOTE: Previously, the concurrent authentication check was made by the `ProviderManager`, which could be injected with a `ConcurrentSessionController`. +[NOTE] +==== +Previously, the concurrent authentication check was made by the `ProviderManager`, which could be injected with a `ConcurrentSessionController`. The latter would check if the user was attempting to exceed the number of permitted sessions. However, this approach required that an HTTP session be created in advance, which is undesirable. In Spring Security 3 and later, the user is first authenticated by the `AuthenticationManager` and once they are successfully authenticated, a session is created and the check is made whether they are allowed to have another session open. +==== To use concurrent session support, you need to add the following to `web.xml`: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/digest.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/digest.adoc index 565503a29f..293b339dd9 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/digest.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/digest.adoc @@ -3,10 +3,13 @@ This section provides details on how Spring Security provides support for https://tools.ietf.org/html/rfc2617[Digest Authentication], which is provided `DigestAuthenticationFilter`. -WARNING: You should not use Digest Authentication in modern applications, because it is not considered to be secure. +[WARNING] +==== +You should not use Digest Authentication in modern applications, because it is not considered to be secure. The most obvious problem is that you must store your passwords in plaintext or an encrypted or MD5 format. All of these storage formats are considered insecure. Instead, you should store credentials by using a one way adaptive password hash (bCrypt, PBKDF2, SCrypt, and others), which is not supported by Digest Authentication. +==== Digest Authentication tries to solve many of the weaknesses of <>, specifically by ensuring credentials are never sent in clear text across the wire. Many https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Digest#Browser_compatibility[browsers support Digest Authentication]. diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/jdbc.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/jdbc.adoc index 740c8b4de7..227f027d80 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/jdbc.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/jdbc.adoc @@ -23,7 +23,10 @@ You need to adjust the schema to match any customizations to the queries and the `JdbcDaoImpl` requires tables to load the password, account status (enabled or disabled) and a list of authorities (roles) for the user. -NOTE: The default schema is also exposed as a classpath resource named `org/springframework/security/core/userdetails/jdbc/users.ddl`. +[NOTE] +==== +The default schema is also exposed as a classpath resource named `org/springframework/security/core/userdetails/jdbc/users.ddl`. +==== .Default User Schema ==== diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/ldap.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/ldap.adoc index f1c32667e2..38ae5a784b 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/ldap.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/ldap.adoc @@ -155,9 +155,12 @@ fun ldapContainer(): UnboundIdContainer { [[servlet-authentication-ldap-apacheds]] === Embedded ApacheDS Server -NOTE: Spring Security uses ApacheDS 1.x, which is no longer maintained. +[NOTE] +==== +Spring Security uses ApacheDS 1.x, which is no longer maintained. Unfortunately, ApacheDS 2.x has only released milestone versions with no stable release. Once a stable release of ApacheDS 2.x is available, we will consider updating. +==== If you wish to use https://directory.apache.org/apacheds/[Apache DS], specify the following dependencies: @@ -543,8 +546,11 @@ To make this easier, Spring Security has an authentication provider, which is cu Configuring `ActiveDirectoryLdapAuthenticationProvider` is quite straightforward. You need only supply the domain name and an LDAP URL that supplies the address of the server. -NOTE: It is also possible to obtain the server's IP address byusing a DNS lookup. +[NOTE] +==== +It is also possible to obtain the server's IP address byusing a DNS lookup. This is not currently supported, but hopefully will be in a future version. +==== The following example configures Active Directory: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/user-details-service.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/user-details-service.adoc index f630021ee5..1ed13105bd 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/user-details-service.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/authentication/unpwd/user-details-service.adoc @@ -7,7 +7,10 @@ Spring Security provides <> and <>. +[NOTE] +==== +For earlier versions, please read about similar support with <>. +==== For example, the following would enable Spring Security's `@PreAuthorize` annotation: @@ -772,11 +775,17 @@ public Account post(Account account, double amount); Expression-based annotations are a good choice if you need to define simple rules that go beyond checking the role names against the user's list of authorities. -NOTE: The annotated methods will only be secured for instances which are defined as Spring beans (in the same application context in which method-security is enabled). +[NOTE] +==== +The annotated methods will only be secured for instances which are defined as Spring beans (in the same application context in which method-security is enabled). If you want to secure instances which are not created by Spring (using the `new` operator, for example) then you need to use AspectJ. +==== -NOTE: You can enable more than one type of annotation in the same application, but only one type should be used for any interface or class as the behaviour will not be well-defined otherwise. +[NOTE] +==== +You can enable more than one type of annotation in the same application, but only one type should be used for any interface or class as the behaviour will not be well-defined otherwise. If two annotations are found which apply to a particular method, then only one of them will be applied. +==== [[ns-protect-pointcut]] === Adding Security Pointcuts by using protect-pointcut diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/crypto/index.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/crypto/index.adoc index e5cd9f81e5..c2c020ab46 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/crypto/index.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/crypto/index.adoc @@ -14,7 +14,11 @@ This class lets you create {security-api-url}org/springframework/security/crypto You can also construct {security-api-url}org/springframework/security/crypto/encrypt/TextEncryptor.html[TextEncryptor] instances to encrypt text strings. Encryptors are thread-safe. -NOTE: Both `BytesEncryptor` and `TextEncryptor` are interfaces. `BytesEncryptor` has multiple implementations. +[NOTE] +==== +Both `BytesEncryptor` and `TextEncryptor` are interfaces. `BytesEncryptor` has multiple implementations. +==== + [[spring-security-crypto-encryption-bytes]] === BytesEncryptor diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/exploits/csrf.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/exploits/csrf.adoc index ca941c692f..2607659e88 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/exploits/csrf.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/exploits/csrf.adoc @@ -48,9 +48,12 @@ You can configure `CookieCsrfTokenRepository` in XML byusing the following: ---- ==== -NOTE: The sample explicitly sets `cookieHttpOnly=false`. +[NOTE] +==== +The sample explicitly sets `cookieHttpOnly=false`. This is necessary to allow JavaScript (such as AngularJS) to read it. If you do not need the ability to read the cookie with JavaScript directly, we recommend omitting `cookieHttpOnly=false` to improve security. +==== You can configure `CookieCsrfTokenRepository` in Java or Kotlin configuration by using: @@ -90,9 +93,12 @@ class SecurityConfig : WebSecurityConfigurerAdapter() { ---- ==== -NOTE: The sample explicitly sets `cookieHttpOnly=false`. +[NOTE] +==== +The sample explicitly sets `cookieHttpOnly=false`. This is necessary to let JavaScript (such as AngularJS) read it. If you do not need the ability to read the cookie with JavaScript directly, we recommend omitting `cookieHttpOnly=false` (by using `new CookieCsrfTokenRepository()` instead) to improve security. +==== [[servlet-csrf-configure-disable]] ==== Disable CSRF Protection @@ -375,7 +381,10 @@ For an example of how to customize the `AccessDeniedHandler`, see the provided l We have <> how protecting multipart requests (file uploads) from CSRF attacks causes a https://en.wikipedia.org/wiki/Chicken_or_the_egg[chicken and the egg] problem. This section discusses how to implement placing the CSRF token in the <> and <> within a servlet application. -NOTE: You can find more information about using multipart forms with Spring in the https://docs.spring.io/spring/docs/5.2.x/spring-framework-reference/web.html#mvc-multipart[1.1.11. Multipart Resolver] section of the Spring reference and the https://docs.spring.io/spring/docs/5.2.x/javadoc-api/org/springframework/web/multipart/support/MultipartFilter.html[`MultipartFilter` javadoc]. +[NOTE] +==== +You can find more information about using multipart forms with Spring in the https://docs.spring.io/spring/docs/5.2.x/spring-framework-reference/web.html#mvc-multipart[1.1.11. Multipart Resolver] section of the Spring reference and the https://docs.spring.io/spring/docs/5.2.x/javadoc-api/org/springframework/web/multipart/support/MultipartFilter.html[`MultipartFilter` javadoc]. +==== [[servlet-csrf-considerations-multipart-body]] ==== Place CSRF Token in the Body diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/exploits/firewall.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/exploits/firewall.adoc index 618368eef4..b086b73b93 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/exploits/firewall.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/exploits/firewall.adoc @@ -120,10 +120,13 @@ fun httpFirewall(): StrictHttpFirewall { ---- ==== -TIP: If you use `new MockHttpServletRequest()`, it currently creates an HTTP method as an empty String (`""`). +[TIP] +==== +If you use `new MockHttpServletRequest()`, it currently creates an HTTP method as an empty String (`""`). This is an invalid HTTP method and is rejected by Spring Security. You can resolve this by replacing it with `new MockHttpServletRequest("GET", "")`. See https://jira.spring.io/browse/SPR-16851[SPR_16851] for an issue that requests improving this. +==== If you must allow any HTTP method (not recommended), you can use `StrictHttpFirewall.setUnsafeAllowAnyHttpMethod(true)`. Doing so entirely disables validation of the HTTP method. @@ -139,7 +142,10 @@ This requirement can be relaxed or adjusted as necessary by using the following * `StrictHttpFirewall#setAllowedHeaderValues(Predicate)` * `StrictHttpFirewall#setAllowedParameterNames(Predicate)` -NOTE: Parameter values can be also controlled with `setAllowedParameterValues(Predicate)`. +[NOTE] +==== +Parameter values can be also controlled with `setAllowedParameterValues(Predicate)`. +==== For example, to switch off this check, you can wire your `StrictHttpFirewall` with `Predicate` instances that always return `true`: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/hello/index.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/hello/index.adoc index 98bd31f5c4..04c0308488 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/hello/index.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/hello/index.adoc @@ -3,8 +3,11 @@ This section covers the minimum setup for how to use Spring Security with Spring Boot. -NOTE: The completed application can be found at {gh-samples-url}/boot/helloworld[samples/boot/helloworld] +[NOTE] +==== +The completed application can be found at {gh-samples-url}/boot/helloworld[samples/boot/helloworld] For your convenience, you can download https://start.spring.io/starter.zip?type=maven-project&language=java&packaging=jar&jvmVersion=1.8&groupId=example&artifactId=hello-security&name=hello-security&description=Hello%20Security&packageName=example.hello-security&dependencies=web,security[a minimal Spring Boot + Spring Security application]. +==== [[servlet-hello-dependencies]] == Updating Dependencies diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/jsp-taglibs.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/jsp-taglibs.adoc index b0c1e3a5d9..c1ba0748d9 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/jsp-taglibs.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/jsp-taglibs.adoc @@ -18,7 +18,10 @@ To use any of the tags, you must have the security taglib declared in your JSP: This tag is used to determine whether its contents should be evaluated or not. In Spring Security 3.0, it can be used in two ways. -NOTE: The legacy options from Spring Security 2.0 are also supported, but discouraged. +[NOTE] +==== +The legacy options from Spring Security 2.0 are also supported, but discouraged. +==== The first approach uses a <>, which is specified in the `access` attribute of the tag. The expression evaluation is delegated to the `SecurityExpressionHandler` defined in the application context (you should have web expressions enabled in your `` namespace configuration to make sure this service is available). @@ -100,8 +103,11 @@ It checks a comma-separated list of required permissions for a specified domain If the current user has all of those permissions, the tag body is evaluated. If they do not, it is skipped. -CAUTION: In general this tag should be considered deprecated. -Instead use the <>. +[CAUTION] +==== +In general, this tag should be considered deprecated. +Instead, use the <>. +==== The following listing shows an example: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/mvc.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/mvc.adoc index 020e209adf..1a12acb269 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/mvc.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/mvc.adoc @@ -7,13 +7,19 @@ This section covers the integration in further detail. [[mvc-enablewebmvcsecurity]] === @EnableWebMvcSecurity -NOTE: As of Spring Security 4.0, `@EnableWebMvcSecurity` is deprecated. +[NOTE] +==== +As of Spring Security 4.0, `@EnableWebMvcSecurity` is deprecated. The replacement is `@EnableWebSecurity`, which adds the Spring MVC features, based upon the classpath. +==== To enable Spring Security integration with Spring MVC, add the `@EnableWebSecurity` annotation to your configuration. -NOTE: Spring Security provides the configuration by using Spring MVC's https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web.html#mvc-config-customize[`WebMvcConfigurer`]. +[NOTE] +==== +Spring Security provides the configuration by using Spring MVC's https://docs.spring.io/spring/docs/5.0.0.RELEASE/spring-framework-reference/web.html#mvc-config-customize[`WebMvcConfigurer`]. This means that, if you use more advanced options, such as integrating with `WebMvcConfigurationSupport` directly, you need to manually provide the Spring Security configuration. +==== [[mvc-requestmatcher]] === MvcRequestMatcher @@ -273,8 +279,11 @@ public ModelAndView updateName(@AuthenticationPrincipal(expression = "@jpaEntity We can further remove our dependency on Spring Security by making `@AuthenticationPrincipal` a meta-annotation on our own annotation. The next example demonstrates how we could do so on an annotation named `@CurrentUser`. -NOTE: To remove the dependency on Spring Security, it is the consuming application that would create `@CurrentUser`. +[NOTE] +==== +To remove the dependency on Spring Security, it is the consuming application that would create `@CurrentUser`. This step is not strictly required but assists in isolating your dependency to Spring Security to a more central location. +==== ==== [source,java] @@ -325,8 +334,12 @@ return new Callable() { ==== .Associating SecurityContext to Callable's -NOTE: More technically speaking, Spring Security integrates with `WebAsyncManager`. + +[NOTE] +==== +More technically speaking, Spring Security integrates with `WebAsyncManager`. The `SecurityContext` that is used to process the `Callable` is the `SecurityContext` that exists on the `SecurityContextHolder` when `startCallableProcessing` is invoked. +==== There is no automatic integration with a `DeferredResult` that is returned by controllers. This is because `DeferredResult` is processed by the users and, thus, there is no way of automatically integrating with it. diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/servlet-api.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/servlet-api.adoc index c2a4f0a47e..e34e8714fe 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/servlet-api.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/integrations/servlet-api.adoc @@ -37,8 +37,11 @@ String lastName = userDetails.getLastName(); ---- ==== -NOTE: It is typically bad practice to perform logic throughout your application. +[NOTE] +==== +It is typically bad practice to perform logic throughout your application. Instead, you should centralize it to reduce any coupling of Spring Security and the Servlet API. +==== [[servletapi-user-in-role]] ==== HttpServletRequest.isUserInRole(String) @@ -83,7 +86,10 @@ httpServletRequest.login("user","password"); ---- ==== -NOTE: You need not catch the `ServletException` if you want Spring Security to process the failed authentication attempt. +[NOTE] +==== +You need not catch the `ServletException` if you want Spring Security to process the failed authentication attempt. +==== [[servletapi-logout]] ==== HttpServletRequest.logout() diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/java-configuration/index.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/java-configuration/index.adoc index a53ce7937b..7aa6356174 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/java-configuration/index.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/java-configuration/index.adoc @@ -6,7 +6,11 @@ Spring Security 3.2 introduced Java configuration to let users configure Spring If you are familiar with the <>, you should find quite a few similarities between it and Spring Security Java configuration. -NOTE: Spring Security provides https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration[lots of sample applications] to demonstrate the use of Spring Security Java Configuration. +[NOTE] +==== +Spring Security provides https://github.com/spring-projects/spring-security-samples/tree/main/servlet/java-configuration[lots of sample applications] to demonstrate the use of Spring Security Java Configuration. +==== + [[jc-hello-wsca]] == Hello Web Security Java Configuration @@ -273,7 +277,10 @@ public class MyCustomDsl extends AbstractHttpConfigurer>. -NOTE: You can use multiple `` elements to define different access requirements for different sets of URLs, but they are evaluated in the order listed and the first match is used. +[NOTE] +==== +You can use multiple `` elements to define different access requirements for different sets of URLs, but they are evaluated in the order listed and the first match is used. So you must put the most specific matches at the top. You can also add a `method` attribute to limit the match to a particular HTTP method (`GET`, `POST`, `PUT`, and so on). +==== To add users, you can define a set of test data directly in the namespace: @@ -252,9 +255,12 @@ How can you do this with namespace configuration, since the filter chain is not The order of the filters is always strictly enforced when you use the namespace. When the application context is being created, the filter beans are sorted by the namespace handling code, and the standard Spring Security filters each have an alias in the namespace and a well-known position. -NOTE: In previous versions, the sorting took place after the filter instances had been created, during post-processing of the application context. +[NOTE] +==== +In previous versions, the sorting took place after the filter instances had been created, during post-processing of the application context. In version 3.0+, the sorting is now done at the bean metadata level, before the classes have been instantiated. This has implications for how you add your own filters to the stack, as the entire filter list must be known during the parsing of the `` element. As a result, the syntax changed slightly in version 3.0. +==== The filters, aliases, and namespace elements and attributes that create the filters are shown in the following table, in the order in which they occur in the filter chain: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-client.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-client.adoc index c126a83020..6c1db41373 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-client.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-client.adoc @@ -264,12 +264,18 @@ As an alternative, you can use `ClientRegistrations.fromOidcIssuerLocation()` to The `ClientRegistrationRepository` serves as a repository for OAuth 2.0 / OpenID Connect 1.0 `ClientRegistration`(s). -NOTE: Client registration information is ultimately stored and owned by the associated Authorization Server. +[NOTE] +==== +Client registration information is ultimately stored and owned by the associated Authorization Server. This repository provides the ability to retrieve a subset of the primary client registration information, which is stored with the Authorization Server. +==== Spring Boot 2.x auto-configuration binds each of the properties under `spring.security.oauth2.client.registration._[registrationId]_` to an instance of `ClientRegistration` and then composes each of the `ClientRegistration` instance(s) within a `ClientRegistrationRepository`. -NOTE: The default implementation of `ClientRegistrationRepository` is `InMemoryClientRegistrationRepository`. +[NOTE] +==== +The default implementation of `ClientRegistrationRepository` is `InMemoryClientRegistrationRepository`. +==== The auto-configuration also registers the `ClientRegistrationRepository` as a `@Bean` in the `ApplicationContext` so that it is available for dependency injection, if needed by the application. @@ -385,15 +391,20 @@ class OAuth2ClientController { ---- ==== -NOTE: Spring Boot 2.x auto-configuration registers an `OAuth2AuthorizedClientRepository` or an `OAuth2AuthorizedClientService` `@Bean` in the `ApplicationContext`. +[NOTE] +==== +Spring Boot 2.x auto-configuration registers an `OAuth2AuthorizedClientRepository` or an `OAuth2AuthorizedClientService` `@Bean` in the `ApplicationContext`. However, the application can override and register a custom `OAuth2AuthorizedClientRepository` or `OAuth2AuthorizedClientService` `@Bean`. +==== The default implementation of `OAuth2AuthorizedClientService` is `InMemoryOAuth2AuthorizedClientService`, which stores `OAuth2AuthorizedClient` objects in-memory. Alternatively, you can configure the JDBC implementation `JdbcOAuth2AuthorizedClientService` to persist `OAuth2AuthorizedClient` instances in a database. -NOTE: `JdbcOAuth2AuthorizedClientService` depends on the table definition described in <>. - +[NOTE] +==== +`JdbcOAuth2AuthorizedClientService` depends on the table definition described in <>. +==== [[oauth2Client-authorized-manager-provider]] ==== OAuth2AuthorizedClientManager and OAuth2AuthorizedClientProvider @@ -616,12 +627,18 @@ This section describes Spring Security's support for authorization grants. [[oauth2Client-auth-code-grant]] ==== Authorization Code -NOTE: See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.1[Authorization Code] grant. +[NOTE] +==== +See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.1[Authorization Code] grant. +==== ===== Obtaining Authorization -NOTE: See the https://tools.ietf.org/html/rfc6749#section-4.1.1[Authorization Request/Response] protocol flow for the Authorization Code grant. +[NOTE] +==== +See the https://tools.ietf.org/html/rfc6749#section-4.1.1[Authorization Request/Response] protocol flow for the Authorization Code grant. +==== ===== Initiating the Authorization Request @@ -656,8 +673,11 @@ spring: Given the preceding properties, a request with the base path `/oauth2/authorization/okta` initiates the Authorization Request redirect by the `OAuth2AuthorizationRequestRedirectFilter` and ultimately starts the Authorization Code grant flow. -NOTE: The `AuthorizationCodeOAuth2AuthorizedClientProvider` is an implementation of `OAuth2AuthorizedClientProvider` for the Authorization Code grant, +[NOTE] +==== +The `AuthorizationCodeOAuth2AuthorizedClientProvider` is an implementation of `OAuth2AuthorizedClientProvider` for the Authorization Code grant, which also initiates the Authorization Request redirect by the `OAuth2AuthorizationRequestRedirectFilter`. +==== If the OAuth 2.0 Client is a https://tools.ietf.org/html/rfc6749#section-2.1[Public Client], configure the OAuth 2.0 Client registration as follows: @@ -704,7 +724,10 @@ spring: ---- ==== -NOTE: `+{baseUrl}+` resolves to `+{baseScheme}://{baseHost}{basePort}{basePath}+` +[NOTE] +==== +`+{baseUrl}+` resolves to `+{baseScheme}://{baseHost}{basePort}{basePath}+` +==== Configuring the `redirect-uri` with `URI` template variables is especially useful when the OAuth 2.0 Client is running behind a <>. Doing so ensures that the `X-Forwarded-*` headers are used when expanding the `redirect-uri`. @@ -716,7 +739,10 @@ One of the primary use cases an `OAuth2AuthorizationRequestResolver` can realize For example, OpenID Connect defines additional OAuth 2.0 request parameters for the https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest[Authorization Code Flow] extending from the standard parameters defined in the https://tools.ietf.org/html/rfc6749#section-4.1.1[OAuth 2.0 Authorization Framework]. One of those extended parameters is the `prompt` parameter. -NOTE: The `prompt` parameter is optional. Space delimited, case sensitive list of ASCII string values that specifies whether the Authorization Server prompts the End-User for re-authentication and consent. The defined values are: `none`, `login`, `consent`, and `select_account`. +[NOTE] +==== +The `prompt` parameter is optional. Space delimited, case sensitive list of ASCII string values that specifies whether the Authorization Server prompts the End-User for re-authentication and consent. The defined values are: `none`, `login`, `consent`, and `select_account`. +==== The following example shows how to configure the `DefaultOAuth2AuthorizationRequestResolver` with a `Consumer` that customizes the Authorization Request for `oauth2Login()`, by including the request parameter `prompt=consent`. @@ -825,7 +851,10 @@ spring: The preceding example shows the common use case of adding a custom parameter on top of the standard parameters. Alternatively, if your requirements are more advanced, you can take full control in building the Authorization Request URI by overriding the `OAuth2AuthorizationRequest.authorizationRequestUri` property. -TIP: `OAuth2AuthorizationRequest.Builder.build()` constructs the `OAuth2AuthorizationRequest.authorizationRequestUri`, which represents the Authorization Request URI that includes all query parameters that use the `application/x-www-form-urlencoded` format. +[TIP] +==== +`OAuth2AuthorizationRequest.Builder.build()` constructs the `OAuth2AuthorizationRequest.authorizationRequestUri`, which represents the Authorization Request URI that includes all query parameters that use the `application/x-www-form-urlencoded` format. +==== The following example shows a variation of `authorizationRequestCustomizer()` from the preceding example and instead overrides the `OAuth2AuthorizationRequest.authorizationRequestUri` property: @@ -860,7 +889,10 @@ private fun authorizationRequestCustomizer(): Consumer, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`. @@ -1025,12 +1066,18 @@ class OAuth2ClientSecurityConfig : WebSecurityConfigurerAdapter() { [[oauth2Client-refresh-token-grant]] ==== Refresh Token -NOTE: See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.5[Refresh Token]. +[NOTE] +==== +See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.5[Refresh Token]. +==== ===== Refreshing an Access Token -NOTE: See the https://tools.ietf.org/html/rfc6749#section-6[Access Token Request/Response] protocol flow for the Refresh Token grant. +[NOTE] +==== +See the https://tools.ietf.org/html/rfc6749#section-6[Access Token Request/Response] protocol flow for the Refresh Token grant. +==== The default implementation of `OAuth2AccessTokenResponseClient` for the Refresh Token grant is `DefaultRefreshTokenTokenResponseClient`, which uses a `RestOperations` when refreshing an access token at the Authorization Server’s Token Endpoint. @@ -1043,7 +1090,10 @@ If you need to customize the pre-processing of the Token Request, you can provid The default implementation (`OAuth2RefreshTokenGrantRequestEntityConverter`) builds a `RequestEntity` representation of a standard https://tools.ietf.org/html/rfc6749#section-6[OAuth 2.0 Access Token Request]. However, providing a custom `Converter` would let you extend the standard Token Request and add custom parameter(s). -IMPORTANT: The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider. +[IMPORTANT] +==== +The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider. +==== ===== Customizing the Access Token Response @@ -1073,7 +1123,10 @@ restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler() ---- ==== -TIP: Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request. +[TIP] +==== +Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request. +==== `OAuth2AccessTokenResponseHttpMessageConverter` is a `HttpMessageConverter` for an OAuth 2.0 Access Token Response. You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setTokenResponseConverter()` with a custom `Converter, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`. @@ -1129,12 +1182,18 @@ If the `OAuth2AuthorizedClient.getRefreshToken()` is available and the `OAuth2Au [[oauth2Client-client-creds-grant]] ==== Client Credentials -NOTE: See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.4[Client Credentials] grant. +[NOTE] +==== +See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.4[Client Credentials] grant. +==== ===== Requesting an Access Token -NOTE: See the https://tools.ietf.org/html/rfc6749#section-4.4.2[Access Token Request/Response] protocol flow for the Client Credentials grant. +[NOTE] +==== +See the https://tools.ietf.org/html/rfc6749#section-4.4.2[Access Token Request/Response] protocol flow for the Client Credentials grant. +==== The default implementation of `OAuth2AccessTokenResponseClient` for the Client Credentials grant is `DefaultClientCredentialsTokenResponseClient`, which uses a `RestOperations` when requesting an access token at the Authorization Server’s Token Endpoint. @@ -1147,7 +1206,10 @@ If you need to customize the pre-processing of the Token Request, you can provid The default implementation (`OAuth2ClientCredentialsGrantRequestEntityConverter`) builds a `RequestEntity` representation of a standard https://tools.ietf.org/html/rfc6749#section-4.4.2[OAuth 2.0 Access Token Request]. However, providing a custom `Converter` would let you extend the standard Token Request and add custom parameter(s). -IMPORTANT: The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider. +[IMPORTANT] +==== +The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider. +==== ===== Customizing the Access Token Response @@ -1177,7 +1239,10 @@ restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler() ---- ==== -TIP: Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request. +[TIP] +==== +Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request. +==== `OAuth2AccessTokenResponseHttpMessageConverter` is a `HttpMessageConverter` for an OAuth 2.0 Access Token Response. You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setTokenResponseConverter()` with a custom `Converter, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`. @@ -1220,8 +1285,12 @@ authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider) ---- ==== -NOTE: `OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials()` configures a `ClientCredentialsOAuth2AuthorizedClientProvider`, +[NOTE] +==== +`OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials()` configures a `ClientCredentialsOAuth2AuthorizedClientProvider`, which is an implementation of an `OAuth2AuthorizedClientProvider` for the Client Credentials grant. +==== + ===== Using the Access Token @@ -1354,19 +1423,28 @@ class OAuth2ClientController { ---- ==== -NOTE: `HttpServletRequest` and `HttpServletResponse` are both OPTIONAL attributes. +[NOTE] +==== +`HttpServletRequest` and `HttpServletResponse` are both OPTIONAL attributes. If not provided, they default to `ServletRequestAttributes` by using `RequestContextHolder.getRequestAttributes()`. +==== [[oauth2Client-password-grant]] ==== Resource Owner Password Credentials -NOTE: See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.3[Resource Owner Password Credentials] grant. +[NOTE] +==== +See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.3[Resource Owner Password Credentials] grant. +==== ===== Requesting an Access Token -NOTE: See the https://tools.ietf.org/html/rfc6749#section-4.3.2[Access Token Request/Response] protocol flow for the Resource Owner Password Credentials grant. +[NOTE] +==== +See the https://tools.ietf.org/html/rfc6749#section-4.3.2[Access Token Request/Response] protocol flow for the Resource Owner Password Credentials grant. +==== The default implementation of `OAuth2AccessTokenResponseClient` for the Resource Owner Password Credentials grant is `DefaultPasswordTokenResponseClient`, which uses a `RestOperations` when requesting an access token at the Authorization Server’s Token Endpoint. @@ -1379,7 +1457,10 @@ If you need to customize the pre-processing of the Token Request, you can provid The default implementation (`OAuth2PasswordGrantRequestEntityConverter`) builds a `RequestEntity` representation of a standard https://tools.ietf.org/html/rfc6749#section-4.3.2[OAuth 2.0 Access Token Request]. However, providing a custom `Converter` would let you extend the standard Token Request and add custom parameter(s). -IMPORTANT: The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider. +[IMPORTANT] +==== +The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider. +==== ===== Customizing the Access Token Response @@ -1409,7 +1490,10 @@ restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler() ---- ==== -TIP: Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request. +[TIP] +==== +Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request. +==== `OAuth2AccessTokenResponseHttpMessageConverter` is a `HttpMessageConverter` for an OAuth 2.0 Access Token Response. You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setTokenResponseConverter()` with a custom `Converter, OAuth2AccessTokenResponse>` that is used to convert the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`. @@ -1685,7 +1769,10 @@ restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler() ---- ==== -TIP: Spring MVC `FormHttpMessageConverter` is required as it's used when sending the OAuth 2.0 Access Token Request. +[TIP] +==== +Spring MVC `FormHttpMessageConverter` is required as it's used when sending the OAuth 2.0 Access Token Request. +==== `OAuth2AccessTokenResponseHttpMessageConverter` is a `HttpMessageConverter` for an OAuth 2.0 Access Token Response. You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setTokenResponseConverter()` with a custom `Converter, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`. @@ -2246,8 +2333,10 @@ fun webClient(authorizedClientManager: OAuth2AuthorizedClientManager?): WebClien ---- ==== -WARNING: Be cautious with this feature, since all HTTP requests receive the access token. - +[WARNING] +==== +Be cautious with this feature, since all HTTP requests receive the access token. +==== Alternatively, if `setDefaultClientRegistrationId("okta")` is configured with a valid `ClientRegistration`, the `OAuth2AccessToken` associated with the `OAuth2AuthorizedClient` is used. The following code shows the specific configuration: @@ -2281,4 +2370,7 @@ fun webClient(authorizedClientManager: OAuth2AuthorizedClientManager?): WebClien ---- ==== -WARNING: Be cautious with this feature, since all HTTP requests receive the access token. +[WARNING] +==== +Be cautious with this feature, since all HTTP requests receive the access token. +==== diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-login.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-login.adoc index e2cd5bdde1..e134815b6b 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-login.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-login.adoc @@ -4,7 +4,10 @@ The OAuth 2.0 Login feature lets an application have users log in to the application by using their existing account at an OAuth 2.0 Provider (such as GitHub) or OpenID Connect 1.0 Provider (such as Google). OAuth 2.0 Login implements two use cases: "`Login with Google`" or "`Login with GitHub`". -NOTE: OAuth 2.0 Login is implemented by using the *Authorization Code Grant*, as specified in the https://tools.ietf.org/html/rfc6749#section-4.1[OAuth 2.0 Authorization Framework] and https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[OpenID Connect Core 1.0]. +[NOTE] +==== +OAuth 2.0 Login is implemented by using the *Authorization Code Grant*, as specified in the https://tools.ietf.org/html/rfc6749#section-4.1[OAuth 2.0 Authorization Framework] and https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[OpenID Connect Core 1.0]. +==== [[oauth2login-sample-boot]] @@ -25,7 +28,10 @@ This section shows how to configure the {gh-samples-url}/boot/oauth2login[*OAuth To use Google's OAuth 2.0 authentication system for login, you must set up a project in the Google API Console to obtain OAuth 2.0 credentials. -NOTE: https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the https://openid.net/connect/[OpenID Connect 1.0] specification and is https://openid.net/certification/[OpenID certified]. +[NOTE] +==== +https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the https://openid.net/connect/[OpenID Connect 1.0] specification and is https://openid.net/certification/[OpenID certified]. +==== Follow the instructions on the https://developers.google.com/identity/protocols/OpenIDConnect[OpenID Connect] page, starting in the "`Setting up OAuth 2.0`" section. @@ -39,11 +45,17 @@ The redirect URI is the path in the application that the end-user's user-agent i In the "`Set a redirect URI`" subsection, ensure that the *Authorized redirect URIs* field is set to `http://localhost:8080/login/oauth2/code/google`. -TIP: The default redirect URI template is `+{baseUrl}/login/oauth2/code/{registrationId}+`. +[TIP] +==== +The default redirect URI template is `+{baseUrl}/login/oauth2/code/{registrationId}+`. The `registrationId` is a unique identifier for the <>. +==== -IMPORTANT: If the OAuth Client runs behind a proxy server, you should check the <> to ensure the application is correctly configured. +[IMPORTANT] +==== +If the OAuth Client runs behind a proxy server, you should check the <> to ensure the application is correctly configured. Also, see the supported <> for `redirect-uri`. +==== [[oauth2login-sample-application-config]] @@ -144,7 +156,10 @@ The following table outlines the mapping of the Spring Boot 2.x OAuth Client pro |`providerDetails.userInfoEndpoint.userNameAttributeName` |=== -TIP: You can initially configure a `ClientRegistration` by using discovery of an OpenID Connect Provider's https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Configuration endpoint] or an Authorization Server's https://tools.ietf.org/html/rfc8414#section-3[Metadata endpoint], by specifying the `spring.security.oauth2.client.provider._[providerId]_.issuer-uri` property. +[TIP] +==== +You can initially configure a `ClientRegistration` by using discovery of an OpenID Connect Provider's https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Configuration endpoint] or an Authorization Server's https://tools.ietf.org/html/rfc8414#section-3[Metadata endpoint], by specifying the `spring.security.oauth2.client.provider._[providerId]_.issuer-uri` property. +==== [[oauth2login-common-oauth2-provider]] @@ -732,8 +747,11 @@ The following sections go into more detail on each of the configuration options By default, the OAuth 2.0 Login Page is auto-generated by the `DefaultLoginPageGeneratingFilter`. The default login page shows each configured OAuth Client with its `ClientRegistration.clientName` as a link, which is capable of initiating the Authorization Request (or OAuth 2.0 Login). -NOTE: For `DefaultLoginPageGeneratingFilter` to show links for configured OAuth Clients, the registered `ClientRegistrationRepository` needs to also implement `Iterable`. +[NOTE] +==== +For `DefaultLoginPageGeneratingFilter` to show links for configured OAuth Clients, the registered `ClientRegistrationRepository` needs to also implement `Iterable`. See `InMemoryClientRegistrationRepository` for reference. +==== The link's destination for each OAuth Client defaults to the following: @@ -805,7 +823,10 @@ class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() { ---- ==== -IMPORTANT: You need to provide a `@Controller` with a `@RequestMapping("/login/oauth2")` that is capable of rendering the custom login page. +[IMPORTANT] +==== +You need to provide a `@Controller` with a `@RequestMapping("/login/oauth2")` that is capable of rendering the custom login page. +==== [TIP] ===== @@ -828,8 +849,11 @@ The following line shows an example: The Redirection Endpoint is used by the Authorization Server for returning the Authorization Response (which contains the authorization credentials) to the client through the Resource Owner user-agent. -TIP: OAuth 2.0 Login leverages the Authorization Code Grant. +[TIP] +==== +OAuth 2.0 Login leverages the Authorization Code Grant. Therefore, the authorization credential is the authorization code. +==== The default Authorization Response `baseUri` (redirection endpoint) is `*/login/oauth2/code/**`, which is defined in `OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI`. @@ -1191,7 +1215,10 @@ class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() { `DefaultOAuth2UserService` is an implementation of an `OAuth2UserService` that supports standard OAuth 2.0 Provider's. -NOTE: `OAuth2UserService` obtains the user attributes of the end-user (the resource owner) from the UserInfo Endpoint (by using the access token granted to the client during the authorization flow) and returns an `AuthenticatedPrincipal` in the form of an `OAuth2User`. +[NOTE] +==== +`OAuth2UserService` obtains the user attributes of the end-user (the resource owner) from the UserInfo Endpoint (by using the access token granted to the client during the authorization flow) and returns an `AuthenticatedPrincipal` in the form of an `OAuth2User`. +==== `DefaultOAuth2UserService` uses a `RestOperations` instance when requesting the user attributes at the UserInfo Endpoint. @@ -1361,9 +1388,15 @@ fun idTokenDecoderFactory(): JwtDecoderFactory { ---- ==== -NOTE: For MAC-based algorithms (such as `HS256`, `HS384`, or `HS512`), the `client-secret` that corresponds to the `client-id` is used as the symmetric key for signature verification. +[NOTE] +==== +For MAC-based algorithms (such as `HS256`, `HS384`, or `HS512`), the `client-secret` that corresponds to the `client-id` is used as the symmetric key for signature verification. +==== -TIP: If more than one `ClientRegistration` is configured for OpenID Connect 1.0 Authentication, the JWS algorithm resolver may evaluate the provided `ClientRegistration` to determine which algorithm to return. +[TIP] +==== +If more than one `ClientRegistration` is configured for OpenID Connect 1.0 Authentication, the JWS algorithm resolver may evaluate the provided `ClientRegistration` to determine which algorithm to return. +==== [[oauth2login-advanced-oidc-logout]] @@ -1433,9 +1466,11 @@ public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter { ---- ==== -[subs="none"] -NOTE: `OidcClientInitiatedLogoutSuccessHandler` supports the `{baseUrl}` placeholder. +[NOTE] +==== +`OidcClientInitiatedLogoutSuccessHandler` supports the `+{baseUrl}+` placeholder. If used, the application's base URL, such as `https://app.example.org`, replaces it at request time. +==== .Kotlin ==== @@ -1470,6 +1505,8 @@ class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() { ---- ==== -[subs="none"] -NOTE: `OidcClientInitiatedLogoutSuccessHandler` supports the `{baseUrl}` placeholder. +[NOTE] +==== +`OidcClientInitiatedLogoutSuccessHandler` supports the `+{baseUrl}+` placeholder. If used, the application's base URL, such as `https://app.example.org`, replaces it at request time. +==== diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-resourceserver.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-resourceserver.adoc index f5b2ea6dc1..9f7fba6ae3 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-resourceserver.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/oauth2/oauth2-resourceserver.adoc @@ -13,7 +13,10 @@ This authorization server can be consulted by resource servers to authorize requ This section details how Spring Security provides support for OAuth 2.0 https://tools.ietf.org/html/rfc6750.html[Bearer Tokens]. -NOTE: Working samples for both {gh-samples-url}/boot/oauth2resourceserver[JWTs] and {gh-samples-url}/boot/oauth2resourceserver-opaque[Opaque Tokens] are available in the {gh-samples-url}[Spring Security repository]. +[NOTE] +==== +Working samples for both {gh-samples-url}/boot/oauth2resourceserver[JWTs] and {gh-samples-url}/boot/oauth2resourceserver-opaque[Opaque Tokens] are available in the {gh-samples-url}[Spring Security repository]. +==== Now we can consider how Bearer Token Authentication works within Spring Security. First, we see that, as with <>, the https://tools.ietf.org/html/rfc7235#section-4.1[WWW-Authenticate] header is sent back to an unauthenticated client: @@ -29,7 +32,10 @@ image:{icondir}/number_3.png[] Since the user is not authenticated, <> is an instance of {security-api-url}org/springframework/security/oauth2/server/resource/authentication/BearerTokenAuthenticationEntryPoint.html[`BearerTokenAuthenticationEntryPoint`], which sends a `WWW-Authenticate` header. The `RequestCache` is typically a `NullRequestCache` that does not save the request, since the client is capable of replaying the requests it originally requested. -NOTE: The preceding figure builds off of our <> diagram. +[NOTE] +==== +The preceding figure builds off of our <> diagram. +==== When a client receives the `WWW-Authenticate: Bearer` header, it knows it should retry with a bearer token. The following image shows the flow for the bearer token being processed: @@ -53,7 +59,10 @@ image:{icondir}/number_4.png[] If authentication is successful, then __Success__ * The <> is set on the <>. * The `BearerTokenAuthenticationFilter` invokes `FilterChain.doFilter(request,response)` to continue with the rest of the application logic. -NOTE: The preceding figure builds off our <> diagram. +[NOTE] +==== +The preceding figure builds off our <> diagram. +==== [[oauth2resourceserver-jwt-minimaldependencies]] === Minimal Dependencies for JWT @@ -88,8 +97,11 @@ spring: Resource Server uses this property to further self-configure, discover the authorization server's public keys, and, subsequently, validate incoming JWTs. -NOTE: To use the `issuer-uri` property, it must also be true that one of `https://idp.example.com/issuer/.well-known/openid-configuration`, `https://idp.example.com/.well-known/openid-configuration/issuer`, or `https://idp.example.com/.well-known/oauth-authorization-server/issuer` is a supported endpoint for the authorization server. +[NOTE] +==== +To use the `issuer-uri` property, it must also be true that one of `https://idp.example.com/issuer/.well-known/openid-configuration`, `https://idp.example.com/.well-known/openid-configuration/issuer`, or `https://idp.example.com/.well-known/oauth-authorization-server/issuer` is a supported endpoint for the authorization server. This endpoint is referred to as a https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Provider Configuration] endpoint or a https://tools.ietf.org/html/rfc8414#section-3[Authorization Server Metadata] endpoint. +==== ==== Startup Expectations @@ -104,7 +116,10 @@ It achieves this through a deterministic startup process: A consequence of this process is that the authorization server must be up and receiving requests for Resource Server to successfully start up. -NOTE: If the authorization server is down when Resource Server queries it (given appropriate timeouts), startup fails. +[NOTE] +==== +If the authorization server is down when Resource Server queries it (given appropriate timeouts), startup fails. +==== ==== Runtime Expectations @@ -126,7 +141,10 @@ Given a well-formed JWT, Resource Server: . Validates the JWT's `exp` and `nbf` timestamps and the JWT's `iss` claim. . Maps each scope to an authority with the prefix `SCOPE_`. -NOTE: As the authorization server makes available new keys, Spring Security automatically rotates the keys used to validate JWTs. +[NOTE] +==== +As the authorization server makes available new keys, Spring Security automatically rotates the keys used to validate JWTs. +==== The resulting `Authentication#getPrincipal`, by default, is a Spring Security `Jwt` object, and `Authentication#getName` maps to the JWT's `sub` property, if one is present. @@ -180,12 +198,19 @@ spring: ---- ==== -NOTE: The JWK Set URI is not standardized, but you can typically find it in the authorization server's documentation. +[NOTE] +==== +The JWK Set URI is not standardized, but you can typically find it in the authorization server's documentation. +==== Consequently, Resource Server does not ping the authorization server at startup. We still specify the `issuer-uri` so that Resource Server still validates the `iss` claim on incoming JWTs. -NOTE: You can also supply this property directly on the <>. +[NOTE] +==== +You can also supply this property directly on the <>. +==== + [[oauth2resourceserver-jwt-sansboot]] === Overriding or Replacing Boot Auto Configuration @@ -300,7 +325,10 @@ fun jwtDecoder(): JwtDecoder { ---- ==== -NOTE: Calling `{security-api-url}org/springframework/security/oauth2/jwt/JwtDecoders.html#fromIssuerLocation-java.lang.String-[JwtDecoders#fromIssuerLocation]` invokes the Provider Configuration or Authorization Server Metadata endpoint, to derive the JWK Set URI. +[NOTE] +==== +Calling `{security-api-url}org/springframework/security/oauth2/jwt/JwtDecoders.html#fromIssuerLocation-java.lang.String-[JwtDecoders#fromIssuerLocation]` invokes the Provider Configuration or Authorization Server Metadata endpoint, to derive the JWK Set URI. +==== If the application does not expose a `JwtDecoder` bean, Spring Boot exposes the earlier default one. @@ -1074,6 +1102,8 @@ fun jwtDecoder(): JwtDecoder { [NOTE] By default, Resource Server configures a clock skew of 60 seconds. +==== + [[oauth2resourceserver-jwt-validation-custom]] ==== Configuring a Custom Validator @@ -1426,10 +1456,17 @@ fun jwtDecoder(cacheManager: CacheManager): JwtDecoder { When given a `Cache`, Resource Server uses the JWK Set URI as the key and the JWK Set JSON as the value. -NOTE: Spring is not a cache provider, so you need to make sure to include the appropriate dependencies, such as `spring-boot-starter-cache` and your favorite caching provider. +[NOTE] +==== +Spring is not a cache provider, so you need to make sure to include the appropriate dependencies, such as `spring-boot-starter-cache` and your favorite caching provider. +==== -NOTE: Whether it is socket or cache timeouts, you may instead want to work with Nimbus directly. +[NOTE] +==== +Whether it is socket or cache timeouts, you may instead want to work with Nimbus directly. To do so, remember that `NimbusJwtDecoder` ships with a constructor that takes Nimbus's `JWTProcessor`. +==== + [[oauth2resourceserver-opaque-minimaldependencies]] === Minimal Dependencies for Introspection @@ -1471,8 +1508,12 @@ Where `https://idp.example.com/introspect` is the introspection endpoint hosted Resource Server uses these properties to further self-configure and subsequently validate incoming JWTs. -NOTE: When using introspection, the authorization server's word is law. +[NOTE] +==== +When using introspection, the authorization server's word is law. If the authorization server responsed that the token is valid, it is. +==== + ==== Startup Expectations @@ -2377,7 +2418,10 @@ fun tokenAuthenticationManagerResolver(): AuthenticationManagerResolver>. +==== [[oauth2resourceserver-bearertoken-failure]] === Bearer Token Failure diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc index 11ed3058b9..b93bd85508 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/saml2/saml2-login.adoc @@ -5,15 +5,21 @@ The SAML 2.0 Login feature provides an application with the ability to act as a SAML 2.0 relying party, having users https://wiki.shibboleth.net/confluence/display/CONCEPT/FlowsAndConfig[log in] to the application by using their existing account at a SAML 2.0 Asserting Party (Okta, ADFS, and others). -NOTE: SAML 2.0 Login is implemented by using the *Web Browser SSO Profile*, as specified in +[NOTE] +==== +SAML 2.0 Login is implemented by using the *Web Browser SSO Profile*, as specified in https://www.oasis-open.org/committees/download.php/35389/sstc-saml-profiles-errata-2.0-wd-06-diff.pdf#page=15[SAML 2 Profiles]. +==== [[servlet-saml2login-spring-security-history]] Since 2009, support for relying parties has existed as an https://github.com/spring-projects/spring-security-saml/tree/1e013b07a7772defd6a26fcfae187c9bf661ee8f#spring-saml[extension project]. In 2019, the process began to port that into https://github.com/spring-projects/spring-security[Spring Security] proper. This process is similar to the one started in 2017 for <>. -NOTE: A working sample for {gh-samples-url}/boot/saml2login[SAML 2.0 Login] is available in the {gh-samples-url}[Spring Security repository]. +[NOTE] +==== +A working sample for {gh-samples-url}/boot/saml2login[SAML 2.0 Login] is available in the {gh-samples-url}[Spring Security repository]. +==== We start by examining how SAML 2.0 Relying Party Authentication works within Spring Security. First, we see that, like <>, Spring Security takes the user to a third party for performing authentication. @@ -22,7 +28,10 @@ It does this through a series of redirects: .Redirecting to Asserting Party Authentication image::{figures}/saml2webssoauthenticationrequestfilter.png[] -NOTE: The preceding figure above builds off our <> and <> diagrams. +[NOTE] +==== +The preceding figure above builds off our <> and <> diagrams. +==== image:{icondir}/number_1.png[] First, a user makes an unauthenticated request to the `/private` resource, for which it is not authorized. @@ -46,7 +55,10 @@ The following image shows how Spring Security authenticates a `` .Authenticating a `` image::{figures}/saml2webssoauthenticationfilter.png[] -NOTE: The figure builds off our <> diagram. +[NOTE] +==== +The figure builds off our <> diagram. +==== image:{icondir}/number_1.png[] When the browser submits a `` to the application, it <>. This filter calls its configured `AuthenticationConverter` to create a `Saml2AuthenticationToken` by extracting the response from the `HttpServletRequest`. @@ -110,8 +122,11 @@ where: * `classpath:idp.crt` is the location on the classpath for the identity provider's certificate for verifying SAML responses. * `https://idp.example.com/issuer/sso` is the endpoint where the identity provider is expecting `AuthnRequest` instances. -NOTE: Identity Provider and Asserting Party are synonymous, as are Service Provider and Relying Party. +[NOTE] +==== +Identity Provider and Asserting Party are synonymous, as are Service Provider and Relying Party. These are frequently abbreviated as AP and RP, respectively. +==== ==== Runtime Expectations @@ -158,7 +173,10 @@ For example, once your application receives a `SAMLResponse` and delegates to `S .Authenticating an OpenSAML `Response` image:{figures}/opensamlauthenticationprovider.png[] -NOTE: This figure builds off of the <>. +[NOTE] +==== +This figure builds off of the <>. +==== image:{icondir}/number_1.png[] The `Saml2WebSsoAuthenticationFilter` formulates the `Saml2AuthenticationToken` and invokes the <>. @@ -373,7 +391,10 @@ public RelyingPartyRegistrationRepository relyingPartyRegistrations() throws Exc ---- ==== -NOTE: `X509Support` is an OpenSAML class, used in the preceding snippet for brevity. +[NOTE] +==== +`X509Support` is an OpenSAML class, used in the preceding snippet for brevity. +==== [[servlet-saml2login-relyingpartyregistrationrepository-dsl]] Alternatively, you can directly wire up the repository by using the DSL, which also overrides the auto-configured `WebSecurityConfigurerAdapter`: @@ -418,8 +439,10 @@ class MyCustomSecurityConfiguration : WebSecurityConfigurerAdapter() { ---- ==== -NOTE: A relying party can be multi-tenant by registering more than one relying party in the `RelyingPartyRegistrationRepository`. - +[NOTE] +==== +A relying party can be multi-tenant by registering more than one relying party in the `RelyingPartyRegistrationRepository`. +==== [[servlet-saml2login-relyingpartyregistration]] === RelyingPartyRegistration A {security-api-url}org/springframework/security/saml2/provider/service/registration/RelyingPartyRegistration.html[`RelyingPartyRegistration`] @@ -458,10 +481,16 @@ RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration.wit ---- ==== -TIP: The top-level metadata methods are details about the relying party. +[TIP] +==== +The top-level metadata methods are details about the relying party. The methods inside `assertingPartyDetails` are details about the asserting party. +==== -NOTE: The location where a relying party is expecting SAML Responses is the Assertion Consumer Service Location. +[NOTE] +==== +The location where a relying party is expecting SAML Responses is the Assertion Consumer Service Location. +==== The default for the relying party's `entityId` is `+{baseUrl}/saml2/service-provider-metadata/{registrationId}+`. You need this value when you configure the asserting party to know about your relying party. @@ -543,7 +572,11 @@ try (InputStream is = resource.getInputStream()) { ---- ==== -TIP: When you specify the locations of these files as the appropriate Spring Boot properties, Spring Boot performs these conversions for you. +[TIP] +==== +When you specify the locations of these files as the appropriate Spring Boot properties, Spring Boot performs these conversions for you. +==== + [[servlet-saml2login-rpr-relyingpartyregistrationresolver]] ==== Resolving the Relying Party from the Request @@ -576,7 +609,10 @@ public class SingleRelyingPartyRegistrationResolver Then you can provide this resolver to the appropriate filters that <` instances>>, <` instances>>, and <` metadata>>. -NOTE: Remember that, if you have any placeholders in your `RelyingPartyRegistration`, your resolver implementation should resolve them. +[NOTE] +==== +Remember that, if you have any placeholders in your `RelyingPartyRegistration`, your resolver implementation should resolve them. +==== [[servlet-saml2login-rpr-duplicated]] ==== Duplicated Relying Party Configurations @@ -716,9 +752,12 @@ RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations.fr ---- ==== -NOTE: The preceding snippet uses the OpenSAML `SignatureConstants` class to supply the algorithm name. +[NOTE] +==== +The preceding snippet uses the OpenSAML `SignatureConstants` class to supply the algorithm name. However, that is only for convenience. Since the datatype is `String`, you can supply the name of the algorithm directly. +==== [[servlet-saml2login-sp-initiated-factory-binding]] Some asserting parties require that the `` be POSTed. @@ -897,8 +936,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { <3> Return a custom authentication that includes the user details ==== -NOTE: You need not call the default authentication converter of `OpenSamlAuthenticationProvider`. +[NOTE] +==== +You need not call the default authentication converter of `OpenSamlAuthenticationProvider`. It returns a `Saml2AuthenticatedPrincipal` that contains the attributes it extracted from `AttributeStatement` instances as well as the single `ROLE_USER` authority. +==== [[servlet-saml2login-opensamlauthenticationprovider-additionalvalidation]] ==== Performing Additional Validation @@ -938,8 +980,11 @@ provider.setAssertionValidator(assertionToken -> { ---- ==== -NOTE: While recommended, you need not call the default assertion validator of `OpenSamlAuthenticationProvider`. +[NOTE] +==== +While recommended, you need not call the default assertion validator of `OpenSamlAuthenticationProvider`. For example, you could skip it if you do not need to check the `` or the `` because you are doing those yourself. +==== [[servlet-saml2login-opensamlauthenticationprovider-decryption]] ==== Customizing Decryption @@ -971,9 +1016,12 @@ provider.setAssertionElementsDecrypter((assertionToken) -> decryptionService.dec ---- ==== -NOTE: We have two separate decrypters, because assertions can be signed separately from responses. +[NOTE] +==== +We have two separate decrypters, because assertions can be signed separately from responses. Trying to decrypt a signed assertion's elements before signature verification may invalidate the signature. If your asserting party signs only the response, it is safe to decrypt all elements by using only the response decrypter. +==== [[servlet-saml2login-authenticationmanager-custom]] ==== Using a Custom Authentication Manager @@ -1027,8 +1075,12 @@ public class MainController { ---- ==== -TIP: Because the SAML 2.0 specification lets each attribute have multiple values, you can either call `getAttribute` to get the list of attributes or `getFirstAttribute` to get the first in the list. +[TIP] +==== +Because the SAML 2.0 specification lets each attribute have multiple values, you can either call `getAttribute` to get the list of attributes or `getFirstAttribute` to get the first in the list. `getFirstAttribute` is handy when you know that there is only one value. +==== + [[servlet-saml2login-metadata]] === Producing `` Metadata diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/test/index.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/test/index.adoc index ae8ef2de74..2e3025847a 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/test/index.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/test/index.adoc @@ -3,7 +3,10 @@ This section describes the testing support provided by Spring Security. -NOTE: To use the Spring Security test support, you must include `spring-security-test-{spring-security-version}.jar` as a dependency of your project. +[NOTE] +==== +To use the Spring Security test support, you must include `spring-security-test-{spring-security-version}.jar` as a dependency of your project. +==== include::method.adoc[] diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/test/method.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/test/method.adoc index 316cf6c4d0..aeb883cbcc 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/test/method.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/test/method.adoc @@ -47,11 +47,14 @@ public class WithMockUserTests { <2> `@ContextConfiguration` instructs the Spring test configuration to use to create the `ApplicationContext`. Since no configuration is specified, the default configuration locations are tried. This is no different than using the existing Spring test support. For additional information, see the https://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/htmlsingle/#testcontext-ctx-management[Spring Reference]. ==== -NOTE: Spring Security hooks into Spring Test support through the `WithSecurityContextTestExecutionListener`, which ensures that our tests are run with the correct user. +[NOTE] +==== +Spring Security hooks into Spring Test support through the `WithSecurityContextTestExecutionListener`, which ensures that our tests are run with the correct user. It does this by populating the `SecurityContextHolder` prior to running our tests. If you use reactive method security, you also need `ReactorContextTestExecutionListener`, which populates `ReactiveSecurityContextHolder`. After the test is done, it clears out the `SecurityContextHolder`. If you need only Spring Security related support, you can replace `@ContextConfiguration` with `@SecurityTestExecutionListeners`. +==== Remember, we added the `@PreAuthorize` annotation to our `HelloMessageService`, so it requires an authenticated user to invoke it. If we run the tests, we expect the following test will pass: diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/test/mockmvc.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/test/mockmvc.adoc index aa380f4b33..468bd09165 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/test/mockmvc.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/test/mockmvc.adoc @@ -6,7 +6,10 @@ Spring Security provides comprehensive integration with https://docs.spring.io/s [[test-mockmvc-setup]] === Setting Up MockMvc and Spring Security -NOTE: Spring Security's testing support requires spring-test-4.1.3.RELEASE or greater. +[NOTE] +==== +Spring Security's testing support requires spring-test-4.1.3.RELEASE or greater. +==== To use Spring Security with Spring MVC Test, add the Spring Security `FilterChainProxy` as a `Filter`. You also need to add Spring Security's `TestSecurityContextHolderPostProcessor` to support <>.