Remove includes
This commit is contained in:
parent
59e7a10732
commit
c3dfb1711d
|
@ -5,10 +5,14 @@
|
||||||
** xref:overview/getting-spring-security.adoc[Getting Spring Security]
|
** xref:overview/getting-spring-security.adoc[Getting Spring Security]
|
||||||
** xref:overview/features/index.adoc[Features]
|
** xref:overview/features/index.adoc[Features]
|
||||||
*** xref:overview/features/authentication/index.adoc[Authentication]
|
*** xref:overview/features/authentication/index.adoc[Authentication]
|
||||||
|
**** xref:overview/features/authentication/password-storage.adoc[Password Storage]
|
||||||
*** xref:overview/features/exploits/index.adoc[Protection Against Exploits]
|
*** xref:overview/features/exploits/index.adoc[Protection Against Exploits]
|
||||||
|
**** xref:overview/features/exploits/csrf.adoc[CSRF]
|
||||||
|
**** xref:overview/features/exploits/headers.adoc[HTTP Headers]
|
||||||
|
**** xref:overview/features/exploits/http.adoc[HTTP Requests]
|
||||||
** xref:overview/modules.adoc[Project Modules & Dependencies]
|
** xref:overview/modules.adoc[Project Modules & Dependencies]
|
||||||
** xref:overview/samples.adoc[Samples]
|
** xref:overview/samples.adoc[Samples]
|
||||||
* Servlet Applications
|
* xref:servlet/index.adoc[Servlet Applications]
|
||||||
** xref:servlet/hello/index.adoc[Hello Spring Security]
|
** xref:servlet/hello/index.adoc[Hello Spring Security]
|
||||||
** xref:servlet/architecture/index.adoc[The Big Picture]
|
** xref:servlet/architecture/index.adoc[The Big Picture]
|
||||||
** Authentication
|
** Authentication
|
||||||
|
@ -37,31 +41,55 @@
|
||||||
*** xref:servlet/authentication/runas.adoc[Run-As]
|
*** xref:servlet/authentication/runas.adoc[Run-As]
|
||||||
*** xref:servlet/authentication/logout.adoc[Logout]
|
*** xref:servlet/authentication/logout.adoc[Logout]
|
||||||
*** xref:servlet/authentication/events.adoc[Authentication Events]
|
*** xref:servlet/authentication/events.adoc[Authentication Events]
|
||||||
** Authorization
|
** xref:servlet/authorization/index.adoc[Authorization]
|
||||||
*** xref:servlet/authorization/architecture.adoc[Authorization Architecture]
|
*** xref:servlet/authorization/architecture.adoc[Authorization Architecture]
|
||||||
*** xref:servlet/authorization/authorize-requests.adoc[Authorize HTTP Requests]
|
*** xref:servlet/authorization/authorize-requests.adoc[Authorize HTTP Requests]
|
||||||
*** xref:servlet/authorization/expression-based.adoc[Expression-Based Access Control]
|
*** xref:servlet/authorization/expression-based.adoc[Expression-Based Access Control]
|
||||||
*** xref:servlet/authorization/secure-objects.adoc[Secure Object Implementations]
|
*** xref:servlet/authorization/secure-objects.adoc[Secure Object Implementations]
|
||||||
*** xref:servlet/authorization/method-security.adoc[Method Security]
|
*** xref:servlet/authorization/method-security.adoc[Method Security]
|
||||||
*** xref:servlet/authorization/acls.adoc[Domain Object Security ACLs]
|
*** xref:servlet/authorization/acls.adoc[Domain Object Security ACLs]
|
||||||
** OAuth2
|
** xref:servlet/oauth2/index.adoc[OAuth2]
|
||||||
*** xref:servlet/oauth2/oauth2-login.adoc[OAuth2 Log In]
|
*** xref:servlet/oauth2/oauth2-login.adoc[OAuth2 Log In]
|
||||||
*** xref:servlet/oauth2/oauth2-client.adoc[OAuth2 Client]
|
*** xref:servlet/oauth2/oauth2-client.adoc[OAuth2 Client]
|
||||||
*** xref:servlet/oauth2/oauth2-resourceserver.adoc[OAuth2 Resource Server]
|
*** xref:servlet/oauth2/oauth2-resourceserver.adoc[OAuth2 Resource Server]
|
||||||
** xref:servlet/saml2/index.adoc[SAML2]
|
** xref:servlet/saml2/index.adoc[SAML2]
|
||||||
** xref:servlet/exploits/index.adoc[Protection Against Exploits]
|
** xref:servlet/exploits/index.adoc[Protection Against Exploits]
|
||||||
|
*** xref:servlet/exploits/csrf.adoc[]
|
||||||
|
*** xref:servlet/exploits/headers.adoc[]
|
||||||
|
*** xref:servlet/exploits/http.adoc[]
|
||||||
|
*** xref:servlet/exploits/firewall.adoc[
|
||||||
** xref:servlet/integrations/index.adoc[Integrations]
|
** xref:servlet/integrations/index.adoc[Integrations]
|
||||||
|
*** xref:servlet/integrations/servlet-api.adoc[Servlet APIs]
|
||||||
|
*** xref:servlet/integrations/data.adoc[Spring Data]
|
||||||
|
*** xref:servlet/integrations/concurrency.adoc[Java's Concurrency APIs]
|
||||||
|
*** xref:servlet/integrations/jackson.adoc[Jackson]
|
||||||
|
*** xref:servlet/integrations/localization.adoc[Localization]
|
||||||
|
*** xref:servlet/integrations/mvc.adoc[Spring MVC]
|
||||||
|
*** xref:servlet/integrations/websocket.adoc[WebSocket]
|
||||||
|
*** xref:servlet/integrations/cors.adoc[Spring's CORS Support]
|
||||||
|
*** xref:servlet/integrations/jsp-taglibs.adoc[JSP Taglib]
|
||||||
** Configuration
|
** Configuration
|
||||||
*** xref:servlet/java-configuration/index.adoc[Java Configuration]
|
*** xref:servlet/java-configuration/index.adoc[Java Configuration]
|
||||||
*** xref:servlet/kotlin-configuration/index.adoc[Kotlin Configuration]
|
*** xref:servlet/kotlin-configuration/index.adoc[Kotlin Configuration]
|
||||||
*** xref:servlet/namespace/index.adoc[Namespace Configuration]
|
*** xref:servlet/namespace/index.adoc[Namespace Configuration]
|
||||||
** xref:servlet/test/index.adoc[Testing]
|
** xref:servlet/test/index.adoc[Testing]
|
||||||
|
** xref:servlet/test/method.adoc[Method Security]
|
||||||
|
** xref:servlet/test/mockmvc.adoc[MockMvc Support]
|
||||||
** xref:servlet/crypto/index.adoc[Cryptography]
|
** xref:servlet/crypto/index.adoc[Cryptography]
|
||||||
** xref:servlet/appendix/index.adoc[Appendix]
|
** xref:servlet/appendix/index.adoc[Appendix]
|
||||||
* Reactive Applications
|
*** xref:servlet/appendix/database-schema.adoc[Database Schemas]
|
||||||
|
*** xref:servlet/appendix/namespace.adoc[XML Namespace]
|
||||||
|
*** xref:servlet/appendix/faq.adoc[FAQ]
|
||||||
|
* xref:reactive/index.adoc[Reactive Applications]
|
||||||
** xref:reactive/webflux.adoc[WebFlux Security]
|
** xref:reactive/webflux.adoc[WebFlux Security]
|
||||||
** xref:reactive/exploits/index.adoc[Protection Against Exploits]
|
** xref:reactive/exploits/index.adoc[Protection Against Exploits]
|
||||||
|
*** xref:reactive/exploits/csrf.adoc[CSRF]
|
||||||
|
*** xref:reactive/exploits/headers.adoc[Headers]
|
||||||
|
*** xref:reactive/exploits/http.adoc[HTTP Requests]
|
||||||
** xref:reactive/oauth2/index.adoc[OAuth2]
|
** xref:reactive/oauth2/index.adoc[OAuth2]
|
||||||
|
*** xref:reactive/oauth2/login.adoc[OAuth 2.0 Login]
|
||||||
|
*** xref:reactive/oauth2/access-token.adoc[OAuth2 Client]
|
||||||
|
*** xref:reactive/oauth2/resource-server.adoc[OAuth 2.0 Resource Server]
|
||||||
** xref:reactive/registered-oauth2-authorized-client.adoc[@RegisteredOAuth2AuthorizedClient]
|
** xref:reactive/registered-oauth2-authorized-client.adoc[@RegisteredOAuth2AuthorizedClient]
|
||||||
** xref:reactive/x509.adoc[X.509 Authentication]
|
** xref:reactive/x509.adoc[X.509 Authentication]
|
||||||
** xref:reactive/logout.adoc[Logout]
|
** xref:reactive/logout.adoc[Logout]
|
||||||
|
|
|
@ -5,8 +5,9 @@ Spring Security provides comprehensive support for https://en.wikipedia.org/wiki
|
||||||
Authentication is how we verify the identity of who is trying to access a particular resource.
|
Authentication is how we verify the identity of who is trying to access a particular resource.
|
||||||
A common way to authenticate users is by requiring the user to enter a username and password.
|
A common way to authenticate users is by requiring the user to enter a username and password.
|
||||||
Once authentication is performed we know the identity and can perform authorization.
|
Once authentication is performed we know the identity and can perform authorization.
|
||||||
// FIXME: Link authorization to authorization
|
|
||||||
|
|
||||||
include::supported.adoc[leveloffset=+1]
|
== Authentication Support
|
||||||
|
|
||||||
include::password-storage.adoc[leveloffset=+1]
|
Spring Security provides built in support for authenticating users.
|
||||||
|
This section is dedicated to generic authentication support that applies in both Servlet and WebFlux environments.
|
||||||
|
Refer to the sections on authentication for <<servlet-authentication,Servlet>> and WebFlux for details on what is supported for each stack.
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[[authentication-support]]
|
|
||||||
= Authentication Support
|
|
||||||
|
|
||||||
Spring Security provides built in support for authenticating users.
|
|
||||||
Refer to the sections on authentication for <<servlet-authentication,Servlet>> and WebFlux for details on what is supported for each stack.
|
|
|
@ -5,8 +5,6 @@ Spring Security provides protection against common exploits.
|
||||||
Whenever possible, the protection is enabled by default.
|
Whenever possible, the protection is enabled by default.
|
||||||
Below you will find high level description of the various exploits that Spring Security protects against.
|
Below you will find high level description of the various exploits that Spring Security protects against.
|
||||||
|
|
||||||
include::csrf.adoc[leveloffset=+1]
|
* xref:overview/features/exploits/csrf.adoc[CSRF]
|
||||||
|
* xref:overview/features/exploits/headers.adoc[HTTP Headers]
|
||||||
include::headers.adoc[leveloffset=+1]
|
* xref:overview/features/exploits/http.adoc[HTTP Requests]
|
||||||
|
|
||||||
include::http.adoc[leveloffset=+1]
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
= Protection Against Exploits
|
= Protection Against Exploits
|
||||||
|
|
||||||
include::csrf.adoc[leveloffset=+1]
|
Spring Security provides protection against numerous exploits.
|
||||||
|
This section discusses WebFlux specific support for:
|
||||||
|
|
||||||
include::headers.adoc[leveloffset=+1]
|
* xref:reactive/exploits/csrf.adoc[CSRF]
|
||||||
|
* xref:reactive/exploits/headers.adoc[Headers]
|
||||||
include::http.adoc[leveloffset=+1]
|
* xref:reactive/exploits/http.adoc[HTTP Requests]
|
||||||
|
|
|
@ -1,23 +1,4 @@
|
||||||
= Reactive Applications
|
= Reactive Applications
|
||||||
|
|
||||||
include::webflux.adoc[leveloffset=+1]
|
Reactive applications work very differently than <<servlet-applications>>.
|
||||||
|
This section discusses how Spring Security works with reactive applications which are typically written using Spring's WebFlux.
|
||||||
include::exploits/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::oauth2/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::registered-oauth2-authorized-client.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::x509.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::logout.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::webclient.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::method.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::cors.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::test.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::rsocket.adoc[leveloffset=+1]
|
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
Spring Security provides OAuth2 and WebFlux integration for reactive applications.
|
Spring Security provides OAuth2 and WebFlux integration for reactive applications.
|
||||||
|
|
||||||
include::login.adoc[leveloffset=+1]
|
* xref:reactive/oauth2/login.adoc[OAuth 2.0 Login]
|
||||||
|
* xref:reactive/oauth2/access-token.adoc[OAuth2 Client]
|
||||||
include::access-token.adoc[leveloffset=+1]
|
* xref:reactive/oauth2/resource-server.adoc[OAuth 2.0 Resource Server]
|
||||||
|
|
||||||
include::resource-server.adoc[leveloffset=+1]
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
= Appendix
|
= Appendix
|
||||||
|
|
||||||
include::database-schema.adoc[leveloffset=+1]
|
This is an appendix for Servlet based Spring Security.
|
||||||
|
It has the following sections:
|
||||||
|
|
||||||
include::namespace.adoc[]
|
* xref:servlet/appendix/database-schema.adoc[Database Schemas]
|
||||||
|
* xref:servlet/appendix/namespace.adoc[XML Namespace]
|
||||||
include::faq.adoc[]
|
* xref:servlet/appendix/faq.adoc[FAQ]
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
[[servlet-delegatingfilterproxy]]
|
|
||||||
= DelegatingFilterProxy
|
|
||||||
|
|
||||||
Spring provides a `Filter` implementation named {spring-framework-api-url}org/springframework/web/filter/DelegatingFilterProxy.html[`DelegatingFilterProxy`] that allows bridging between the Servlet container's lifecycle and Spring's `ApplicationContext`.
|
|
||||||
The Servlet container allows registering ``Filter``s using its own standards, but it is not aware of Spring defined Beans.
|
|
||||||
`DelegatingFilterProxy` can be registered via standard Servlet container mechanisms, but delegate all the work to a Spring Bean that implements `Filter`.
|
|
||||||
|
|
||||||
Here is a picture of how `DelegatingFilterProxy` fits into the <<servlet-filters-review,``Filter``s and the `FilterChain`>>.
|
|
||||||
|
|
||||||
.DelegatingFilterProxy
|
|
||||||
[[servlet-delegatingfilterproxy-figure]]
|
|
||||||
image::{figures}/delegatingfilterproxy.png[]
|
|
||||||
|
|
||||||
`DelegatingFilterProxy` looks up __Bean Filter~0~__ from the `ApplicationContext` and then invokes __Bean Filter~0~__.
|
|
||||||
The pseudo code of `DelegatingFilterProxy` can be seen below.
|
|
||||||
|
|
||||||
.`DelegatingFilterProxy` Pseudo Code
|
|
||||||
====
|
|
||||||
.Java
|
|
||||||
[source,java,role="primary",subs="+quotes,+macros"]
|
|
||||||
----
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
|
|
||||||
// Lazily get Filter that was registered as a Spring Bean
|
|
||||||
// For the example in <<servlet-delegatingfilterproxy-figure>> `delegate` is an instance of __Bean Filter~0~__
|
|
||||||
Filter delegate = getFilterBean(someBeanName);
|
|
||||||
// delegate work to the Spring Bean
|
|
||||||
delegate.doFilter(request, response);
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
.Kotlin
|
|
||||||
[source,kotlin,role="secondary",subs="+quotes,+macros"]
|
|
||||||
----
|
|
||||||
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
|
|
||||||
// Lazily get Filter that was registered as a Spring Bean
|
|
||||||
// For the example in <<servlet-delegatingfilterproxy-figure>> `delegate` is an instance of __Bean Filter~0~__
|
|
||||||
val delegate: Filter = getFilterBean(someBeanName)
|
|
||||||
// delegate work to the Spring Bean
|
|
||||||
delegate.doFilter(request, response)
|
|
||||||
}
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
Another benefit of `DelegatingFilterProxy` is that it allows delaying looking `Filter` bean instances up.
|
|
||||||
This is important because the container needs to register the `Filter` instances before the container can startup.
|
|
||||||
However, Spring typically uses a `ContextLoaderListener` to load the Spring Beans which will not be done until after the `Filter` instances need to be registered.
|
|
|
@ -1,50 +0,0 @@
|
||||||
[[servlet-exceptiontranslationfilter]]
|
|
||||||
= Handling Security Exceptions
|
|
||||||
:figures: images/servlet/architecture
|
|
||||||
:icondir: images/icons
|
|
||||||
|
|
||||||
|
|
||||||
The {security-api-url}org/springframework/security/web/access/ExceptionTranslationFilter.html[`ExceptionTranslationFilter`] allows translation of {security-api-url}org/springframework/security/access/AccessDeniedException.html[`AccessDeniedException`] and {security-api-url}/org/springframework/security/core/AuthenticationException.html[`AuthenticationException`] into HTTP responses.
|
|
||||||
|
|
||||||
`ExceptionTranslationFilter` is inserted into the <<servlet-filterchainproxy>> as one of the <<servlet-security-filters>>.
|
|
||||||
|
|
||||||
image::{figures}/exceptiontranslationfilter.png[]
|
|
||||||
|
|
||||||
|
|
||||||
* image:{icondir}/number_1.png[] First, the `ExceptionTranslationFilter` invokes `FilterChain.doFilter(request, response)` to invoke the rest of the application.
|
|
||||||
* image:{icondir}/number_2.png[] If the user is not authenticated or it is an `AuthenticationException`, then __Start Authentication__.
|
|
||||||
** The <<servlet-authentication-securitycontextholder>> is cleared out.
|
|
||||||
** The `HttpServletRequest` is saved in the {security-api-url}org/springframework/security/web/savedrequest/RequestCache.html[`RequestCache`].
|
|
||||||
When the user successfully authenticates, the `RequestCache` is used to replay the original request.
|
|
||||||
// FIXME: add link to authentication success
|
|
||||||
** The `AuthenticationEntryPoint` is used to request credentials from the client.
|
|
||||||
For example, it might redirect to a log in page or send a `WWW-Authenticate` header.
|
|
||||||
// FIXME: link to AuthenticationEntryPoint
|
|
||||||
* image:{icondir}/number_3.png[] Otherwise if it is an `AccessDeniedException`, then __Access Denied__.
|
|
||||||
The `AccessDeniedHandler` is invoked to handle access denied.
|
|
||||||
// FIXME: link to AccessDeniedHandler
|
|
||||||
|
|
||||||
[NOTE]
|
|
||||||
====
|
|
||||||
If the application does not throw an `AccessDeniedException` or an `AuthenticationException`, then `ExceptionTranslationFilter` does not do anything.
|
|
||||||
====
|
|
||||||
|
|
||||||
The pseudocode for `ExceptionTranslationFilter` looks something like this:
|
|
||||||
|
|
||||||
.ExceptionTranslationFilter pseudocode
|
|
||||||
[source,java]
|
|
||||||
----
|
|
||||||
try {
|
|
||||||
filterChain.doFilter(request, response); // <1>
|
|
||||||
} catch (AccessDeniedException | AuthenticationException ex) {
|
|
||||||
if (!authenticated || ex instanceof AuthenticationException) {
|
|
||||||
startAuthentication(); // <2>
|
|
||||||
} else {
|
|
||||||
accessDenied(); // <3>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
<1> You will recall from <<servlet-filters-review>> that invoking `FilterChain.doFilter(request, response)` is the equivalent of invoking the rest of the application.
|
|
||||||
This means that if another part of the application, (i.e. <<servlet-authorization-filtersecurityinterceptor,`FilterSecurityInterceptor`>> or method security) throws an `AuthenticationException` or `AccessDeniedException` it will be caught and handled here.
|
|
||||||
<2> If the user is not authenticated or it is an `AuthenticationException`, then __Start Authentication__.
|
|
||||||
<3> Otherwise, __Access Denied__
|
|
|
@ -1,10 +0,0 @@
|
||||||
[[servlet-filterchainproxy]]
|
|
||||||
= FilterChainProxy
|
|
||||||
|
|
||||||
Spring Security's Servlet support is contained within `FilterChainProxy`.
|
|
||||||
`FilterChainProxy` is a special `Filter` provided by Spring Security that allows delegating to many `Filter` instances through <<servlet-securityfilterchain,`SecurityFilterChain`>>.
|
|
||||||
Since `FilterChainProxy` is a Bean, it is typically wrapped in a <<servlet-delegatingfilterproxy>>.
|
|
||||||
|
|
||||||
.FilterChainProxy
|
|
||||||
[[servlet-filterchainproxy-figure]]
|
|
||||||
image::{figures}/filterchainproxy.png[]
|
|
|
@ -1,45 +0,0 @@
|
||||||
[[servlet-filters-review]]
|
|
||||||
= A Review of ``Filter``s
|
|
||||||
|
|
||||||
Spring Security's Servlet support is based on Servlet ``Filter``s, so it is helpful to look at the role of ``Filter``s generally first.
|
|
||||||
The picture below shows the typical layering of the handlers for a single HTTP request.
|
|
||||||
|
|
||||||
.FilterChain
|
|
||||||
[[servlet-filterchain-figure]]
|
|
||||||
image::{figures}/filterchain.png[]
|
|
||||||
|
|
||||||
The client sends a request to the application, and the container creates a `FilterChain` which contains the ``Filter``s and `Servlet` that should process the `HttpServletRequest` based on the path of the request URI.
|
|
||||||
In a Spring MVC application the `Servlet` is an instance of {spring-framework-reference-url}web.html#mvc-servlet[`DispatcherServlet`].
|
|
||||||
At most one `Servlet` can handle a single `HttpServletRequest` and `HttpServletResponse`.
|
|
||||||
However, more than one `Filter` can be used to:
|
|
||||||
|
|
||||||
* Prevent downstream ``Filter``s or the `Servlet` from being invoked.
|
|
||||||
In this instance the `Filter` will typically write the `HttpServletResponse`.
|
|
||||||
* Modify the `HttpServletRequest` or `HttpServletResponse` used by the downstream ``Filter``s and `Servlet`
|
|
||||||
|
|
||||||
The power of the `Filter` comes from the `FilterChain` that is passed into it.
|
|
||||||
|
|
||||||
.`FilterChain` Usage Example
|
|
||||||
====
|
|
||||||
.Java
|
|
||||||
[source,java,role="primary"]
|
|
||||||
----
|
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
|
|
||||||
// do something before the rest of the application
|
|
||||||
chain.doFilter(request, response); // invoke the rest of the application
|
|
||||||
// do something after the rest of the application
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
.Kotlin
|
|
||||||
[source,kotlin,role="secondary"]
|
|
||||||
----
|
|
||||||
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
|
|
||||||
// do something before the rest of the application
|
|
||||||
chain.doFilter(request, response) // invoke the rest of the application
|
|
||||||
// do something after the rest of the application
|
|
||||||
}
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
Since a `Filter` only impacts downstream ``Filter``s and the `Servlet`, the order each `Filter` is invoked is extremely important.
|
|
|
@ -1,19 +1,249 @@
|
||||||
[[servlet-architecture]]
|
[[servlet-architecture]]
|
||||||
= Servlet Security: The Big Picture
|
= Servlet Security: The Big Picture
|
||||||
:figures: images/servlet/architecture
|
:figures: images/servlet/architecture
|
||||||
|
:icondir: images/icons
|
||||||
|
|
||||||
This section discusses Spring Security's high level architecture within Servlet based applications.
|
This section discusses Spring Security's high level architecture within Servlet based applications.
|
||||||
We build on this high level understanding within <<servlet-authentication>>, <<servlet-authorization>>, <<servlet-exploits>> sections of the reference.
|
We build on this high level understanding within <<servlet-authentication>>, <<servlet-authorization>>, <<servlet-exploits>> sections of the reference.
|
||||||
// FIXME: Add links to other sections of architecture
|
// FIXME: Add links to other sections of architecture
|
||||||
|
|
||||||
include::filters.adoc[leveloffset=+1]
|
[[servlet-filters-review]]
|
||||||
|
== A Review of ``Filter``s
|
||||||
|
|
||||||
include::delegating-filter-proxy.adoc[leveloffset=+1]
|
Spring Security's Servlet support is based on Servlet ``Filter``s, so it is helpful to look at the role of ``Filter``s generally first.
|
||||||
|
The picture below shows the typical layering of the handlers for a single HTTP request.
|
||||||
|
|
||||||
include::filter-chain-proxy.adoc[leveloffset=+1]
|
.FilterChain
|
||||||
|
[[servlet-filterchain-figure]]
|
||||||
|
image::{figures}/filterchain.png[]
|
||||||
|
|
||||||
include::security-filter-chain.adoc[leveloffset=+1]
|
The client sends a request to the application, and the container creates a `FilterChain` which contains the ``Filter``s and `Servlet` that should process the `HttpServletRequest` based on the path of the request URI.
|
||||||
|
In a Spring MVC application the `Servlet` is an instance of {spring-framework-reference-url}web.html#mvc-servlet[`DispatcherServlet`].
|
||||||
|
At most one `Servlet` can handle a single `HttpServletRequest` and `HttpServletResponse`.
|
||||||
|
However, more than one `Filter` can be used to:
|
||||||
|
|
||||||
include::security-filters.adoc[leveloffset=+1]
|
* Prevent downstream ``Filter``s or the `Servlet` from being invoked.
|
||||||
|
In this instance the `Filter` will typically write the `HttpServletResponse`.
|
||||||
|
* Modify the `HttpServletRequest` or `HttpServletResponse` used by the downstream ``Filter``s and `Servlet`
|
||||||
|
|
||||||
include::exception-translation-filter.adoc[leveloffset=+1]
|
The power of the `Filter` comes from the `FilterChain` that is passed into it.
|
||||||
|
|
||||||
|
.`FilterChain` Usage Example
|
||||||
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
|
----
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
|
||||||
|
// do something before the rest of the application
|
||||||
|
chain.doFilter(request, response); // invoke the rest of the application
|
||||||
|
// do something after the rest of the application
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
|
||||||
|
// do something before the rest of the application
|
||||||
|
chain.doFilter(request, response) // invoke the rest of the application
|
||||||
|
// do something after the rest of the application
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
Since a `Filter` only impacts downstream ``Filter``s and the `Servlet`, the order each `Filter` is invoked is extremely important.
|
||||||
|
|
||||||
|
|
||||||
|
[[servlet-delegatingfilterproxy]]
|
||||||
|
== DelegatingFilterProxy
|
||||||
|
|
||||||
|
Spring provides a `Filter` implementation named {spring-framework-api-url}org/springframework/web/filter/DelegatingFilterProxy.html[`DelegatingFilterProxy`] that allows bridging between the Servlet container's lifecycle and Spring's `ApplicationContext`.
|
||||||
|
The Servlet container allows registering ``Filter``s using its own standards, but it is not aware of Spring defined Beans.
|
||||||
|
`DelegatingFilterProxy` can be registered via standard Servlet container mechanisms, but delegate all the work to a Spring Bean that implements `Filter`.
|
||||||
|
|
||||||
|
Here is a picture of how `DelegatingFilterProxy` fits into the <<servlet-filters-review,``Filter``s and the `FilterChain`>>.
|
||||||
|
|
||||||
|
.DelegatingFilterProxy
|
||||||
|
[[servlet-delegatingfilterproxy-figure]]
|
||||||
|
image::{figures}/delegatingfilterproxy.png[]
|
||||||
|
|
||||||
|
`DelegatingFilterProxy` looks up __Bean Filter~0~__ from the `ApplicationContext` and then invokes __Bean Filter~0~__.
|
||||||
|
The pseudo code of `DelegatingFilterProxy` can be seen below.
|
||||||
|
|
||||||
|
.`DelegatingFilterProxy` Pseudo Code
|
||||||
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary",subs="+quotes,+macros"]
|
||||||
|
----
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
|
||||||
|
// Lazily get Filter that was registered as a Spring Bean
|
||||||
|
// For the example in <<servlet-delegatingfilterproxy-figure>> `delegate` is an instance of __Bean Filter~0~__
|
||||||
|
Filter delegate = getFilterBean(someBeanName);
|
||||||
|
// delegate work to the Spring Bean
|
||||||
|
delegate.doFilter(request, response);
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary",subs="+quotes,+macros"]
|
||||||
|
----
|
||||||
|
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
|
||||||
|
// Lazily get Filter that was registered as a Spring Bean
|
||||||
|
// For the example in <<servlet-delegatingfilterproxy-figure>> `delegate` is an instance of __Bean Filter~0~__
|
||||||
|
val delegate: Filter = getFilterBean(someBeanName)
|
||||||
|
// delegate work to the Spring Bean
|
||||||
|
delegate.doFilter(request, response)
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
Another benefit of `DelegatingFilterProxy` is that it allows delaying looking `Filter` bean instances up.
|
||||||
|
This is important because the container needs to register the `Filter` instances before the container can startup.
|
||||||
|
However, Spring typically uses a `ContextLoaderListener` to load the Spring Beans which will not be done until after the `Filter` instances need to be registered.
|
||||||
|
|
||||||
|
[[servlet-filterchainproxy]]
|
||||||
|
== FilterChainProxy
|
||||||
|
|
||||||
|
Spring Security's Servlet support is contained within `FilterChainProxy`.
|
||||||
|
`FilterChainProxy` is a special `Filter` provided by Spring Security that allows delegating to many `Filter` instances through <<servlet-securityfilterchain,`SecurityFilterChain`>>.
|
||||||
|
Since `FilterChainProxy` is a Bean, it is typically wrapped in a <<servlet-delegatingfilterproxy>>.
|
||||||
|
|
||||||
|
.FilterChainProxy
|
||||||
|
[[servlet-filterchainproxy-figure]]
|
||||||
|
image::{figures}/filterchainproxy.png[]
|
||||||
|
|
||||||
|
[[servlet-securityfilterchain]]
|
||||||
|
== SecurityFilterChain
|
||||||
|
|
||||||
|
{security-api-url}org/springframework/security/web/SecurityFilterChain.html[`SecurityFilterChain`] is used by <<servlet-filterchainproxy>> to determine which Spring Security ``Filter``s should be invoked for this request.
|
||||||
|
|
||||||
|
.SecurityFilterChain
|
||||||
|
[[servlet-securityfilterchain-figure]]
|
||||||
|
image::{figures}/securityfilterchain.png[]
|
||||||
|
|
||||||
|
The <<servlet-security-filters,Security Filters>> in `SecurityFilterChain` are typically Beans, but they are registered with `FilterChainProxy` instead of <<servlet-delegatingfilterproxy>>.
|
||||||
|
`FilterChainProxy` provides a number of advantages to registering directly with the Servlet container or <<servlet-delegatingfilterproxy>>.
|
||||||
|
First, it provides a starting point for all of Spring Security's Servlet support.
|
||||||
|
For that reason, if you are attempting to troubleshoot Spring Security's Servlet support, adding a debug point in `FilterChainProxy` is a great place to start.
|
||||||
|
|
||||||
|
Second, since `FilterChainProxy` is central to Spring Security usage it can perform tasks that are not viewed as optional.
|
||||||
|
// FIXME: Add a link to SecurityContext
|
||||||
|
For example, it clears out the `SecurityContext` to avoid memory leaks.
|
||||||
|
It also applies Spring Security's <<servlet-httpfirewall,`HttpFirewall`>> to protect applications against certain types of attacks.
|
||||||
|
|
||||||
|
In addition, it provides more flexibility in determining when a `SecurityFilterChain` should be invoked.
|
||||||
|
In a Servlet container, ``Filter``s are invoked based upon the URL alone.
|
||||||
|
// FIXME: Link to RequestMatcher
|
||||||
|
However, `FilterChainProxy` can determine invocation based upon anything in the `HttpServletRequest` by leveraging the `RequestMatcher` interface.
|
||||||
|
|
||||||
|
In fact, `FilterChainProxy` can be used to determine which `SecurityFilterChain` should be used.
|
||||||
|
This allows providing a totally separate configuration for different _slices_ of your application.
|
||||||
|
|
||||||
|
.Multiple SecurityFilterChain
|
||||||
|
[[servlet-multi-securityfilterchain-figure]]
|
||||||
|
image::{figures}/multi-securityfilterchain.png[]
|
||||||
|
|
||||||
|
In the <<servlet-multi-securityfilterchain-figure>> Figure `FilterChainProxy` decides which `SecurityFilterChain` should be used.
|
||||||
|
Only the first `SecurityFilterChain` that matches will be invoked.
|
||||||
|
If a URL of `/api/messages/` is requested, it will first match on ``SecurityFilterChain~0~``'s pattern of `+/api/**+`, so only `SecurityFilterChain~0~` will be invoked even though it also matches on ``SecurityFilterChain~n~``.
|
||||||
|
If a URL of `/messages/` is requested, it will not match on ``SecurityFilterChain~0~``'s pattern of `+/api/**+`, so `FilterChainProxy` will continue trying each `SecurityFilterChain`.
|
||||||
|
Assuming that no other, `SecurityFilterChain` instances match `SecurityFilterChain~n~` will be invoked.
|
||||||
|
// FIXME add link to pattern matching
|
||||||
|
|
||||||
|
Notice that `SecurityFilterChain~0~` has only three security ``Filter``s instances configured.
|
||||||
|
However, `SecurityFilterChain~n~` has four security ``Filter``s configured.
|
||||||
|
It is important to note that each `SecurityFilterChain` can be unique and configured in isolation.
|
||||||
|
In fact, a `SecurityFilterChain` might have zero security ``Filter``s if the application wants Spring Security to ignore certain requests.
|
||||||
|
// FIXME: add link to configuring multiple `SecurityFilterChain` instances
|
||||||
|
|
||||||
|
[[servlet-security-filters]]
|
||||||
|
== Security Filters
|
||||||
|
|
||||||
|
The Security Filters are inserted into the <<servlet-filterchainproxy>> with the <<servlet-securityfilterchain>> API.
|
||||||
|
The <<servlet-filters-review,order of ``Filter``>>s matters.
|
||||||
|
It is typically not necessary to know the ordering of Spring Security's ``Filter``s.
|
||||||
|
However, there are times that it is beneficial to know the ordering
|
||||||
|
|
||||||
|
Below is a comprehensive list of Spring Security Filter ordering:
|
||||||
|
|
||||||
|
* ChannelProcessingFilter
|
||||||
|
* WebAsyncManagerIntegrationFilter
|
||||||
|
* SecurityContextPersistenceFilter
|
||||||
|
* HeaderWriterFilter
|
||||||
|
* CorsFilter
|
||||||
|
* CsrfFilter
|
||||||
|
* LogoutFilter
|
||||||
|
* OAuth2AuthorizationRequestRedirectFilter
|
||||||
|
* Saml2WebSsoAuthenticationRequestFilter
|
||||||
|
* X509AuthenticationFilter
|
||||||
|
* AbstractPreAuthenticatedProcessingFilter
|
||||||
|
* CasAuthenticationFilter
|
||||||
|
* OAuth2LoginAuthenticationFilter
|
||||||
|
* Saml2WebSsoAuthenticationFilter
|
||||||
|
* <<servlet-authentication-usernamepasswordauthenticationfilter,`UsernamePasswordAuthenticationFilter`>>
|
||||||
|
* OpenIDAuthenticationFilter
|
||||||
|
* DefaultLoginPageGeneratingFilter
|
||||||
|
* DefaultLogoutPageGeneratingFilter
|
||||||
|
* ConcurrentSessionFilter
|
||||||
|
* <<servlet-authentication-digest,`DigestAuthenticationFilter`>>
|
||||||
|
* BearerTokenAuthenticationFilter
|
||||||
|
* <<servlet-authentication-basic,`BasicAuthenticationFilter`>>
|
||||||
|
* RequestCacheAwareFilter
|
||||||
|
* SecurityContextHolderAwareRequestFilter
|
||||||
|
* JaasApiIntegrationFilter
|
||||||
|
* RememberMeAuthenticationFilter
|
||||||
|
* AnonymousAuthenticationFilter
|
||||||
|
* OAuth2AuthorizationCodeGrantFilter
|
||||||
|
* SessionManagementFilter
|
||||||
|
* <<servlet-exceptiontranslationfilter,`ExceptionTranslationFilter`>>
|
||||||
|
* <<servlet-authorization-filtersecurityinterceptor,`FilterSecurityInterceptor`>>
|
||||||
|
* SwitchUserFilter
|
||||||
|
|
||||||
|
[[servlet-exceptiontranslationfilter]]
|
||||||
|
== Handling Security Exceptions
|
||||||
|
|
||||||
|
|
||||||
|
The {security-api-url}org/springframework/security/web/access/ExceptionTranslationFilter.html[`ExceptionTranslationFilter`] allows translation of {security-api-url}org/springframework/security/access/AccessDeniedException.html[`AccessDeniedException`] and {security-api-url}/org/springframework/security/core/AuthenticationException.html[`AuthenticationException`] into HTTP responses.
|
||||||
|
|
||||||
|
`ExceptionTranslationFilter` is inserted into the <<servlet-filterchainproxy>> as one of the <<servlet-security-filters>>.
|
||||||
|
|
||||||
|
image::{figures}/exceptiontranslationfilter.png[]
|
||||||
|
|
||||||
|
|
||||||
|
* image:{icondir}/number_1.png[] First, the `ExceptionTranslationFilter` invokes `FilterChain.doFilter(request, response)` to invoke the rest of the application.
|
||||||
|
* image:{icondir}/number_2.png[] If the user is not authenticated or it is an `AuthenticationException`, then __Start Authentication__.
|
||||||
|
** The <<servlet-authentication-securitycontextholder>> is cleared out.
|
||||||
|
** The `HttpServletRequest` is saved in the {security-api-url}org/springframework/security/web/savedrequest/RequestCache.html[`RequestCache`].
|
||||||
|
When the user successfully authenticates, the `RequestCache` is used to replay the original request.
|
||||||
|
// FIXME: add link to authentication success
|
||||||
|
** The `AuthenticationEntryPoint` is used to request credentials from the client.
|
||||||
|
For example, it might redirect to a log in page or send a `WWW-Authenticate` header.
|
||||||
|
// FIXME: link to AuthenticationEntryPoint
|
||||||
|
* image:{icondir}/number_3.png[] Otherwise if it is an `AccessDeniedException`, then __Access Denied__.
|
||||||
|
The `AccessDeniedHandler` is invoked to handle access denied.
|
||||||
|
// FIXME: link to AccessDeniedHandler
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
If the application does not throw an `AccessDeniedException` or an `AuthenticationException`, then `ExceptionTranslationFilter` does not do anything.
|
||||||
|
====
|
||||||
|
|
||||||
|
The pseudocode for `ExceptionTranslationFilter` looks something like this:
|
||||||
|
|
||||||
|
.ExceptionTranslationFilter pseudocode
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
try {
|
||||||
|
filterChain.doFilter(request, response); // <1>
|
||||||
|
} catch (AccessDeniedException | AuthenticationException ex) {
|
||||||
|
if (!authenticated || ex instanceof AuthenticationException) {
|
||||||
|
startAuthentication(); // <2>
|
||||||
|
} else {
|
||||||
|
accessDenied(); // <3>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
<1> You will recall from <<servlet-filters-review>> that invoking `FilterChain.doFilter(request, response)` is the equivalent of invoking the rest of the application.
|
||||||
|
This means that if another part of the application, (i.e. <<servlet-authorization-filtersecurityinterceptor,`FilterSecurityInterceptor`>> or method security) throws an `AuthenticationException` or `AccessDeniedException` it will be caught and handled here.
|
||||||
|
<2> If the user is not authenticated or it is an `AuthenticationException`, then __Start Authentication__.
|
||||||
|
<3> Otherwise, __Access Denied__
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
[[servlet-securityfilterchain]]
|
|
||||||
= SecurityFilterChain
|
|
||||||
|
|
||||||
{security-api-url}org/springframework/security/web/SecurityFilterChain.html[`SecurityFilterChain`] is used by <<servlet-filterchainproxy>> to determine which Spring Security ``Filter``s should be invoked for this request.
|
|
||||||
|
|
||||||
.SecurityFilterChain
|
|
||||||
[[servlet-securityfilterchain-figure]]
|
|
||||||
image::{figures}/securityfilterchain.png[]
|
|
||||||
|
|
||||||
The <<servlet-security-filters,Security Filters>> in `SecurityFilterChain` are typically Beans, but they are registered with `FilterChainProxy` instead of <<servlet-delegatingfilterproxy>>.
|
|
||||||
`FilterChainProxy` provides a number of advantages to registering directly with the Servlet container or <<servlet-delegatingfilterproxy>>.
|
|
||||||
First, it provides a starting point for all of Spring Security's Servlet support.
|
|
||||||
For that reason, if you are attempting to troubleshoot Spring Security's Servlet support, adding a debug point in `FilterChainProxy` is a great place to start.
|
|
||||||
|
|
||||||
Second, since `FilterChainProxy` is central to Spring Security usage it can perform tasks that are not viewed as optional.
|
|
||||||
// FIXME: Add a link to SecurityContext
|
|
||||||
For example, it clears out the `SecurityContext` to avoid memory leaks.
|
|
||||||
It also applies Spring Security's <<servlet-httpfirewall,`HttpFirewall`>> to protect applications against certain types of attacks.
|
|
||||||
|
|
||||||
In addition, it provides more flexibility in determining when a `SecurityFilterChain` should be invoked.
|
|
||||||
In a Servlet container, ``Filter``s are invoked based upon the URL alone.
|
|
||||||
// FIXME: Link to RequestMatcher
|
|
||||||
However, `FilterChainProxy` can determine invocation based upon anything in the `HttpServletRequest` by leveraging the `RequestMatcher` interface.
|
|
||||||
|
|
||||||
In fact, `FilterChainProxy` can be used to determine which `SecurityFilterChain` should be used.
|
|
||||||
This allows providing a totally separate configuration for different _slices_ of your application.
|
|
||||||
|
|
||||||
.Multiple SecurityFilterChain
|
|
||||||
[[servlet-multi-securityfilterchain-figure]]
|
|
||||||
image::{figures}/multi-securityfilterchain.png[]
|
|
||||||
|
|
||||||
In the <<servlet-multi-securityfilterchain-figure>> Figure `FilterChainProxy` decides which `SecurityFilterChain` should be used.
|
|
||||||
Only the first `SecurityFilterChain` that matches will be invoked.
|
|
||||||
If a URL of `/api/messages/` is requested, it will first match on ``SecurityFilterChain~0~``'s pattern of `+/api/**+`, so only `SecurityFilterChain~0~` will be invoked even though it also matches on ``SecurityFilterChain~n~``.
|
|
||||||
If a URL of `/messages/` is requested, it will not match on ``SecurityFilterChain~0~``'s pattern of `+/api/**+`, so `FilterChainProxy` will continue trying each `SecurityFilterChain`.
|
|
||||||
Assuming that no other, `SecurityFilterChain` instances match `SecurityFilterChain~n~` will be invoked.
|
|
||||||
// FIXME add link to pattern matching
|
|
||||||
|
|
||||||
Notice that `SecurityFilterChain~0~` has only three security ``Filter``s instances configured.
|
|
||||||
However, `SecurityFilterChain~n~` has four security ``Filter``s configured.
|
|
||||||
It is important to note that each `SecurityFilterChain` can be unique and configured in isolation.
|
|
||||||
In fact, a `SecurityFilterChain` might have zero security ``Filter``s if the application wants Spring Security to ignore certain requests.
|
|
||||||
// FIXME: add link to configuring multiple `SecurityFilterChain` instances
|
|
|
@ -1,42 +0,0 @@
|
||||||
[[servlet-security-filters]]
|
|
||||||
= Security Filters
|
|
||||||
|
|
||||||
The Security Filters are inserted into the <<servlet-filterchainproxy>> with the <<servlet-securityfilterchain>> API.
|
|
||||||
The <<servlet-filters-review,order of ``Filter``>>s matters.
|
|
||||||
It is typically not necessary to know the ordering of Spring Security's ``Filter``s.
|
|
||||||
However, there are times that it is beneficial to know the ordering
|
|
||||||
|
|
||||||
Below is a comprehensive list of Spring Security Filter ordering:
|
|
||||||
|
|
||||||
* ChannelProcessingFilter
|
|
||||||
* WebAsyncManagerIntegrationFilter
|
|
||||||
* SecurityContextPersistenceFilter
|
|
||||||
* HeaderWriterFilter
|
|
||||||
* CorsFilter
|
|
||||||
* CsrfFilter
|
|
||||||
* LogoutFilter
|
|
||||||
* OAuth2AuthorizationRequestRedirectFilter
|
|
||||||
* Saml2WebSsoAuthenticationRequestFilter
|
|
||||||
* X509AuthenticationFilter
|
|
||||||
* AbstractPreAuthenticatedProcessingFilter
|
|
||||||
* CasAuthenticationFilter
|
|
||||||
* OAuth2LoginAuthenticationFilter
|
|
||||||
* Saml2WebSsoAuthenticationFilter
|
|
||||||
* <<servlet-authentication-usernamepasswordauthenticationfilter,`UsernamePasswordAuthenticationFilter`>>
|
|
||||||
* OpenIDAuthenticationFilter
|
|
||||||
* DefaultLoginPageGeneratingFilter
|
|
||||||
* DefaultLogoutPageGeneratingFilter
|
|
||||||
* ConcurrentSessionFilter
|
|
||||||
* <<servlet-authentication-digest,`DigestAuthenticationFilter`>>
|
|
||||||
* BearerTokenAuthenticationFilter
|
|
||||||
* <<servlet-authentication-basic,`BasicAuthenticationFilter`>>
|
|
||||||
* RequestCacheAwareFilter
|
|
||||||
* SecurityContextHolderAwareRequestFilter
|
|
||||||
* JaasApiIntegrationFilter
|
|
||||||
* RememberMeAuthenticationFilter
|
|
||||||
* AnonymousAuthenticationFilter
|
|
||||||
* OAuth2AuthorizationCodeGrantFilter
|
|
||||||
* SessionManagementFilter
|
|
||||||
* <<servlet-exceptiontranslationfilter,`ExceptionTranslationFilter`>>
|
|
||||||
* <<servlet-authorization-filtersecurityinterceptor,`FilterSecurityInterceptor`>>
|
|
||||||
* SwitchUserFilter
|
|
|
@ -1,41 +0,0 @@
|
||||||
[[servlet-authentication-abstractprocessingfilter]]
|
|
||||||
= AbstractAuthenticationProcessingFilter
|
|
||||||
:figures: images/servlet/authentication/architecture
|
|
||||||
:icondir: images/icons
|
|
||||||
|
|
||||||
{security-api-url}org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html[`AbstractAuthenticationProcessingFilter`] is used as a base `Filter` for authenticating a user's credentials.
|
|
||||||
Before the credentials can be authenticated, Spring Security typically requests the credentials using <<servlet-authentication-authenticationentrypoint,`AuthenticationEntryPoint`>>.
|
|
||||||
|
|
||||||
Next, the `AbstractAuthenticationProcessingFilter` can authenticate any authentication requests that are submitted to it.
|
|
||||||
|
|
||||||
image::{figures}/abstractauthenticationprocessingfilter.png[]
|
|
||||||
|
|
||||||
image:{icondir}/number_1.png[] When the user submits their credentials, the `AbstractAuthenticationProcessingFilter` creates an <<servlet-authentication-authentication,`Authentication`>> from the `HttpServletRequest` to be authenticated.
|
|
||||||
The type of `Authentication` created depends on the subclass of `AbstractAuthenticationProcessingFilter`.
|
|
||||||
For example, <<servlet-authentication-usernamepasswordauthenticationfilter,`UsernamePasswordAuthenticationFilter`>> creates a `UsernamePasswordAuthenticationToken` from a __username__ and __password__ that are submitted in the `HttpServletRequest`.
|
|
||||||
|
|
||||||
image:{icondir}/number_2.png[] Next, the <<servlet-authentication-authentication,`Authentication`>> is passed into the <<servlet-authentication-authenticationmanager,`AuthenticationManager`>> to be authenticated.
|
|
||||||
|
|
||||||
image:{icondir}/number_3.png[] If authentication fails, then __Failure__
|
|
||||||
|
|
||||||
* The <<servlet-authentication-securitycontextholder>> is cleared out.
|
|
||||||
* `RememberMeServices.loginFail` is invoked.
|
|
||||||
If remember me is not configured, this is a no-op.
|
|
||||||
// FIXME: link to rememberme
|
|
||||||
* `AuthenticationFailureHandler` is invoked.
|
|
||||||
// FIXME: link to AuthenticationFailureHandler
|
|
||||||
|
|
||||||
image:{icondir}/number_4.png[] If authentication is successful, then __Success__.
|
|
||||||
|
|
||||||
* `SessionAuthenticationStrategy` is notified of a new log in.
|
|
||||||
// FIXME: Add link to SessionAuthenticationStrategy
|
|
||||||
* The <<servlet-authentication-authentication>> is set on the <<servlet-authentication-securitycontextholder>>.
|
|
||||||
Later the `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession`.
|
|
||||||
// FIXME: link securitycontextpersistencefilter
|
|
||||||
* `RememberMeServices.loginSuccess` is invoked.
|
|
||||||
If remember me is not configured, this is a no-op.
|
|
||||||
// FIXME: link to rememberme
|
|
||||||
* `ApplicationEventPublisher` publishes an `InteractiveAuthenticationSuccessEvent`.
|
|
||||||
* `AuthenticationSuccessHandler` is invoked.
|
|
||||||
// FIXME: link to AuthenticationSuccessHandler
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
[[servlet-authentication-authenticationentrypoint]]
|
|
||||||
= Request Credentials with `AuthenticationEntryPoint`
|
|
||||||
|
|
||||||
|
|
||||||
{security-api-url}org/springframework/security/web/AuthenticationEntryPoint.html[`AuthenticationEntryPoint`] is used to send an HTTP response that requests credentials from a client.
|
|
||||||
|
|
||||||
Sometimes a client will proactively include credentials such as a username/password to request a resource.
|
|
||||||
In these cases, Spring Security does not need to provide an HTTP response that requests credentials from the client since they are already included.
|
|
||||||
|
|
||||||
In other cases, a client will make an unauthenticated request to a resource that they are not authorized to access.
|
|
||||||
In this case, an implementation of `AuthenticationEntryPoint` is used to request credentials from the client.
|
|
||||||
The `AuthenticationEntryPoint` implementation might perform a <<servlet-authentication-form,redirect to a log in page>>, respond with an <<servlet-authentication-basic,WWW-Authenticate>> header, etc.
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
[[servlet-authentication-authenticationmanager]]
|
|
||||||
= AuthenticationManager
|
|
||||||
|
|
||||||
{security-api-url}org/springframework/security/authentication/AuthenticationManager.html[`AuthenticationManager`] is the API that defines how Spring Security's Filters perform <<authentication,authentication>>.
|
|
||||||
The <<servlet-authentication-authentication,`Authentication`>> that is returned is then set on the <<servlet-authentication-securitycontextholder>> by the controller (i.e. <<servlet-security-filters,Spring Security's ``Filters``s>>) that invoked the `AuthenticationManager`.
|
|
||||||
If you are not integrating with __Spring Security's ``Filters``s__ you can set the `SecurityContextHolder` directly and are not required to use an `AuthenticationManager`.
|
|
||||||
|
|
||||||
While the implementation of `AuthenticationManager` could be anything, the most common implementation is <<servlet-authentication-providermanager,`ProviderManager`>>.
|
|
||||||
// FIXME: add configuration
|
|
|
@ -1,6 +0,0 @@
|
||||||
[[servlet-authentication-authenticationprovider]]
|
|
||||||
= AuthenticationProvider
|
|
||||||
|
|
||||||
Multiple {security-api-url}org/springframework/security/authentication/AuthenticationProvider.html[``AuthenticationProvider``s] can be injected into <<servlet-authentication-providermanager,`ProviderManager`>>.
|
|
||||||
Each `AuthenticationProvider` performs a specific type of authentication.
|
|
||||||
For example, <<servlet-authentication-daoauthenticationprovider,`DaoAuthenticationProvider`>> supports username/password based authentication while `JwtAuthenticationProvider` supports authenticating a JWT token.
|
|
|
@ -1,18 +0,0 @@
|
||||||
[[servlet-authentication-authentication]]
|
|
||||||
= Authentication
|
|
||||||
|
|
||||||
The {security-api-url}org/springframework/security/core/Authentication.html[`Authentication`] serves two main purposes within Spring Security:
|
|
||||||
|
|
||||||
* An input to <<servlet-authentication-authenticationmanager,`AuthenticationManager`>> to provide the credentials a user has provided to authenticate.
|
|
||||||
When used in this scenario, `isAuthenticated()` returns `false`.
|
|
||||||
* Represents the currently authenticated user.
|
|
||||||
The current `Authentication` can be obtained from the <<servlet-authentication-securitycontext>>.
|
|
||||||
|
|
||||||
The `Authentication` contains:
|
|
||||||
|
|
||||||
* `principal` - identifies the user.
|
|
||||||
When authenticating with a username/password this is often an instance of <<servlet-authentication-userdetails,`UserDetails`>>.
|
|
||||||
* `credentials` - often a password.
|
|
||||||
In many cases this will be cleared after the user is authenticated to ensure it is not leaked.
|
|
||||||
* `authorities` - the <<servlet-authentication-granted-authority,``GrantedAuthority``s>> are high level permissions the user is granted.
|
|
||||||
A few examples are roles or scopes.
|
|
|
@ -1,16 +0,0 @@
|
||||||
[[servlet-authentication-granted-authority]]
|
|
||||||
= GrantedAuthority
|
|
||||||
{security-api-url}org/springframework/security/core/GrantedAuthority.html[``GrantedAuthority``s] are high level permissions the user is granted. A few examples are roles or scopes.
|
|
||||||
|
|
||||||
``GrantedAuthority``s can be obtained from the <<servlet-authentication-authentication,`Authentication.getAuthorities()`>> method.
|
|
||||||
This method provides a `Collection` of `GrantedAuthority` objects.
|
|
||||||
A `GrantedAuthority` is, not surprisingly, an authority that is granted to the principal.
|
|
||||||
Such authorities are usually "roles", such as `ROLE_ADMINISTRATOR` or `ROLE_HR_SUPERVISOR`.
|
|
||||||
These roles are later on configured for web authorization, method authorization and domain object authorization.
|
|
||||||
Other parts of Spring Security are capable of interpreting these authorities, and expect them to be present.
|
|
||||||
When using username/password based authentication ``GrantedAuthority``s are usually loaded by the <<servlet-authentication-userdetailsservice,`UserDetailsService`>>.
|
|
||||||
|
|
||||||
Usually the `GrantedAuthority` objects are application-wide permissions.
|
|
||||||
They are not specific to a given domain object.
|
|
||||||
Thus, you wouldn't likely have a `GrantedAuthority` to represent a permission to `Employee` object number 54, because if there are thousands of such authorities you would quickly run out of memory (or, at the very least, cause the application to take a long time to authenticate a user).
|
|
||||||
Of course, Spring Security is expressly designed to handle this common requirement, but you'd instead use the project's domain object security capabilities for this purpose.
|
|
|
@ -1,22 +1,249 @@
|
||||||
include::security-context-holder.adoc[leveloffset=+1]
|
[[servlet-authentication-architecture]]
|
||||||
|
= Servlet Authentication Architecture
|
||||||
|
:figures: images/servlet/authentication/architecture
|
||||||
|
:icondir: images/icons
|
||||||
|
|
||||||
include::security-context.adoc[leveloffset=+1]
|
This discussion expands on <<servlet-architecture>> to discuss the Servlet Authentication architecture.
|
||||||
|
|
||||||
include::authentication.adoc[leveloffset=+1]
|
[[servlet-authentication-securitycontextholder]]
|
||||||
|
== SecurityContextHolder
|
||||||
|
|
||||||
include::granted-authority.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::authentication-manager.adoc[leveloffset=+1]
|
At the heart of Spring Security's authentication model is the `SecurityContextHolder`.
|
||||||
|
It contains the <<servlet-authentication-securitycontext>>.
|
||||||
|
|
||||||
include::provider-manager.adoc[leveloffset=+1]
|
image::{figures}/securitycontextholder.png[]
|
||||||
|
|
||||||
|
The `SecurityContextHolder` is where Spring Security stores the details of who is <<authentication,authenticated>>.
|
||||||
|
Spring Security does not care how the `SecurityContextHolder` is populated.
|
||||||
|
If it contains a value, then it is used as the currently authenticated user.
|
||||||
|
|
||||||
|
The simplest way to indicate a user is authenticated is to set the `SecurityContextHolder` directly.
|
||||||
|
|
||||||
|
.Setting `SecurityContextHolder`
|
||||||
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
|
----
|
||||||
|
SecurityContext context = SecurityContextHolder.createEmptyContext(); // <1>
|
||||||
|
Authentication authentication =
|
||||||
|
new TestingAuthenticationToken("username", "password", "ROLE_USER"); // <2>
|
||||||
|
context.setAuthentication(authentication);
|
||||||
|
|
||||||
|
SecurityContextHolder.setContext(context); // <3>
|
||||||
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
val context: SecurityContext = SecurityContextHolder.createEmptyContext() // <1>
|
||||||
|
val authentication: Authentication = TestingAuthenticationToken("username", "password", "ROLE_USER") // <2>
|
||||||
|
context.authentication = authentication
|
||||||
|
|
||||||
|
SecurityContextHolder.setContext(context) // <3>
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
<1> We start by creating an empty `SecurityContext`.
|
||||||
|
It is important to create a new `SecurityContext` instance instead of using `SecurityContextHolder.getContext().setAuthentication(authentication)` to avoid race conditions across multiple threads.
|
||||||
|
<2> Next we create a new <<servlet-authentication-authentication,`Authentication`>> object.
|
||||||
|
Spring Security does not care what type of `Authentication` implementation is set on the `SecurityContext`.
|
||||||
|
Here we use `TestingAuthenticationToken` because it is very simple.
|
||||||
|
A more common production scenario is `UsernamePasswordAuthenticationToken(userDetails, password, authorities)`.
|
||||||
|
<3> Finally, we set the `SecurityContext` on the `SecurityContextHolder`.
|
||||||
|
Spring Security will use this information for <<servlet-authorization,authorization>>.
|
||||||
|
|
||||||
|
If you wish to obtain information about the authenticated principal, you can do so by accessing the `SecurityContextHolder`.
|
||||||
|
|
||||||
|
.Access Currently Authenticated User
|
||||||
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
|
----
|
||||||
|
SecurityContext context = SecurityContextHolder.getContext();
|
||||||
|
Authentication authentication = context.getAuthentication();
|
||||||
|
String username = authentication.getName();
|
||||||
|
Object principal = authentication.getPrincipal();
|
||||||
|
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
|
||||||
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
val context = SecurityContextHolder.getContext()
|
||||||
|
val authentication = context.authentication
|
||||||
|
val username = authentication.name
|
||||||
|
val principal = authentication.principal
|
||||||
|
val authorities = authentication.authorities
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
// FIXME: add links to HttpServletRequest.getRemoteUser() and @CurrentSecurityContext @AuthenticationPrincipal
|
||||||
|
|
||||||
|
By default the `SecurityContextHolder` uses a `ThreadLocal` to store these details, which means that the `SecurityContext` is always available to methods in the same thread, even if the `SecurityContext` is not explicitly passed around as an argument to those methods.
|
||||||
|
Using a `ThreadLocal` in this way is quite safe if care is taken to clear the thread after the present principal's request is processed.
|
||||||
|
Spring Security's <<servlet-filterchainproxy,FilterChainProxy>> ensures that the `SecurityContext` is always cleared.
|
||||||
|
|
||||||
|
Some applications aren't entirely suitable for using a `ThreadLocal`, because of the specific way they work with threads.
|
||||||
|
For example, a Swing client might want all threads in a Java Virtual Machine to use the same security context.
|
||||||
|
`SecurityContextHolder` can be configured with a strategy on startup to specify how you would like the context to be stored.
|
||||||
|
For a standalone application you would use the `SecurityContextHolder.MODE_GLOBAL` strategy.
|
||||||
|
Other applications might want to have threads spawned by the secure thread also assume the same security identity.
|
||||||
|
This is achieved by using `SecurityContextHolder.MODE_INHERITABLETHREADLOCAL`.
|
||||||
|
You can change the mode from the default `SecurityContextHolder.MODE_THREADLOCAL` in two ways.
|
||||||
|
The first is to set a system property, the second is to call a static method on `SecurityContextHolder`.
|
||||||
|
Most applications won't need to change from the default, but if you do, take a look at the Javadoc for `SecurityContextHolder` to learn more.
|
||||||
|
|
||||||
|
[[servlet-authentication-securitycontext]]
|
||||||
|
== SecurityContext
|
||||||
|
|
||||||
|
The {security-api-url}org/springframework/security/core/context/SecurityContext.html[`SecurityContext`] is obtained from the <<servlet-authentication-securitycontextholder>>.
|
||||||
|
The `SecurityContext` contains an <<servlet-authentication-authentication>> object.
|
||||||
|
|
||||||
|
[[servlet-authentication-authentication]]
|
||||||
|
== Authentication
|
||||||
|
|
||||||
|
The {security-api-url}org/springframework/security/core/Authentication.html[`Authentication`] serves two main purposes within Spring Security:
|
||||||
|
|
||||||
|
* An input to <<servlet-authentication-authenticationmanager,`AuthenticationManager`>> to provide the credentials a user has provided to authenticate.
|
||||||
|
When used in this scenario, `isAuthenticated()` returns `false`.
|
||||||
|
* Represents the currently authenticated user.
|
||||||
|
The current `Authentication` can be obtained from the <<servlet-authentication-securitycontext>>.
|
||||||
|
|
||||||
|
The `Authentication` contains:
|
||||||
|
|
||||||
|
* `principal` - identifies the user.
|
||||||
|
When authenticating with a username/password this is often an instance of <<servlet-authentication-userdetails,`UserDetails`>>.
|
||||||
|
* `credentials` - often a password.
|
||||||
|
In many cases this will be cleared after the user is authenticated to ensure it is not leaked.
|
||||||
|
* `authorities` - the <<servlet-authentication-granted-authority,``GrantedAuthority``s>> are high level permissions the user is granted.
|
||||||
|
A few examples are roles or scopes.
|
||||||
|
|
||||||
|
[[servlet-authentication-granted-authority]]
|
||||||
|
== GrantedAuthority
|
||||||
|
{security-api-url}org/springframework/security/core/GrantedAuthority.html[``GrantedAuthority``s] are high level permissions the user is granted. A few examples are roles or scopes.
|
||||||
|
|
||||||
|
``GrantedAuthority``s can be obtained from the <<servlet-authentication-authentication,`Authentication.getAuthorities()`>> method.
|
||||||
|
This method provides a `Collection` of `GrantedAuthority` objects.
|
||||||
|
A `GrantedAuthority` is, not surprisingly, an authority that is granted to the principal.
|
||||||
|
Such authorities are usually "roles", such as `ROLE_ADMINISTRATOR` or `ROLE_HR_SUPERVISOR`.
|
||||||
|
These roles are later on configured for web authorization, method authorization and domain object authorization.
|
||||||
|
Other parts of Spring Security are capable of interpreting these authorities, and expect them to be present.
|
||||||
|
When using username/password based authentication ``GrantedAuthority``s are usually loaded by the <<servlet-authentication-userdetailsservice,`UserDetailsService`>>.
|
||||||
|
|
||||||
|
Usually the `GrantedAuthority` objects are application-wide permissions.
|
||||||
|
They are not specific to a given domain object.
|
||||||
|
Thus, you wouldn't likely have a `GrantedAuthority` to represent a permission to `Employee` object number 54, because if there are thousands of such authorities you would quickly run out of memory (or, at the very least, cause the application to take a long time to authenticate a user).
|
||||||
|
Of course, Spring Security is expressly designed to handle this common requirement, but you'd instead use the project's domain object security capabilities for this purpose.
|
||||||
|
|
||||||
|
[[servlet-authentication-authenticationmanager]]
|
||||||
|
== AuthenticationManager
|
||||||
|
|
||||||
|
{security-api-url}org/springframework/security/authentication/AuthenticationManager.html[`AuthenticationManager`] is the API that defines how Spring Security's Filters perform <<authentication,authentication>>.
|
||||||
|
The <<servlet-authentication-authentication,`Authentication`>> that is returned is then set on the <<servlet-authentication-securitycontextholder>> by the controller (i.e. <<servlet-security-filters,Spring Security's ``Filters``s>>) that invoked the `AuthenticationManager`.
|
||||||
|
If you are not integrating with __Spring Security's ``Filters``s__ you can set the `SecurityContextHolder` directly and are not required to use an `AuthenticationManager`.
|
||||||
|
|
||||||
|
While the implementation of `AuthenticationManager` could be anything, the most common implementation is <<servlet-authentication-providermanager,`ProviderManager`>>.
|
||||||
|
// FIXME: add configuration
|
||||||
|
|
||||||
|
[[servlet-authentication-providermanager]]
|
||||||
|
== ProviderManager
|
||||||
|
|
||||||
|
{security-api-url}org/springframework/security/authentication/ProviderManager.html[`ProviderManager`] is the most commonly used implementation of <<servlet-authentication-authenticationmanager,`AuthenticationManager`>>.
|
||||||
|
`ProviderManager` delegates to a `List` of <<servlet-authentication-authenticationprovider,``AuthenticationProvider``s>>.
|
||||||
|
// FIXME: link to AuthenticationProvider
|
||||||
|
Each `AuthenticationProvider` has an opportunity to indicate that authentication should be successful, fail, or indicate it cannot make a decision and allow a downstream `AuthenticationProvider` to decide.
|
||||||
|
If none of the configured ``AuthenticationProvider``s can authenticate, then authentication will fail with a `ProviderNotFoundException` which is a special `AuthenticationException` that indicates the `ProviderManager` was not configured to support the type of `Authentication` that was passed into it.
|
||||||
|
|
||||||
|
image::{figures}/providermanager.png[]
|
||||||
|
|
||||||
|
In practice each `AuthenticationProvider` knows how to perform a specific type of authentication.
|
||||||
|
For example, one `AuthenticationProvider` might be able to validate a username/password, while another might be able to authenticate a SAML assertion.
|
||||||
|
This allows each `AuthenticationProvider` to do a very specific type of authentication, while supporting multiple types of authentication and only exposing a single `AuthenticationManager` bean.
|
||||||
|
|
||||||
|
`ProviderManager` also allows configuring an optional parent `AuthenticationManager` which is consulted in the event that no `AuthenticationProvider` can perform authentication.
|
||||||
|
The parent can be any type of `AuthenticationManager`, but it is often an instance of `ProviderManager`.
|
||||||
|
|
||||||
|
image::{figures}/providermanager-parent.png[]
|
||||||
|
|
||||||
|
In fact, multiple `ProviderManager` instances might share the same parent `AuthenticationManager`.
|
||||||
|
This is somewhat common in scenarios where there are multiple <<servlet-securityfilterchain,`SecurityFilterChain`>> instances that have some authentication in common (the shared parent `AuthenticationManager`), but also different authentication mechanisms (the different `ProviderManager` instances).
|
||||||
|
|
||||||
|
image::{figures}/providermanagers-parent.png[]
|
||||||
|
|
||||||
|
[[servlet-authentication-providermanager-erasing-credentials]]
|
||||||
|
By default `ProviderManager` will attempt to clear any sensitive credentials information from the `Authentication` object which is returned by a successful authentication request.
|
||||||
|
This prevents information like passwords being retained longer than necessary in the `HttpSession`.
|
||||||
|
|
||||||
|
This may cause issues when you are using a cache of user objects, for example, to improve performance in a stateless application.
|
||||||
|
If the `Authentication` contains a reference to an object in the cache (such as a `UserDetails` instance) and this has its credentials removed, then it will no longer be possible to authenticate against the cached value.
|
||||||
|
You need to take this into account if you are using a cache.
|
||||||
|
An obvious solution is to make a copy of the object first, either in the cache implementation or in the `AuthenticationProvider` which creates the returned `Authentication` object.
|
||||||
|
Alternatively, you can disable the `eraseCredentialsAfterAuthentication` property on `ProviderManager`.
|
||||||
|
See the {security-api-url}org/springframework/security/authentication/ProviderManager.html[Javadoc] for more information.
|
||||||
|
|
||||||
|
[[servlet-authentication-authenticationprovider]]
|
||||||
|
== AuthenticationProvider
|
||||||
|
|
||||||
|
Multiple {security-api-url}org/springframework/security/authentication/AuthenticationProvider.html[``AuthenticationProvider``s] can be injected into <<servlet-authentication-providermanager,`ProviderManager`>>.
|
||||||
|
Each `AuthenticationProvider` performs a specific type of authentication.
|
||||||
|
For example, <<servlet-authentication-daoauthenticationprovider,`DaoAuthenticationProvider`>> supports username/password based authentication while `JwtAuthenticationProvider` supports authenticating a JWT token.
|
||||||
|
|
||||||
|
[[servlet-authentication-authenticationentrypoint]]
|
||||||
|
== Request Credentials with `AuthenticationEntryPoint`
|
||||||
|
|
||||||
|
{security-api-url}org/springframework/security/web/AuthenticationEntryPoint.html[`AuthenticationEntryPoint`] is used to send an HTTP response that requests credentials from a client.
|
||||||
|
|
||||||
|
Sometimes a client will proactively include credentials such as a username/password to request a resource.
|
||||||
|
In these cases, Spring Security does not need to provide an HTTP response that requests credentials from the client since they are already included.
|
||||||
|
|
||||||
|
In other cases, a client will make an unauthenticated request to a resource that they are not authorized to access.
|
||||||
|
In this case, an implementation of `AuthenticationEntryPoint` is used to request credentials from the client.
|
||||||
|
The `AuthenticationEntryPoint` implementation might perform a <<servlet-authentication-form,redirect to a log in page>>, respond with an <<servlet-authentication-basic,WWW-Authenticate>> header, etc.
|
||||||
|
|
||||||
include::authentication-provider.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::authentication-entry-point.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
// FIXME: authenticationsuccesshandler
|
// FIXME: authenticationsuccesshandler
|
||||||
// FIXME: authenticationfailurehandler
|
// FIXME: authenticationfailurehandler
|
||||||
|
|
||||||
include::abstract-authentication-processing-filter.adoc[leveloffset=+1]
|
[[servlet-authentication-abstractprocessingfilter]]
|
||||||
|
== AbstractAuthenticationProcessingFilter
|
||||||
|
|
||||||
|
{security-api-url}org/springframework/security/web/authentication/AbstractAuthenticationProcessingFilter.html[`AbstractAuthenticationProcessingFilter`] is used as a base `Filter` for authenticating a user's credentials.
|
||||||
|
Before the credentials can be authenticated, Spring Security typically requests the credentials using <<servlet-authentication-authenticationentrypoint,`AuthenticationEntryPoint`>>.
|
||||||
|
|
||||||
|
Next, the `AbstractAuthenticationProcessingFilter` can authenticate any authentication requests that are submitted to it.
|
||||||
|
|
||||||
|
image::{figures}/abstractauthenticationprocessingfilter.png[]
|
||||||
|
|
||||||
|
image:{icondir}/number_1.png[] When the user submits their credentials, the `AbstractAuthenticationProcessingFilter` creates an <<servlet-authentication-authentication,`Authentication`>> from the `HttpServletRequest` to be authenticated.
|
||||||
|
The type of `Authentication` created depends on the subclass of `AbstractAuthenticationProcessingFilter`.
|
||||||
|
For example, <<servlet-authentication-usernamepasswordauthenticationfilter,`UsernamePasswordAuthenticationFilter`>> creates a `UsernamePasswordAuthenticationToken` from a __username__ and __password__ that are submitted in the `HttpServletRequest`.
|
||||||
|
|
||||||
|
image:{icondir}/number_2.png[] Next, the <<servlet-authentication-authentication,`Authentication`>> is passed into the <<servlet-authentication-authenticationmanager,`AuthenticationManager`>> to be authenticated.
|
||||||
|
|
||||||
|
image:{icondir}/number_3.png[] If authentication fails, then __Failure__
|
||||||
|
|
||||||
|
* The <<servlet-authentication-securitycontextholder>> is cleared out.
|
||||||
|
* `RememberMeServices.loginFail` is invoked.
|
||||||
|
If remember me is not configured, this is a no-op.
|
||||||
|
// FIXME: link to rememberme
|
||||||
|
* `AuthenticationFailureHandler` is invoked.
|
||||||
|
// FIXME: link to AuthenticationFailureHandler
|
||||||
|
|
||||||
|
image:{icondir}/number_4.png[] If authentication is successful, then __Success__.
|
||||||
|
|
||||||
|
* `SessionAuthenticationStrategy` is notified of a new log in.
|
||||||
|
// FIXME: Add link to SessionAuthenticationStrategy
|
||||||
|
* The <<servlet-authentication-authentication>> is set on the <<servlet-authentication-securitycontextholder>>.
|
||||||
|
Later the `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession`.
|
||||||
|
// FIXME: link securitycontextpersistencefilter
|
||||||
|
* `RememberMeServices.loginSuccess` is invoked.
|
||||||
|
If remember me is not configured, this is a no-op.
|
||||||
|
// FIXME: link to rememberme
|
||||||
|
* `ApplicationEventPublisher` publishes an `InteractiveAuthenticationSuccessEvent`.
|
||||||
|
* `AuthenticationSuccessHandler` is invoked.
|
||||||
|
// FIXME: link to AuthenticationSuccessHandler
|
||||||
|
|
||||||
|
|
||||||
// daoauthenticationprovider (goes in username/password)
|
// daoauthenticationprovider (goes in username/password)
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
[[servlet-authentication-providermanager]]
|
|
||||||
= ProviderManager
|
|
||||||
:figures: images/servlet/authentication/architecture
|
|
||||||
|
|
||||||
{security-api-url}org/springframework/security/authentication/ProviderManager.html[`ProviderManager`] is the most commonly used implementation of <<servlet-authentication-authenticationmanager,`AuthenticationManager`>>.
|
|
||||||
`ProviderManager` delegates to a `List` of <<servlet-authentication-authenticationprovider,``AuthenticationProvider``s>>.
|
|
||||||
// FIXME: link to AuthenticationProvider
|
|
||||||
Each `AuthenticationProvider` has an opportunity to indicate that authentication should be successful, fail, or indicate it cannot make a decision and allow a downstream `AuthenticationProvider` to decide.
|
|
||||||
If none of the configured ``AuthenticationProvider``s can authenticate, then authentication will fail with a `ProviderNotFoundException` which is a special `AuthenticationException` that indicates the `ProviderManager` was not configured to support the type of `Authentication` that was passed into it.
|
|
||||||
|
|
||||||
image::{figures}/providermanager.png[]
|
|
||||||
|
|
||||||
In practice each `AuthenticationProvider` knows how to perform a specific type of authentication.
|
|
||||||
For example, one `AuthenticationProvider` might be able to validate a username/password, while another might be able to authenticate a SAML assertion.
|
|
||||||
This allows each `AuthenticationProvider` to do a very specific type of authentication, while supporting multiple types of authentication and only exposing a single `AuthenticationManager` bean.
|
|
||||||
|
|
||||||
`ProviderManager` also allows configuring an optional parent `AuthenticationManager` which is consulted in the event that no `AuthenticationProvider` can perform authentication.
|
|
||||||
The parent can be any type of `AuthenticationManager`, but it is often an instance of `ProviderManager`.
|
|
||||||
|
|
||||||
image::{figures}/providermanager-parent.png[]
|
|
||||||
|
|
||||||
In fact, multiple `ProviderManager` instances might share the same parent `AuthenticationManager`.
|
|
||||||
This is somewhat common in scenarios where there are multiple <<servlet-securityfilterchain,`SecurityFilterChain`>> instances that have some authentication in common (the shared parent `AuthenticationManager`), but also different authentication mechanisms (the different `ProviderManager` instances).
|
|
||||||
|
|
||||||
image::{figures}/providermanagers-parent.png[]
|
|
||||||
|
|
||||||
[[servlet-authentication-providermanager-erasing-credentials]]
|
|
||||||
By default `ProviderManager` will attempt to clear any sensitive credentials information from the `Authentication` object which is returned by a successful authentication request.
|
|
||||||
This prevents information like passwords being retained longer than necessary in the `HttpSession`.
|
|
||||||
|
|
||||||
This may cause issues when you are using a cache of user objects, for example, to improve performance in a stateless application.
|
|
||||||
If the `Authentication` contains a reference to an object in the cache (such as a `UserDetails` instance) and this has its credentials removed, then it will no longer be possible to authenticate against the cached value.
|
|
||||||
You need to take this into account if you are using a cache.
|
|
||||||
An obvious solution is to make a copy of the object first, either in the cache implementation or in the `AuthenticationProvider` which creates the returned `Authentication` object.
|
|
||||||
Alternatively, you can disable the `eraseCredentialsAfterAuthentication` property on `ProviderManager`.
|
|
||||||
See the {security-api-url}org/springframework/security/authentication/ProviderManager.html[Javadoc] for more information.
|
|
|
@ -1,89 +0,0 @@
|
||||||
[[servlet-authentication-securitycontextholder]]
|
|
||||||
= SecurityContextHolder
|
|
||||||
|
|
||||||
:figures: images/servlet/authentication/architecture
|
|
||||||
|
|
||||||
At the heart of Spring Security's authentication model is the `SecurityContextHolder`.
|
|
||||||
It contains the <<servlet-authentication-securitycontext>>.
|
|
||||||
|
|
||||||
image::{figures}/securitycontextholder.png[]
|
|
||||||
|
|
||||||
The `SecurityContextHolder` is where Spring Security stores the details of who is <<authentication,authenticated>>.
|
|
||||||
Spring Security does not care how the `SecurityContextHolder` is populated.
|
|
||||||
If it contains a value, then it is used as the currently authenticated user.
|
|
||||||
|
|
||||||
The simplest way to indicate a user is authenticated is to set the `SecurityContextHolder` directly.
|
|
||||||
|
|
||||||
.Setting `SecurityContextHolder`
|
|
||||||
====
|
|
||||||
.Java
|
|
||||||
[source,java,role="primary"]
|
|
||||||
----
|
|
||||||
SecurityContext context = SecurityContextHolder.createEmptyContext(); // <1>
|
|
||||||
Authentication authentication =
|
|
||||||
new TestingAuthenticationToken("username", "password", "ROLE_USER"); // <2>
|
|
||||||
context.setAuthentication(authentication);
|
|
||||||
|
|
||||||
SecurityContextHolder.setContext(context); // <3>
|
|
||||||
----
|
|
||||||
|
|
||||||
.Kotlin
|
|
||||||
[source,kotlin,role="secondary"]
|
|
||||||
----
|
|
||||||
val context: SecurityContext = SecurityContextHolder.createEmptyContext() // <1>
|
|
||||||
val authentication: Authentication = TestingAuthenticationToken("username", "password", "ROLE_USER") // <2>
|
|
||||||
context.authentication = authentication
|
|
||||||
|
|
||||||
SecurityContextHolder.setContext(context) // <3>
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
<1> We start by creating an empty `SecurityContext`.
|
|
||||||
It is important to create a new `SecurityContext` instance instead of using `SecurityContextHolder.getContext().setAuthentication(authentication)` to avoid race conditions across multiple threads.
|
|
||||||
<2> Next we create a new <<servlet-authentication-authentication,`Authentication`>> object.
|
|
||||||
Spring Security does not care what type of `Authentication` implementation is set on the `SecurityContext`.
|
|
||||||
Here we use `TestingAuthenticationToken` because it is very simple.
|
|
||||||
A more common production scenario is `UsernamePasswordAuthenticationToken(userDetails, password, authorities)`.
|
|
||||||
<3> Finally, we set the `SecurityContext` on the `SecurityContextHolder`.
|
|
||||||
Spring Security will use this information for <<servlet-authorization,authorization>>.
|
|
||||||
|
|
||||||
If you wish to obtain information about the authenticated principal, you can do so by accessing the `SecurityContextHolder`.
|
|
||||||
|
|
||||||
.Access Currently Authenticated User
|
|
||||||
====
|
|
||||||
.Java
|
|
||||||
[source,java,role="primary"]
|
|
||||||
----
|
|
||||||
SecurityContext context = SecurityContextHolder.getContext();
|
|
||||||
Authentication authentication = context.getAuthentication();
|
|
||||||
String username = authentication.getName();
|
|
||||||
Object principal = authentication.getPrincipal();
|
|
||||||
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
|
|
||||||
----
|
|
||||||
|
|
||||||
.Kotlin
|
|
||||||
[source,kotlin,role="secondary"]
|
|
||||||
----
|
|
||||||
val context = SecurityContextHolder.getContext()
|
|
||||||
val authentication = context.authentication
|
|
||||||
val username = authentication.name
|
|
||||||
val principal = authentication.principal
|
|
||||||
val authorities = authentication.authorities
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
// FIXME: add links to HttpServletRequest.getRemoteUser() and @CurrentSecurityContext @AuthenticationPrincipal
|
|
||||||
|
|
||||||
By default the `SecurityContextHolder` uses a `ThreadLocal` to store these details, which means that the `SecurityContext` is always available to methods in the same thread, even if the `SecurityContext` is not explicitly passed around as an argument to those methods.
|
|
||||||
Using a `ThreadLocal` in this way is quite safe if care is taken to clear the thread after the present principal's request is processed.
|
|
||||||
Spring Security's <<servlet-filterchainproxy,FilterChainProxy>> ensures that the `SecurityContext` is always cleared.
|
|
||||||
|
|
||||||
Some applications aren't entirely suitable for using a `ThreadLocal`, because of the specific way they work with threads.
|
|
||||||
For example, a Swing client might want all threads in a Java Virtual Machine to use the same security context.
|
|
||||||
`SecurityContextHolder` can be configured with a strategy on startup to specify how you would like the context to be stored.
|
|
||||||
For a standalone application you would use the `SecurityContextHolder.MODE_GLOBAL` strategy.
|
|
||||||
Other applications might want to have threads spawned by the secure thread also assume the same security identity.
|
|
||||||
This is achieved by using `SecurityContextHolder.MODE_INHERITABLETHREADLOCAL`.
|
|
||||||
You can change the mode from the default `SecurityContextHolder.MODE_THREADLOCAL` in two ways.
|
|
||||||
The first is to set a system property, the second is to call a static method on `SecurityContextHolder`.
|
|
||||||
Most applications won't need to change from the default, but if you do, take a look at the Javadoc for `SecurityContextHolder` to learn more.
|
|
|
@ -1,5 +0,0 @@
|
||||||
[[servlet-authentication-securitycontext]]
|
|
||||||
= SecurityContext
|
|
||||||
|
|
||||||
The {security-api-url}org/springframework/security/core/context/SecurityContext.html[`SecurityContext`] is obtained from the <<servlet-authentication-securitycontextholder>>.
|
|
||||||
The `SecurityContext` contains an <<servlet-authentication-authentication>> object.
|
|
|
@ -2,27 +2,14 @@
|
||||||
= Authentication
|
= Authentication
|
||||||
|
|
||||||
Spring Security provides comprehensive support for <<authentication>>.
|
Spring Security provides comprehensive support for <<authentication>>.
|
||||||
This section discusses:
|
We start by discussing the overall <<servlet-architecture,Servlet Authentication Architecture>>.
|
||||||
|
As you might expect, this section is more abstract describing the architecture without much discussion on how it applies to concrete flows.
|
||||||
|
|
||||||
[[servlet-authentication-architecture]]
|
If you prefer, you can refer to <<servlet-authentication-mechanisms,Authentication Mechanisms>> for concrete ways in which users can authenticate.
|
||||||
*Architecture Components*
|
These sections focus on specific ways you may want to authenticate and point back at the architecture sections to describe how the specific flows work.
|
||||||
|
|
||||||
This section describes the main architectural components of Spring Security's used in Servlet authentication.
|
|
||||||
If you need concrete flows that explain how these pieces fit together, look at the <<servlet-authentication-mechanisms,Authentication Mechanism>> specific sections.
|
|
||||||
|
|
||||||
* <<servlet-authentication-securitycontextholder>> - the `SecurityContextHolder` is where Spring Security stores the details of who is <<authentication,authenticated>>.
|
|
||||||
* <<servlet-authentication-securitycontext>> - is obtained from the `SecurityContextHolder` and contains the `Authentication` of the currently authenticated user.
|
|
||||||
* <<servlet-authentication-authentication>> - can be the input to `AuthenticationManager` to provide the credentials a user has provided to authenticate or the current user from the `SecurityContext`.
|
|
||||||
* <<servlet-authentication-granted-authority>> - an authority that is granted to the principal on the `Authentication` (i.e. roles, scopes, etc.)
|
|
||||||
* <<servlet-authentication-authenticationmanager>> - the API that defines how Spring Security's Filters perform <<authentication,authentication>>.
|
|
||||||
* <<servlet-authentication-providermanager>> - the most common implementation of `AuthenticationManager`.
|
|
||||||
* <<servlet-authentication-authenticationprovider>> - used by `ProviderManager` to perform a specific type of authentication.
|
|
||||||
* <<servlet-authentication-authenticationentrypoint>> - used for requesting credentials from a client (i.e. redirecting to a log in page, sending a `WWW-Authenticate` response, etc.)
|
|
||||||
* <<servlet-authentication-abstractprocessingfilter>> - a base `Filter` used for authentication.
|
|
||||||
This also gives a good idea of the high level flow of authentication and how pieces work together.
|
|
||||||
|
|
||||||
[[servlet-authentication-mechanisms]]
|
[[servlet-authentication-mechanisms]]
|
||||||
*Authentication Mechanisms*
|
== Authentication Mechanisms
|
||||||
|
|
||||||
// FIXME: brief description
|
// FIXME: brief description
|
||||||
|
|
||||||
|
@ -35,32 +22,3 @@ This also gives a good idea of the high level flow of authentication and how pie
|
||||||
* <<servlet-openid,OpenID>> - OpenID Authentication (not to be confused with OpenID Connect)
|
* <<servlet-openid,OpenID>> - OpenID Authentication (not to be confused with OpenID Connect)
|
||||||
* <<servlet-preauth>> - authenticate with an external mechanism such as https://www.siteminder.com/[SiteMinder] or Java EE security but still use Spring Security for authorization and protection against common exploits.
|
* <<servlet-preauth>> - authenticate with an external mechanism such as https://www.siteminder.com/[SiteMinder] or Java EE security but still use Spring Security for authorization and protection against common exploits.
|
||||||
* <<servlet-x509,X509 Authentication>> - X509 Authentication
|
* <<servlet-x509,X509 Authentication>> - X509 Authentication
|
||||||
|
|
||||||
// FIXME: Add other mechanisms
|
|
||||||
|
|
||||||
// We intentionally do not increase leveloffset, this is just for organization vs document structure
|
|
||||||
include::architecture/index.adoc[]
|
|
||||||
|
|
||||||
include::unpwd/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::session-management.adoc[]
|
|
||||||
|
|
||||||
include::rememberme.adoc[]
|
|
||||||
|
|
||||||
include::openid.adoc[]
|
|
||||||
|
|
||||||
include::anonymous.adoc[]
|
|
||||||
|
|
||||||
include::preauth.adoc[]
|
|
||||||
|
|
||||||
include::jaas.adoc[]
|
|
||||||
|
|
||||||
include::cas.adoc[]
|
|
||||||
|
|
||||||
include::x509.adoc[]
|
|
||||||
|
|
||||||
include::runas.adoc[]
|
|
||||||
|
|
||||||
include::logout.adoc[]
|
|
||||||
|
|
||||||
include::events.adoc[]
|
|
||||||
|
|
|
@ -6,15 +6,10 @@ Irrespective of how you choose to authenticate - whether using a Spring Security
|
||||||
In this part we'll explore the different `AbstractSecurityInterceptor` implementations, which were introduced in Part I.
|
In this part we'll explore the different `AbstractSecurityInterceptor` implementations, which were introduced in Part I.
|
||||||
We then move on to explore how to fine-tune authorization through use of domain access control lists.
|
We then move on to explore how to fine-tune authorization through use of domain access control lists.
|
||||||
|
|
||||||
include::architecture.adoc[leveloffset=+1]
|
* xref:servlet/authorization/architecture.adoc[leveloffset=+1]
|
||||||
|
* xref:servlet/authorization/authorize-requests.adoc[leveloffset=+1]
|
||||||
include::authorize-requests.adoc[leveloffset=+1]
|
* xref:servlet/authorization/expression-based.adoc[]
|
||||||
|
* xref:servlet/authorization/secure-objects.adoc[]
|
||||||
include::expression-based.adoc[]
|
* xref:servlet/authorization/method-security.adoc[]
|
||||||
|
* xref:servlet/authorization/acls.adoc[]
|
||||||
include::secure-objects.adoc[]
|
|
||||||
|
|
||||||
include::method-security.adoc[]
|
|
||||||
|
|
||||||
include::acls.adoc[]
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
[[servlet-exploits]]
|
[[servlet-exploits]]
|
||||||
= Protection Against Exploits
|
= Protection Against Exploits
|
||||||
|
|
||||||
include::csrf.adoc[leveloffset=+1]
|
This section discusses Servlet specific support for <<exploits,Spring Security's protection against common exploits>>.
|
||||||
|
|
||||||
include::headers.adoc[leveloffset=+1]
|
* xref:servlet/exploits/csrf.adoc[]
|
||||||
|
* xref:servlet/exploits/headers.adoc[]
|
||||||
include::http.adoc[leveloffset=+1]
|
* xref:servlet/exploits/http.adoc[]
|
||||||
|
* xref:servlet/exploits/firewall.adoc[]
|
||||||
include::firewall.adoc[leveloffset=+1]
|
|
||||||
|
|
|
@ -1,31 +1,4 @@
|
||||||
|
[[servlet-applications]]
|
||||||
= Servlet Applications
|
= Servlet Applications
|
||||||
|
|
||||||
Spring Security integrates with the Servlet Container by using a standard Servlet `Filter`. This means it works with any application that runs in a Servlet Container. More concretely, you do not need to use Spring in your Servlet-based application to take advantage of Spring Security.
|
Spring Security integrates with the Servlet Container by using a standard Servlet `Filter`. This means it works with any application that runs in a Servlet Container. More concretely, you do not need to use Spring in your Servlet-based application to take advantage of Spring Security.
|
||||||
|
|
||||||
include::hello/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::architecture/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::authentication/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::authorization/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::oauth2/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::saml2/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::exploits/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::integrations/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::java-configuration/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::kotlin-configuration/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::namespace/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::test/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::crypto/index.adoc[leveloffset=+1]
|
|
||||||
|
|
||||||
include::appendix/index.adoc[leveloffset=+1]
|
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
= Integrations
|
= Integrations
|
||||||
|
|
||||||
include::servlet-api.adoc[]
|
Spring Security integrates with numerous frameworks and APIs.
|
||||||
|
In this section, we discuss Spring Security integration with:
|
||||||
|
|
||||||
include::data.adoc[]
|
* xref:servlet/integrations/servlet-api.adoc[Servlet APIs]
|
||||||
|
* xref:servlet/integrations/data.adoc[Spring Data]
|
||||||
include::concurrency.adoc[]
|
* xref:servlet/integrations/concurrency.adoc[Java's Concurrency APIs]
|
||||||
|
* xref:servlet/integrations/jackson.adoc[Jackson]
|
||||||
include::jackson.adoc[]
|
* xref:servlet/integrations/localization.adoc[Localization]
|
||||||
|
* xref:servlet/integrations/mvc.adoc[Spring MVC]
|
||||||
include::localization.adoc[]
|
* xref:servlet/integrations/websocket.adoc[WebSocket]
|
||||||
|
* xref:servlet/integrations/cors.adoc[Spring's CORS Support]
|
||||||
include::mvc.adoc[]
|
* xref:servlet/integrations/jsp-taglibs.adoc[JSP Taglib]
|
||||||
|
|
||||||
include::websocket.adoc[]
|
|
||||||
|
|
||||||
include::cors.adoc[]
|
|
||||||
|
|
||||||
include::jsp-taglibs.adoc[]
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
= OAuth2
|
= OAuth2
|
||||||
|
|
||||||
include::oauth2-login.adoc[]
|
Spring Security provides comprehensive OAuth 2 support.
|
||||||
|
This section discusses how to integrate OAuth 2 into your servlet based application.
|
||||||
|
|
||||||
include::oauth2-client.adoc[]
|
* xref:servlet/oauth2/oauth2-login.adoc[]
|
||||||
|
* xref:servlet/oauth2/oauth2-client.adoc[]
|
||||||
include::oauth2-resourceserver.adoc[]
|
* xref:servlet/oauth2/oauth2-resourceserver.adoc[]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[[oauth2client]]
|
[[oauth2client]]
|
||||||
== OAuth 2.0 Client
|
= OAuth 2.0 Client
|
||||||
|
|
||||||
The OAuth 2.0 Client features provide support for the Client role as defined in the https://tools.ietf.org/html/rfc6749#section-1.1[OAuth 2.0 Authorization Framework].
|
The OAuth 2.0 Client features provide support for the Client role as defined in the https://tools.ietf.org/html/rfc6749#section-1.1[OAuth 2.0 Authorization Framework].
|
||||||
|
|
||||||
|
@ -166,11 +166,11 @@ The following sections will go into more detail on the core components used by O
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-core-interface-class]]
|
[[oauth2Client-core-interface-class]]
|
||||||
=== Core Interfaces / Classes
|
== Core Interfaces / Classes
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-client-registration]]
|
[[oauth2Client-client-registration]]
|
||||||
==== ClientRegistration
|
=== ClientRegistration
|
||||||
|
|
||||||
`ClientRegistration` is a representation of a client registered with an OAuth 2.0 or OpenID Connect 1.0 Provider.
|
`ClientRegistration` is a representation of a client registered with an OAuth 2.0 or OpenID Connect 1.0 Provider.
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ The above code will query in series `https://idp.example.com/issuer/.well-known/
|
||||||
As an alternative, you can use `ClientRegistrations.fromOidcIssuerLocation()` to only query the OpenID Connect Provider's Configuration endpoint.
|
As an alternative, you can use `ClientRegistrations.fromOidcIssuerLocation()` to only query the OpenID Connect Provider's Configuration endpoint.
|
||||||
|
|
||||||
[[oauth2Client-client-registration-repo]]
|
[[oauth2Client-client-registration-repo]]
|
||||||
==== ClientRegistrationRepository
|
=== ClientRegistrationRepository
|
||||||
|
|
||||||
The `ClientRegistrationRepository` serves as a repository for OAuth 2.0 / OpenID Connect 1.0 `ClientRegistration`(s).
|
The `ClientRegistrationRepository` serves as a repository for OAuth 2.0 / OpenID Connect 1.0 `ClientRegistration`(s).
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ class OAuth2ClientController {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2Client-authorized-client]]
|
[[oauth2Client-authorized-client]]
|
||||||
==== OAuth2AuthorizedClient
|
=== OAuth2AuthorizedClient
|
||||||
|
|
||||||
`OAuth2AuthorizedClient` is a representation of an Authorized Client.
|
`OAuth2AuthorizedClient` is a representation of an Authorized Client.
|
||||||
A client is considered to be authorized when the end-user (Resource Owner) has granted authorization to the client to access its protected resources.
|
A client is considered to be authorized when the end-user (Resource Owner) has granted authorization to the client to access its protected resources.
|
||||||
|
@ -327,7 +327,7 @@ A client is considered to be authorized when the end-user (Resource Owner) has g
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-authorized-repo-service]]
|
[[oauth2Client-authorized-repo-service]]
|
||||||
==== OAuth2AuthorizedClientRepository / OAuth2AuthorizedClientService
|
=== OAuth2AuthorizedClientRepository / OAuth2AuthorizedClientService
|
||||||
|
|
||||||
`OAuth2AuthorizedClientRepository` is responsible for persisting `OAuth2AuthorizedClient`(s) between web requests.
|
`OAuth2AuthorizedClientRepository` is responsible for persisting `OAuth2AuthorizedClient`(s) between web requests.
|
||||||
Whereas, the primary role of `OAuth2AuthorizedClientService` is to manage `OAuth2AuthorizedClient`(s) at the application-level.
|
Whereas, the primary role of `OAuth2AuthorizedClientService` is to manage `OAuth2AuthorizedClient`(s) at the application-level.
|
||||||
|
@ -396,7 +396,7 @@ Alternatively, the JDBC implementation `JdbcOAuth2AuthorizedClientService` may b
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-authorized-manager-provider]]
|
[[oauth2Client-authorized-manager-provider]]
|
||||||
==== OAuth2AuthorizedClientManager / OAuth2AuthorizedClientProvider
|
=== OAuth2AuthorizedClientManager / OAuth2AuthorizedClientProvider
|
||||||
|
|
||||||
The `OAuth2AuthorizedClientManager` is responsible for the overall management of `OAuth2AuthorizedClient`(s).
|
The `OAuth2AuthorizedClientManager` is responsible for the overall management of `OAuth2AuthorizedClient`(s).
|
||||||
|
|
||||||
|
@ -608,23 +608,23 @@ fun authorizedClientManager(
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-auth-grant-support]]
|
[[oauth2Client-auth-grant-support]]
|
||||||
=== Authorization Grant Support
|
== Authorization Grant Support
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-auth-code-grant]]
|
[[oauth2Client-auth-code-grant]]
|
||||||
==== Authorization Code
|
=== Authorization Code
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.1[Authorization Code] grant.
|
Please refer to 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
|
==== Obtaining Authorization
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to the https://tools.ietf.org/html/rfc6749#section-4.1.1[Authorization Request/Response] protocol flow for the Authorization Code grant.
|
Please refer to 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
|
==== Initiating the Authorization Request
|
||||||
|
|
||||||
The `OAuth2AuthorizationRequestRedirectFilter` uses an `OAuth2AuthorizationRequestResolver` to resolve an `OAuth2AuthorizationRequest` and initiate the Authorization Code grant flow by redirecting the end-user's user-agent to the Authorization Server's Authorization Endpoint.
|
The `OAuth2AuthorizationRequestRedirectFilter` uses an `OAuth2AuthorizationRequestResolver` to resolve an `OAuth2AuthorizationRequest` and initiate the Authorization Code grant flow by redirecting the end-user's user-agent to the Authorization Server's Authorization Endpoint.
|
||||||
|
|
||||||
|
@ -705,7 +705,7 @@ spring:
|
||||||
Configuring the `redirect-uri` with `URI` template variables is especially useful when the OAuth 2.0 Client is running behind a <<http-proxy-server,Proxy Server>>.
|
Configuring the `redirect-uri` with `URI` template variables is especially useful when the OAuth 2.0 Client is running behind a <<http-proxy-server,Proxy Server>>.
|
||||||
This ensures that the `X-Forwarded-*` headers are used when expanding the `redirect-uri`.
|
This ensures that the `X-Forwarded-*` headers are used when expanding the `redirect-uri`.
|
||||||
|
|
||||||
===== Customizing the Authorization Request
|
==== Customizing the Authorization Request
|
||||||
|
|
||||||
One of the primary use cases an `OAuth2AuthorizationRequestResolver` can realize is the ability to customize the Authorization Request with additional parameters above the standard parameters defined in the OAuth 2.0 Authorization Framework.
|
One of the primary use cases an `OAuth2AuthorizationRequestResolver` can realize is the ability to customize the Authorization Request with additional parameters above the standard parameters defined in the OAuth 2.0 Authorization Framework.
|
||||||
|
|
||||||
|
@ -852,7 +852,7 @@ private fun authorizationRequestCustomizer(): Consumer<OAuth2AuthorizationReques
|
||||||
====
|
====
|
||||||
|
|
||||||
|
|
||||||
===== Storing the Authorization Request
|
==== Storing the Authorization Request
|
||||||
|
|
||||||
The `AuthorizationRequestRepository` is responsible for the persistence of the `OAuth2AuthorizationRequest` from the time the Authorization Request is initiated to the time the Authorization Response is received (the callback).
|
The `AuthorizationRequestRepository` is responsible for the persistence of the `OAuth2AuthorizationRequest` from the time the Authorization Request is initiated to the time the Authorization Response is received (the callback).
|
||||||
|
|
||||||
|
@ -913,7 +913,7 @@ class OAuth2ClientSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
===== Requesting an Access Token
|
==== Requesting an Access Token
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to the https://tools.ietf.org/html/rfc6749#section-4.1.3[Access Token Request/Response] protocol flow for the Authorization Code grant.
|
Please refer to the https://tools.ietf.org/html/rfc6749#section-4.1.3[Access Token Request/Response] protocol flow for the Authorization Code grant.
|
||||||
|
@ -923,7 +923,7 @@ The default implementation of `OAuth2AccessTokenResponseClient` for the Authoriz
|
||||||
The `DefaultAuthorizationCodeTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
The `DefaultAuthorizationCodeTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
||||||
|
|
||||||
|
|
||||||
===== Customizing the Access Token Request
|
==== Customizing the Access Token Request
|
||||||
|
|
||||||
If you need to customize the pre-processing of the Token Request, you can provide `DefaultAuthorizationCodeTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<?>>`.
|
If you need to customize the pre-processing of the Token Request, you can provide `DefaultAuthorizationCodeTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<?>>`.
|
||||||
The default implementation `OAuth2AuthorizationCodeGrantRequestEntityConverter` builds a `RequestEntity` representation of a standard https://tools.ietf.org/html/rfc6749#section-4.1.3[OAuth 2.0 Access Token Request].
|
The default implementation `OAuth2AuthorizationCodeGrantRequestEntityConverter` builds a `RequestEntity` representation of a standard https://tools.ietf.org/html/rfc6749#section-4.1.3[OAuth 2.0 Access Token Request].
|
||||||
|
@ -932,7 +932,7 @@ However, providing a custom `Converter`, would allow you to extend the standard
|
||||||
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
|
==== Customizing the Access Token Response
|
||||||
|
|
||||||
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultAuthorizationCodeTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultAuthorizationCodeTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
||||||
The default `RestOperations` is configured as follows:
|
The default `RestOperations` is configured as follows:
|
||||||
|
@ -1021,13 +1021,13 @@ class OAuth2ClientSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-refresh-token-grant]]
|
[[oauth2Client-refresh-token-grant]]
|
||||||
==== Refresh Token
|
=== Refresh Token
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.5[Refresh Token].
|
Please refer to 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
|
==== Refreshing an Access Token
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to the https://tools.ietf.org/html/rfc6749#section-6[Access Token Request/Response] protocol flow for the Refresh Token grant.
|
Please refer to the https://tools.ietf.org/html/rfc6749#section-6[Access Token Request/Response] protocol flow for the Refresh Token grant.
|
||||||
|
@ -1037,7 +1037,7 @@ The default implementation of `OAuth2AccessTokenResponseClient` for the Refresh
|
||||||
The `DefaultRefreshTokenTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
The `DefaultRefreshTokenTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
||||||
|
|
||||||
|
|
||||||
===== Customizing the Access Token Request
|
==== Customizing the Access Token Request
|
||||||
|
|
||||||
If you need to customize the pre-processing of the Token Request, you can provide `DefaultRefreshTokenTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2RefreshTokenGrantRequest, RequestEntity<?>>`.
|
If you need to customize the pre-processing of the Token Request, you can provide `DefaultRefreshTokenTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2RefreshTokenGrantRequest, RequestEntity<?>>`.
|
||||||
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].
|
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].
|
||||||
|
@ -1046,7 +1046,7 @@ However, providing a custom `Converter`, would allow you to extend the standard
|
||||||
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
|
==== Customizing the Access Token Response
|
||||||
|
|
||||||
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultRefreshTokenTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultRefreshTokenTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
||||||
The default `RestOperations` is configured as follows:
|
The default `RestOperations` is configured as follows:
|
||||||
|
@ -1127,13 +1127,13 @@ If the `OAuth2AuthorizedClient.getRefreshToken()` is available and the `OAuth2Au
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-client-creds-grant]]
|
[[oauth2Client-client-creds-grant]]
|
||||||
==== Client Credentials
|
=== Client Credentials
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.4[Client Credentials] grant.
|
Please refer to 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
|
==== Requesting an Access Token
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to the https://tools.ietf.org/html/rfc6749#section-4.4.2[Access Token Request/Response] protocol flow for the Client Credentials grant.
|
Please refer to the https://tools.ietf.org/html/rfc6749#section-4.4.2[Access Token Request/Response] protocol flow for the Client Credentials grant.
|
||||||
|
@ -1143,7 +1143,7 @@ The default implementation of `OAuth2AccessTokenResponseClient` for the Client C
|
||||||
The `DefaultClientCredentialsTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
The `DefaultClientCredentialsTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
||||||
|
|
||||||
|
|
||||||
===== Customizing the Access Token Request
|
==== Customizing the Access Token Request
|
||||||
|
|
||||||
If you need to customize the pre-processing of the Token Request, you can provide `DefaultClientCredentialsTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2ClientCredentialsGrantRequest, RequestEntity<?>>`.
|
If you need to customize the pre-processing of the Token Request, you can provide `DefaultClientCredentialsTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2ClientCredentialsGrantRequest, RequestEntity<?>>`.
|
||||||
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].
|
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].
|
||||||
|
@ -1152,7 +1152,7 @@ However, providing a custom `Converter`, would allow you to extend the standard
|
||||||
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
|
==== Customizing the Access Token Response
|
||||||
|
|
||||||
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultClientCredentialsTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultClientCredentialsTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
||||||
The default `RestOperations` is configured as follows:
|
The default `RestOperations` is configured as follows:
|
||||||
|
@ -1226,7 +1226,7 @@ authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
|
||||||
`OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials()` configures a `ClientCredentialsOAuth2AuthorizedClientProvider`,
|
`OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials()` configures a `ClientCredentialsOAuth2AuthorizedClientProvider`,
|
||||||
which is an implementation of an `OAuth2AuthorizedClientProvider` for the Client Credentials grant.
|
which is an implementation of an `OAuth2AuthorizedClientProvider` for the Client Credentials grant.
|
||||||
|
|
||||||
===== Using the Access Token
|
==== Using the Access Token
|
||||||
|
|
||||||
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
||||||
|
|
||||||
|
@ -1361,13 +1361,13 @@ If not provided, it will default to `ServletRequestAttributes` using `RequestCon
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-password-grant]]
|
[[oauth2Client-password-grant]]
|
||||||
==== Resource Owner Password Credentials
|
=== Resource Owner Password Credentials
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to 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.
|
Please refer to 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
|
==== Requesting an Access Token
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to the https://tools.ietf.org/html/rfc6749#section-4.3.2[Access Token Request/Response] protocol flow for the Resource Owner Password Credentials grant.
|
Please refer to the https://tools.ietf.org/html/rfc6749#section-4.3.2[Access Token Request/Response] protocol flow for the Resource Owner Password Credentials grant.
|
||||||
|
@ -1377,7 +1377,7 @@ The default implementation of `OAuth2AccessTokenResponseClient` for the Resource
|
||||||
The `DefaultPasswordTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
The `DefaultPasswordTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
||||||
|
|
||||||
|
|
||||||
===== Customizing the Access Token Request
|
==== Customizing the Access Token Request
|
||||||
|
|
||||||
If you need to customize the pre-processing of the Token Request, you can provide `DefaultPasswordTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2PasswordGrantRequest, RequestEntity<?>>`.
|
If you need to customize the pre-processing of the Token Request, you can provide `DefaultPasswordTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2PasswordGrantRequest, RequestEntity<?>>`.
|
||||||
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].
|
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].
|
||||||
|
@ -1386,7 +1386,7 @@ However, providing a custom `Converter`, would allow you to extend the standard
|
||||||
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
|
==== Customizing the Access Token Response
|
||||||
|
|
||||||
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultPasswordTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultPasswordTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
||||||
The default `RestOperations` is configured as follows:
|
The default `RestOperations` is configured as follows:
|
||||||
|
@ -1461,7 +1461,7 @@ authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
|
||||||
`OAuth2AuthorizedClientProviderBuilder.builder().password()` configures a `PasswordOAuth2AuthorizedClientProvider`,
|
`OAuth2AuthorizedClientProviderBuilder.builder().password()` configures a `PasswordOAuth2AuthorizedClientProvider`,
|
||||||
which is an implementation of an `OAuth2AuthorizedClientProvider` for the Resource Owner Password Credentials grant.
|
which is an implementation of an `OAuth2AuthorizedClientProvider` for the Resource Owner Password Credentials grant.
|
||||||
|
|
||||||
===== Using the Access Token
|
==== Using the Access Token
|
||||||
|
|
||||||
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
||||||
|
|
||||||
|
@ -1639,13 +1639,13 @@ If not provided, it will default to `ServletRequestAttributes` using `RequestCon
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-jwt-bearer-grant]]
|
[[oauth2Client-jwt-bearer-grant]]
|
||||||
==== JWT Bearer
|
=== JWT Bearer
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants for further details on the https://datatracker.ietf.org/doc/html/rfc7523[JWT Bearer] grant.
|
Please refer to JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants for further details on the https://datatracker.ietf.org/doc/html/rfc7523[JWT Bearer] grant.
|
||||||
|
|
||||||
|
|
||||||
===== Requesting an Access Token
|
==== Requesting an Access Token
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to the https://datatracker.ietf.org/doc/html/rfc7523#section-2.1[Access Token Request/Response] protocol flow for the JWT Bearer grant.
|
Please refer to the https://datatracker.ietf.org/doc/html/rfc7523#section-2.1[Access Token Request/Response] protocol flow for the JWT Bearer grant.
|
||||||
|
@ -1655,14 +1655,14 @@ The default implementation of `OAuth2AccessTokenResponseClient` for the JWT Bear
|
||||||
The `DefaultJwtBearerTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
The `DefaultJwtBearerTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
|
||||||
|
|
||||||
|
|
||||||
===== Customizing the Access Token Request
|
==== Customizing the Access Token Request
|
||||||
|
|
||||||
If you need to customize the pre-processing of the Token Request, you can provide `DefaultJwtBearerTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<JwtBearerGrantRequest, RequestEntity<?>>`.
|
If you need to customize the pre-processing of the Token Request, you can provide `DefaultJwtBearerTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<JwtBearerGrantRequest, RequestEntity<?>>`.
|
||||||
The default implementation `JwtBearerGrantRequestEntityConverter` builds a `RequestEntity` representation of a https://datatracker.ietf.org/doc/html/rfc7523#section-2.1[OAuth 2.0 Access Token Request].
|
The default implementation `JwtBearerGrantRequestEntityConverter` builds a `RequestEntity` representation of a https://datatracker.ietf.org/doc/html/rfc7523#section-2.1[OAuth 2.0 Access Token Request].
|
||||||
However, providing a custom `Converter`, would allow you to extend the Token Request and add custom parameter(s).
|
However, providing a custom `Converter`, would allow you to extend the Token Request and add custom parameter(s).
|
||||||
|
|
||||||
|
|
||||||
===== Customizing the Access Token Response
|
==== Customizing the Access Token Response
|
||||||
|
|
||||||
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultJwtBearerTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultJwtBearerTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
|
||||||
The default `RestOperations` is configured as follows:
|
The default `RestOperations` is configured as follows:
|
||||||
|
@ -1738,7 +1738,7 @@ authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
===== Using the Access Token
|
==== Using the Access Token
|
||||||
|
|
||||||
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
||||||
|
|
||||||
|
@ -1857,11 +1857,11 @@ class OAuth2ResourceServerController {
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-client-auth-support]]
|
[[oauth2Client-client-auth-support]]
|
||||||
=== Client Authentication Support
|
== Client Authentication Support
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-jwt-bearer-auth]]
|
[[oauth2Client-jwt-bearer-auth]]
|
||||||
==== JWT Bearer
|
=== JWT Bearer
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
Please refer to JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants for further details on https://datatracker.ietf.org/doc/html/rfc7523#section-2.2[JWT Bearer] Client Authentication.
|
Please refer to JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants for further details on https://datatracker.ietf.org/doc/html/rfc7523#section-2.2[JWT Bearer] Client Authentication.
|
||||||
|
@ -1874,7 +1874,7 @@ The `java.security.PrivateKey` or `javax.crypto.SecretKey` used for signing the
|
||||||
is supplied by the `com.nimbusds.jose.jwk.JWK` resolver associated with `NimbusJwtClientAuthenticationParametersConverter`.
|
is supplied by the `com.nimbusds.jose.jwk.JWK` resolver associated with `NimbusJwtClientAuthenticationParametersConverter`.
|
||||||
|
|
||||||
|
|
||||||
===== Authenticate using `private_key_jwt`
|
==== Authenticate using `private_key_jwt`
|
||||||
|
|
||||||
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
||||||
|
|
||||||
|
@ -1949,7 +1949,7 @@ tokenResponseClient.setRequestEntityConverter(requestEntityConverter)
|
||||||
====
|
====
|
||||||
|
|
||||||
|
|
||||||
===== Authenticate using `client_secret_jwt`
|
==== Authenticate using `client_secret_jwt`
|
||||||
|
|
||||||
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
|
||||||
|
|
||||||
|
@ -2024,11 +2024,11 @@ tokenResponseClient.setRequestEntityConverter(requestEntityConverter)
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-additional-features]]
|
[[oauth2Client-additional-features]]
|
||||||
=== Additional Features
|
== Additional Features
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-registered-authorized-client]]
|
[[oauth2Client-registered-authorized-client]]
|
||||||
==== Resolving an Authorized Client
|
=== Resolving an Authorized Client
|
||||||
|
|
||||||
The `@RegisteredOAuth2AuthorizedClient` annotation provides the capability of resolving a method parameter to an argument value of type `OAuth2AuthorizedClient`.
|
The `@RegisteredOAuth2AuthorizedClient` annotation provides the capability of resolving a method parameter to an argument value of type `OAuth2AuthorizedClient`.
|
||||||
This is a convenient alternative compared to accessing the `OAuth2AuthorizedClient` using the `OAuth2AuthorizedClientManager` or `OAuth2AuthorizedClientService`.
|
This is a convenient alternative compared to accessing the `OAuth2AuthorizedClient` using the `OAuth2AuthorizedClientManager` or `OAuth2AuthorizedClientService`.
|
||||||
|
@ -2072,7 +2072,7 @@ The `@RegisteredOAuth2AuthorizedClient` annotation is handled by `OAuth2Authoriz
|
||||||
|
|
||||||
|
|
||||||
[[oauth2Client-webclient-servlet]]
|
[[oauth2Client-webclient-servlet]]
|
||||||
=== WebClient integration for Servlet Environments
|
== WebClient integration for Servlet Environments
|
||||||
|
|
||||||
The OAuth 2.0 Client support integrates with `WebClient` using an `ExchangeFilterFunction`.
|
The OAuth 2.0 Client support integrates with `WebClient` using an `ExchangeFilterFunction`.
|
||||||
|
|
||||||
|
@ -2114,7 +2114,7 @@ fun webClient(authorizedClientManager: OAuth2AuthorizedClientManager?): WebClien
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
==== Providing the Authorized Client
|
=== Providing the Authorized Client
|
||||||
|
|
||||||
The `ServletOAuth2AuthorizedClientExchangeFilterFunction` determines the client to use (for a request) by resolving the `OAuth2AuthorizedClient` from the `ClientRequest.attributes()` (request attributes).
|
The `ServletOAuth2AuthorizedClientExchangeFilterFunction` determines the client to use (for a request) by resolving the `OAuth2AuthorizedClient` from the `ClientRequest.attributes()` (request attributes).
|
||||||
|
|
||||||
|
@ -2213,7 +2213,7 @@ fun index(): String {
|
||||||
<1> `clientRegistrationId()` is a `static` method in `ServletOAuth2AuthorizedClientExchangeFilterFunction`.
|
<1> `clientRegistrationId()` is a `static` method in `ServletOAuth2AuthorizedClientExchangeFilterFunction`.
|
||||||
|
|
||||||
|
|
||||||
==== Defaulting the Authorized Client
|
=== Defaulting the Authorized Client
|
||||||
|
|
||||||
If neither `OAuth2AuthorizedClient` or `ClientRegistration.getRegistrationId()` is provided as a request attribute, the `ServletOAuth2AuthorizedClientExchangeFilterFunction` can determine the _default_ client to use depending on it's configuration.
|
If neither `OAuth2AuthorizedClient` or `ClientRegistration.getRegistrationId()` is provided as a request attribute, the `ServletOAuth2AuthorizedClientExchangeFilterFunction` can determine the _default_ client to use depending on it's configuration.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[[oauth2login]]
|
[[oauth2login]]
|
||||||
== OAuth 2.0 Login
|
= OAuth 2.0 Login
|
||||||
|
|
||||||
The OAuth 2.0 Login feature provides an application with the capability to have users log in to the application by using their existing account at an OAuth 2.0 Provider (e.g. GitHub) or OpenID Connect 1.0 Provider (such as Google).
|
The OAuth 2.0 Login feature provides an application with the capability to have users log in to the application by using their existing account at an OAuth 2.0 Provider (e.g. GitHub) or OpenID Connect 1.0 Provider (such as Google).
|
||||||
OAuth 2.0 Login implements the use cases: "Login with Google" or "Login with GitHub".
|
OAuth 2.0 Login implements the use cases: "Login with Google" or "Login with GitHub".
|
||||||
|
@ -8,7 +8,7 @@ NOTE: OAuth 2.0 Login is implemented by using the *Authorization Code Grant*, as
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-sample-boot]]
|
[[oauth2login-sample-boot]]
|
||||||
=== Spring Boot 2.x Sample
|
== Spring Boot 2.x Sample
|
||||||
|
|
||||||
Spring Boot 2.x brings full auto-configuration capabilities for OAuth 2.0 Login.
|
Spring Boot 2.x brings full auto-configuration capabilities for OAuth 2.0 Login.
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ This section shows how to configure the {gh-samples-url}/servlet/spring-boot/jav
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-sample-initial-setup]]
|
[[oauth2login-sample-initial-setup]]
|
||||||
==== Initial setup
|
=== Initial setup
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ After completing the "Obtain OAuth 2.0 credentials" instructions, you should hav
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-sample-redirect-uri]]
|
[[oauth2login-sample-redirect-uri]]
|
||||||
==== Setting the redirect URI
|
=== Setting the redirect URI
|
||||||
|
|
||||||
The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Google and have granted access to the OAuth Client _(<<oauth2login-sample-initial-setup,created in the previous step>>)_ on the Consent page.
|
The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Google and have granted access to the OAuth Client _(<<oauth2login-sample-initial-setup,created in the previous step>>)_ on the Consent page.
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ Also, see the supported <<oauth2Client-auth-code-redirect-uri, `URI` template va
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-sample-application-config]]
|
[[oauth2login-sample-application-config]]
|
||||||
==== Configure application.yml
|
=== Configure application.yml
|
||||||
|
|
||||||
Now that you have a new OAuth Client with Google, you need to configure the application to use the OAuth Client for the _authentication flow_.
|
Now that you have a new OAuth Client with Google, you need to configure the application to use the OAuth Client for the _authentication flow_.
|
||||||
To do so:
|
To do so:
|
||||||
|
@ -76,7 +76,7 @@ spring:
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-sample-boot-application]]
|
[[oauth2login-sample-boot-application]]
|
||||||
==== Boot up the application
|
=== Boot up the application
|
||||||
|
|
||||||
Launch the Spring Boot 2.x sample and go to `http://localhost:8080`.
|
Launch the Spring Boot 2.x sample and go to `http://localhost:8080`.
|
||||||
You are then redirected to the default _auto-generated_ login page, which displays a link for Google.
|
You are then redirected to the default _auto-generated_ login page, which displays a link for Google.
|
||||||
|
@ -91,7 +91,7 @@ At this point, the OAuth Client retrieves your email address and basic profile i
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-boot-property-mappings]]
|
[[oauth2login-boot-property-mappings]]
|
||||||
=== Spring Boot 2.x Property Mappings
|
== Spring Boot 2.x Property Mappings
|
||||||
|
|
||||||
The following table outlines the mapping of the Spring Boot 2.x OAuth Client properties to the <<oauth2Client-client-registration,ClientRegistration>> properties.
|
The following table outlines the mapping of the Spring Boot 2.x OAuth Client properties to the <<oauth2Client-client-registration,ClientRegistration>> properties.
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ A `ClientRegistration` can be initially configured using discovery of an OpenID
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-common-oauth2-provider]]
|
[[oauth2login-common-oauth2-provider]]
|
||||||
=== CommonOAuth2Provider
|
== CommonOAuth2Provider
|
||||||
|
|
||||||
`CommonOAuth2Provider` pre-defines a set of default client properties for a number of well known providers: Google, GitHub, Facebook, and Okta.
|
`CommonOAuth2Provider` pre-defines a set of default client properties for a number of well known providers: Google, GitHub, Facebook, and Okta.
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ spring:
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-custom-provider-properties]]
|
[[oauth2login-custom-provider-properties]]
|
||||||
=== Configuring Custom Provider Properties
|
== Configuring Custom Provider Properties
|
||||||
|
|
||||||
There are some OAuth 2.0 Providers that support multi-tenancy, which results in different protocol endpoints for each tenant (or sub-domain).
|
There are some OAuth 2.0 Providers that support multi-tenancy, which results in different protocol endpoints for each tenant (or sub-domain).
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ spring:
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-override-boot-autoconfig]]
|
[[oauth2login-override-boot-autoconfig]]
|
||||||
=== Overriding Spring Boot 2.x Auto-configuration
|
== Overriding Spring Boot 2.x Auto-configuration
|
||||||
|
|
||||||
The Spring Boot 2.x auto-configuration class for OAuth Client support is `OAuth2ClientAutoConfiguration`.
|
The Spring Boot 2.x auto-configuration class for OAuth Client support is `OAuth2ClientAutoConfiguration`.
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ If you need to override the auto-configuration based on your specific requiremen
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-register-clientregistrationrepository-bean]]
|
[[oauth2login-register-clientregistrationrepository-bean]]
|
||||||
==== Register a ClientRegistrationRepository @Bean
|
=== Register a ClientRegistrationRepository @Bean
|
||||||
|
|
||||||
The following example shows how to register a `ClientRegistrationRepository` `@Bean`:
|
The following example shows how to register a `ClientRegistrationRepository` `@Bean`:
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ class OAuth2LoginConfig {
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-provide-websecurityconfigureradapter]]
|
[[oauth2login-provide-websecurityconfigureradapter]]
|
||||||
==== Provide a WebSecurityConfigurerAdapter
|
=== Provide a WebSecurityConfigurerAdapter
|
||||||
|
|
||||||
The following example shows how to provide a `WebSecurityConfigurerAdapter` with `@EnableWebSecurity` and enable OAuth 2.0 login through `httpSecurity.oauth2Login()`:
|
The following example shows how to provide a `WebSecurityConfigurerAdapter` with `@EnableWebSecurity` and enable OAuth 2.0 login through `httpSecurity.oauth2Login()`:
|
||||||
|
|
||||||
|
@ -356,7 +356,7 @@ class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-completely-override-autoconfiguration]]
|
[[oauth2login-completely-override-autoconfiguration]]
|
||||||
==== Completely Override the Auto-configuration
|
=== Completely Override the Auto-configuration
|
||||||
|
|
||||||
The following example shows how to completely override the auto-configuration by registering a `ClientRegistrationRepository` `@Bean` and providing a `WebSecurityConfigurerAdapter`.
|
The following example shows how to completely override the auto-configuration by registering a `ClientRegistrationRepository` `@Bean` and providing a `WebSecurityConfigurerAdapter`.
|
||||||
|
|
||||||
|
@ -451,7 +451,7 @@ class OAuth2LoginConfig {
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-javaconfig-wo-boot]]
|
[[oauth2login-javaconfig-wo-boot]]
|
||||||
=== Java Configuration without Spring Boot 2.x
|
== Java Configuration without Spring Boot 2.x
|
||||||
|
|
||||||
If you are not able to use Spring Boot 2.x and would like to configure one of the pre-defined providers in `CommonOAuth2Provider` (for example, Google), apply the following configuration:
|
If you are not able to use Spring Boot 2.x and would like to configure one of the pre-defined providers in `CommonOAuth2Provider` (for example, Google), apply the following configuration:
|
||||||
|
|
||||||
|
@ -575,7 +575,7 @@ open class OAuth2LoginConfig {
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced]]
|
[[oauth2login-advanced]]
|
||||||
=== Advanced Configuration
|
== Advanced Configuration
|
||||||
|
|
||||||
`HttpSecurity.oauth2Login()` provides a number of configuration options for customizing OAuth 2.0 Login.
|
`HttpSecurity.oauth2Login()` provides a number of configuration options for customizing OAuth 2.0 Login.
|
||||||
The main configuration options are grouped into their protocol endpoint counterparts.
|
The main configuration options are grouped into their protocol endpoint counterparts.
|
||||||
|
@ -770,7 +770,7 @@ The following sections go into more detail on each of the configuration options
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced-login-page]]
|
[[oauth2login-advanced-login-page]]
|
||||||
==== OAuth 2.0 Login Page
|
=== OAuth 2.0 Login Page
|
||||||
|
|
||||||
By default, the OAuth 2.0 Login Page is auto-generated by the `DefaultLoginPageGeneratingFilter`.
|
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).
|
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).
|
||||||
|
@ -865,7 +865,7 @@ The following line shows an example:
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced-redirection-endpoint]]
|
[[oauth2login-advanced-redirection-endpoint]]
|
||||||
==== Redirection Endpoint
|
=== Redirection Endpoint
|
||||||
|
|
||||||
The Redirection Endpoint is used by the Authorization Server for returning the Authorization Response (which contains the authorization credentials) to the client via the Resource Owner user-agent.
|
The Redirection Endpoint is used by the Authorization Server for returning the Authorization Response (which contains the authorization credentials) to the client via the Resource Owner user-agent.
|
||||||
|
|
||||||
|
@ -956,7 +956,7 @@ return CommonOAuth2Provider.GOOGLE.getBuilder("google")
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced-userinfo-endpoint]]
|
[[oauth2login-advanced-userinfo-endpoint]]
|
||||||
==== UserInfo Endpoint
|
=== UserInfo Endpoint
|
||||||
|
|
||||||
The UserInfo Endpoint includes a number of configuration options, as described in the following sub-sections:
|
The UserInfo Endpoint includes a number of configuration options, as described in the following sub-sections:
|
||||||
|
|
||||||
|
@ -966,7 +966,7 @@ The UserInfo Endpoint includes a number of configuration options, as described i
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced-map-authorities]]
|
[[oauth2login-advanced-map-authorities]]
|
||||||
===== Mapping User Authorities
|
==== Mapping User Authorities
|
||||||
|
|
||||||
After the user successfully authenticates with the OAuth 2.0 Provider, the `OAuth2User.getAuthorities()` (or `OidcUser.getAuthorities()`) may be mapped to a new set of `GrantedAuthority` instances, which will be supplied to `OAuth2AuthenticationToken` when completing the authentication.
|
After the user successfully authenticates with the OAuth 2.0 Provider, the `OAuth2User.getAuthorities()` (or `OidcUser.getAuthorities()`) may be mapped to a new set of `GrantedAuthority` instances, which will be supplied to `OAuth2AuthenticationToken` when completing the authentication.
|
||||||
|
|
||||||
|
@ -980,7 +980,7 @@ There are a couple of options to choose from when mapping user authorities:
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced-map-authorities-grantedauthoritiesmapper]]
|
[[oauth2login-advanced-map-authorities-grantedauthoritiesmapper]]
|
||||||
====== Using a GrantedAuthoritiesMapper
|
===== Using a GrantedAuthoritiesMapper
|
||||||
|
|
||||||
Provide an implementation of `GrantedAuthoritiesMapper` and configure it as shown in the following example:
|
Provide an implementation of `GrantedAuthoritiesMapper` and configure it as shown in the following example:
|
||||||
|
|
||||||
|
@ -1126,7 +1126,7 @@ class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2login-advanced-map-authorities-oauth2userservice]]
|
[[oauth2login-advanced-map-authorities-oauth2userservice]]
|
||||||
====== Delegation-based strategy with OAuth2UserService
|
===== Delegation-based strategy with OAuth2UserService
|
||||||
|
|
||||||
This strategy is advanced compared to using a `GrantedAuthoritiesMapper`, however, it's also more flexible as it gives you access to the `OAuth2UserRequest` and `OAuth2User` (when using an OAuth 2.0 UserService) or `OidcUserRequest` and `OidcUser` (when using an OpenID Connect 1.0 UserService).
|
This strategy is advanced compared to using a `GrantedAuthoritiesMapper`, however, it's also more flexible as it gives you access to the `OAuth2UserRequest` and `OAuth2User` (when using an OAuth 2.0 UserService) or `OidcUserRequest` and `OidcUser` (when using an OpenID Connect 1.0 UserService).
|
||||||
|
|
||||||
|
@ -1228,7 +1228,7 @@ class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced-oauth2-user-service]]
|
[[oauth2login-advanced-oauth2-user-service]]
|
||||||
===== OAuth 2.0 UserService
|
==== OAuth 2.0 UserService
|
||||||
|
|
||||||
`DefaultOAuth2UserService` is an implementation of an `OAuth2UserService` that supports standard OAuth 2.0 Provider's.
|
`DefaultOAuth2UserService` is an implementation of an `OAuth2UserService` that supports standard OAuth 2.0 Provider's.
|
||||||
|
|
||||||
|
@ -1304,7 +1304,7 @@ class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced-oidc-user-service]]
|
[[oauth2login-advanced-oidc-user-service]]
|
||||||
===== OpenID Connect 1.0 UserService
|
==== OpenID Connect 1.0 UserService
|
||||||
|
|
||||||
`OidcUserService` is an implementation of an `OAuth2UserService` that supports OpenID Connect 1.0 Provider's.
|
`OidcUserService` is an implementation of an `OAuth2UserService` that supports OpenID Connect 1.0 Provider's.
|
||||||
|
|
||||||
|
@ -1364,7 +1364,7 @@ class OAuth2LoginSecurityConfig : WebSecurityConfigurerAdapter() {
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced-idtoken-verify]]
|
[[oauth2login-advanced-idtoken-verify]]
|
||||||
==== ID Token Signature Verification
|
=== ID Token Signature Verification
|
||||||
|
|
||||||
OpenID Connect 1.0 Authentication introduces the https://openid.net/specs/openid-connect-core-1_0.html#IDToken[ID Token], which is a security token that contains Claims about the Authentication of an End-User by an Authorization Server when used by a Client.
|
OpenID Connect 1.0 Authentication introduces the https://openid.net/specs/openid-connect-core-1_0.html#IDToken[ID Token], which is a security token that contains Claims about the Authentication of an End-User by an Authorization Server when used by a Client.
|
||||||
|
|
||||||
|
@ -1409,7 +1409,7 @@ If more than one `ClientRegistration` is configured for OpenID Connect 1.0 Authe
|
||||||
|
|
||||||
|
|
||||||
[[oauth2login-advanced-oidc-logout]]
|
[[oauth2login-advanced-oidc-logout]]
|
||||||
==== OpenID Connect 1.0 Logout
|
=== OpenID Connect 1.0 Logout
|
||||||
|
|
||||||
OpenID Connect Session Management 1.0 allows the ability to log out the End-User at the Provider using the Client.
|
OpenID Connect Session Management 1.0 allows the ability to log out the End-User at the Provider using the Client.
|
||||||
One of the strategies available is https://openid.net/specs/openid-connect-session-1_0.html#RPLogout[RP-Initiated Logout].
|
One of the strategies available is https://openid.net/specs/openid-connect-session-1_0.html#RPLogout[RP-Initiated Logout].
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[[oauth2resourceserver]]
|
[[oauth2resourceserver]]
|
||||||
== OAuth 2.0 Resource Server
|
= OAuth 2.0 Resource Server
|
||||||
:figures: images/servlet/oauth2
|
:figures: images/servlet/oauth2
|
||||||
:icondir: images/icons
|
:icondir: images/icons
|
||||||
|
|
||||||
|
@ -59,18 +59,18 @@ image:{icondir}/number_4.png[] If authentication is successful, then __Success__
|
||||||
* The `BearerTokenAuthenticationFilter` invokes `FilterChain.doFilter(request,response)` to continue with the rest of the application logic.
|
* The `BearerTokenAuthenticationFilter` invokes `FilterChain.doFilter(request,response)` to continue with the rest of the application logic.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-minimaldependencies]]
|
[[oauth2resourceserver-jwt-minimaldependencies]]
|
||||||
=== Minimal Dependencies for JWT
|
== Minimal Dependencies for JWT
|
||||||
|
|
||||||
Most Resource Server support is collected into `spring-security-oauth2-resource-server`.
|
Most Resource Server support is collected into `spring-security-oauth2-resource-server`.
|
||||||
However, the support for decoding and verifying JWTs is in `spring-security-oauth2-jose`, meaning that both are necessary in order to have a working resource server that supports JWT-encoded Bearer Tokens.
|
However, the support for decoding and verifying JWTs is in `spring-security-oauth2-jose`, meaning that both are necessary in order to have a working resource server that supports JWT-encoded Bearer Tokens.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-minimalconfiguration]]
|
[[oauth2resourceserver-jwt-minimalconfiguration]]
|
||||||
=== Minimal Configuration for JWTs
|
== Minimal Configuration for JWTs
|
||||||
|
|
||||||
When using https://spring.io/projects/spring-boot[Spring Boot], configuring an application as a resource server consists of two basic steps.
|
When using https://spring.io/projects/spring-boot[Spring Boot], configuring an application as a resource server consists of two basic steps.
|
||||||
First, include the needed dependencies and second, indicate the location of the authorization server.
|
First, include the needed dependencies and second, indicate the location of the authorization server.
|
||||||
|
|
||||||
==== Specifying the Authorization Server
|
=== Specifying the Authorization Server
|
||||||
|
|
||||||
In a Spring Boot application, to specify which authorization server to use, simply do:
|
In a Spring Boot application, to specify which authorization server to use, simply do:
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ This endpoint is referred to as a https://openid.net/specs/openid-connect-discov
|
||||||
|
|
||||||
And that's it!
|
And that's it!
|
||||||
|
|
||||||
==== Startup Expectations
|
=== Startup Expectations
|
||||||
|
|
||||||
When this property and these dependencies are used, Resource Server will automatically configure itself to validate JWT-encoded Bearer Tokens.
|
When this property and these dependencies are used, Resource Server will automatically configure itself to validate JWT-encoded Bearer Tokens.
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ A consequence of this process is that the authorization server must be up and re
|
||||||
[NOTE]
|
[NOTE]
|
||||||
If the authorization server is down when Resource Server queries it (given appropriate timeouts), then startup will fail.
|
If the authorization server is down when Resource Server queries it (given appropriate timeouts), then startup will fail.
|
||||||
|
|
||||||
==== Runtime Expectations
|
=== Runtime Expectations
|
||||||
|
|
||||||
Once the application is started up, Resource Server will attempt to process any request containing an `Authorization: Bearer` header:
|
Once the application is started up, Resource Server will attempt to process any request containing an `Authorization: Bearer` header:
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ From here, consider jumping to:
|
||||||
* <<oauth2resourceserver-jwt-sansboot,How to Configure without Spring Boot>>
|
* <<oauth2resourceserver-jwt-sansboot,How to Configure without Spring Boot>>
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-architecture]]
|
[[oauth2resourceserver-jwt-architecture]]
|
||||||
=== How JWT Authentication Works
|
== How JWT Authentication Works
|
||||||
|
|
||||||
Next, let's see the architectural components that Spring Security uses to support https://tools.ietf.org/html/rfc7519[JWT] Authentication in servlet-based applications, like the one we just saw.
|
Next, let's see the architectural components that Spring Security uses to support https://tools.ietf.org/html/rfc7519[JWT] Authentication in servlet-based applications, like the one we just saw.
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ image:{icondir}/number_5.png[] When authentication is successful, the <<servlet-
|
||||||
Ultimately, the returned `JwtAuthenticationToken` will be set on the <<servlet-authentication-securitycontextholder,`SecurityContextHolder`>> by the authentication `Filter`.
|
Ultimately, the returned `JwtAuthenticationToken` will be set on the <<servlet-authentication-securitycontextholder,`SecurityContextHolder`>> by the authentication `Filter`.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-jwkseturi]]
|
[[oauth2resourceserver-jwt-jwkseturi]]
|
||||||
=== Specifying the Authorization Server JWK Set Uri Directly
|
== Specifying the Authorization Server JWK Set Uri Directly
|
||||||
|
|
||||||
If the authorization server doesn't support any configuration endpoints, or if Resource Server must be able to start up independently from the authorization server, then the `jwk-set-uri` can be supplied as well:
|
If the authorization server doesn't support any configuration endpoints, or if Resource Server must be able to start up independently from the authorization server, then the `jwk-set-uri` can be supplied as well:
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ We still specify the `issuer-uri` so that Resource Server still validates the `i
|
||||||
This property can also be supplied directly on the <<oauth2resourceserver-jwt-jwkseturi-dsl,DSL>>.
|
This property can also be supplied directly on the <<oauth2resourceserver-jwt-jwkseturi-dsl,DSL>>.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-sansboot]]
|
[[oauth2resourceserver-jwt-sansboot]]
|
||||||
=== Overriding or Replacing Boot Auto Configuration
|
== Overriding or Replacing Boot Auto Configuration
|
||||||
|
|
||||||
There are two ``@Bean``s that Spring Boot generates on Resource Server's behalf.
|
There are two ``@Bean``s that Spring Boot generates on Resource Server's behalf.
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ And the `JwtDecoder` like so:
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-jwkseturi-dsl]]
|
[[oauth2resourceserver-jwt-jwkseturi-dsl]]
|
||||||
==== Using `jwkSetUri()`
|
=== Using `jwkSetUri()`
|
||||||
|
|
||||||
An authorization server's JWK Set Uri can be configured <<oauth2resourceserver-jwt-jwkseturi,as a configuration property>> or it can be supplied in the DSL:
|
An authorization server's JWK Set Uri can be configured <<oauth2resourceserver-jwt-jwkseturi,as a configuration property>> or it can be supplied in the DSL:
|
||||||
|
|
||||||
|
@ -403,7 +403,7 @@ class DirectlyConfiguredJwkSetUri : WebSecurityConfigurerAdapter() {
|
||||||
Using `jwkSetUri()` takes precedence over any configuration property.
|
Using `jwkSetUri()` takes precedence over any configuration property.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-decoder-dsl]]
|
[[oauth2resourceserver-jwt-decoder-dsl]]
|
||||||
==== Using `decoder()`
|
=== Using `decoder()`
|
||||||
|
|
||||||
More powerful than `jwkSetUri()` is `decoder()`, which will completely replace any Boot auto configuration of <<oauth2resourceserver-jwt-architecture-jwtdecoder,`JwtDecoder`>>:
|
More powerful than `jwkSetUri()` is `decoder()`, which will completely replace any Boot auto configuration of <<oauth2resourceserver-jwt-architecture-jwtdecoder,`JwtDecoder`>>:
|
||||||
|
|
||||||
|
@ -463,7 +463,7 @@ class DirectlyConfiguredJwtDecoder : WebSecurityConfigurerAdapter() {
|
||||||
This is handy when deeper configuration, like <<oauth2resourceserver-jwt-validation,validation>>, <<oauth2resourceserver-jwt-claimsetmapping,mapping>>, or <<oauth2resourceserver-jwt-timeouts,request timeouts>>, is necessary.
|
This is handy when deeper configuration, like <<oauth2resourceserver-jwt-validation,validation>>, <<oauth2resourceserver-jwt-claimsetmapping,mapping>>, or <<oauth2resourceserver-jwt-timeouts,request timeouts>>, is necessary.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-decoder-bean]]
|
[[oauth2resourceserver-jwt-decoder-bean]]
|
||||||
==== Exposing a `JwtDecoder` `@Bean`
|
=== Exposing a `JwtDecoder` `@Bean`
|
||||||
|
|
||||||
Or, exposing a <<oauth2resourceserver-jwt-architecture-jwtdecoder,`JwtDecoder`>> `@Bean` has the same effect as `decoder()`:
|
Or, exposing a <<oauth2resourceserver-jwt-architecture-jwtdecoder,`JwtDecoder`>> `@Bean` has the same effect as `decoder()`:
|
||||||
|
|
||||||
|
@ -488,14 +488,14 @@ fun jwtDecoder(): JwtDecoder {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-decoder-algorithm]]
|
[[oauth2resourceserver-jwt-decoder-algorithm]]
|
||||||
=== Configuring Trusted Algorithms
|
== Configuring Trusted Algorithms
|
||||||
|
|
||||||
By default, `NimbusJwtDecoder`, and hence Resource Server, will only trust and verify tokens using `RS256`.
|
By default, `NimbusJwtDecoder`, and hence Resource Server, will only trust and verify tokens using `RS256`.
|
||||||
|
|
||||||
You can customize this via <<oauth2resourceserver-jwt-boot-algorithm,Spring Boot>>, <<oauth2resourceserver-jwt-decoder-builder,the NimbusJwtDecoder builder>>, or from the <<oauth2resourceserver-jwt-decoder-jwk-response,JWK Set response>>.
|
You can customize this via <<oauth2resourceserver-jwt-boot-algorithm,Spring Boot>>, <<oauth2resourceserver-jwt-decoder-builder,the NimbusJwtDecoder builder>>, or from the <<oauth2resourceserver-jwt-decoder-jwk-response,JWK Set response>>.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-boot-algorithm]]
|
[[oauth2resourceserver-jwt-boot-algorithm]]
|
||||||
==== Via Spring Boot
|
=== Via Spring Boot
|
||||||
|
|
||||||
The simplest way to set the algorithm is as a property:
|
The simplest way to set the algorithm is as a property:
|
||||||
|
|
||||||
|
@ -511,7 +511,7 @@ spring:
|
||||||
----
|
----
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-decoder-builder]]
|
[[oauth2resourceserver-jwt-decoder-builder]]
|
||||||
==== Using a Builder
|
=== Using a Builder
|
||||||
|
|
||||||
For greater power, though, we can use a builder that ships with `NimbusJwtDecoder`:
|
For greater power, though, we can use a builder that ships with `NimbusJwtDecoder`:
|
||||||
|
|
||||||
|
@ -592,7 +592,7 @@ fun jwtDecoder(): JwtDecoder {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-decoder-jwk-response]]
|
[[oauth2resourceserver-jwt-decoder-jwk-response]]
|
||||||
==== From JWK Set response
|
=== From JWK Set response
|
||||||
|
|
||||||
Since Spring Security's JWT support is based off of Nimbus, you can use all it's great features as well.
|
Since Spring Security's JWT support is based off of Nimbus, you can use all it's great features as well.
|
||||||
|
|
||||||
|
@ -632,13 +632,13 @@ fun jwtDecoder(): JwtDecoder {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-decoder-public-key]]
|
[[oauth2resourceserver-jwt-decoder-public-key]]
|
||||||
=== Trusting a Single Asymmetric Key
|
== Trusting a Single Asymmetric Key
|
||||||
|
|
||||||
Simpler than backing a Resource Server with a JWK Set endpoint is to hard-code an RSA public key.
|
Simpler than backing a Resource Server with a JWK Set endpoint is to hard-code an RSA public key.
|
||||||
The public key can be provided via <<oauth2resourceserver-jwt-decoder-public-key-boot,Spring Boot>> or by <<oauth2resourceserver-jwt-decoder-public-key-builder,Using a Builder>>.
|
The public key can be provided via <<oauth2resourceserver-jwt-decoder-public-key-boot,Spring Boot>> or by <<oauth2resourceserver-jwt-decoder-public-key-builder,Using a Builder>>.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-decoder-public-key-boot]]
|
[[oauth2resourceserver-jwt-decoder-public-key-boot]]
|
||||||
==== Via Spring Boot
|
=== Via Spring Boot
|
||||||
|
|
||||||
Specifying a key via Spring Boot is quite simple.
|
Specifying a key via Spring Boot is quite simple.
|
||||||
The key's location can be specified like so:
|
The key's location can be specified like so:
|
||||||
|
@ -705,7 +705,7 @@ val key: RSAPublicKey? = null
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-decoder-public-key-builder]]
|
[[oauth2resourceserver-jwt-decoder-public-key-builder]]
|
||||||
==== Using a Builder
|
=== Using a Builder
|
||||||
|
|
||||||
To wire an `RSAPublicKey` directly, you can simply use the appropriate `NimbusJwtDecoder` builder, like so:
|
To wire an `RSAPublicKey` directly, you can simply use the appropriate `NimbusJwtDecoder` builder, like so:
|
||||||
|
|
||||||
|
@ -730,7 +730,7 @@ fun jwtDecoder(): JwtDecoder {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-decoder-secret-key]]
|
[[oauth2resourceserver-jwt-decoder-secret-key]]
|
||||||
=== Trusting a Single Symmetric Key
|
== Trusting a Single Symmetric Key
|
||||||
|
|
||||||
Using a single symmetric key is also simple.
|
Using a single symmetric key is also simple.
|
||||||
You can simply load in your `SecretKey` and use the appropriate `NimbusJwtDecoder` builder, like so:
|
You can simply load in your `SecretKey` and use the appropriate `NimbusJwtDecoder` builder, like so:
|
||||||
|
@ -756,7 +756,7 @@ fun jwtDecoder(): JwtDecoder {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-authorization]]
|
[[oauth2resourceserver-jwt-authorization]]
|
||||||
=== Configuring Authorization
|
== Configuring Authorization
|
||||||
|
|
||||||
A JWT that is issued from an OAuth 2.0 Authorization Server will typically either have a `scope` or `scp` attribute, indicating the scopes (or authorities) it's been granted, for example:
|
A JWT that is issued from an OAuth 2.0 Authorization Server will typically either have a `scope` or `scp` attribute, indicating the scopes (or authorities) it's been granted, for example:
|
||||||
|
|
||||||
|
@ -837,7 +837,7 @@ fun getMessages(): List<Message> { }
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-authorization-extraction]]
|
[[oauth2resourceserver-jwt-authorization-extraction]]
|
||||||
==== Extracting Authorities Manually
|
=== Extracting Authorities Manually
|
||||||
|
|
||||||
However, there are a number of circumstances where this default is insufficient.
|
However, there are a number of circumstances where this default is insufficient.
|
||||||
For example, some authorization servers don't use the `scope` attribute, but instead have their own custom attribute.
|
For example, some authorization servers don't use the `scope` attribute, but instead have their own custom attribute.
|
||||||
|
@ -1024,14 +1024,14 @@ class CustomAuthenticationConverterConfig : WebSecurityConfigurerAdapter() {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-validation]]
|
[[oauth2resourceserver-jwt-validation]]
|
||||||
=== Configuring Validation
|
== Configuring Validation
|
||||||
|
|
||||||
Using <<oauth2resourceserver-jwt-minimalconfiguration,minimal Spring Boot configuration>>, indicating the authorization server's issuer uri, Resource Server will default to verifying the `iss` claim as well as the `exp` and `nbf` timestamp claims.
|
Using <<oauth2resourceserver-jwt-minimalconfiguration,minimal Spring Boot configuration>>, indicating the authorization server's issuer uri, Resource Server will default to verifying the `iss` claim as well as the `exp` and `nbf` timestamp claims.
|
||||||
|
|
||||||
In circumstances where validation needs to be customized, Resource Server ships with two standard validators and also accepts custom `OAuth2TokenValidator` instances.
|
In circumstances where validation needs to be customized, Resource Server ships with two standard validators and also accepts custom `OAuth2TokenValidator` instances.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-validation-clockskew]]
|
[[oauth2resourceserver-jwt-validation-clockskew]]
|
||||||
==== Customizing Timestamp Validation
|
=== Customizing Timestamp Validation
|
||||||
|
|
||||||
JWT's typically have a window of validity, with the start of the window indicated in the `nbf` claim and the end indicated in the `exp` claim.
|
JWT's typically have a window of validity, with the start of the window indicated in the `nbf` claim and the end indicated in the `exp` claim.
|
||||||
|
|
||||||
|
@ -1081,7 +1081,7 @@ fun jwtDecoder(): JwtDecoder {
|
||||||
By default, Resource Server configures a clock skew of 60 seconds.
|
By default, Resource Server configures a clock skew of 60 seconds.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-validation-custom]]
|
[[oauth2resourceserver-jwt-validation-custom]]
|
||||||
==== Configuring a Custom Validator
|
=== Configuring a Custom Validator
|
||||||
|
|
||||||
Adding a check for the `aud` claim is simple with the `OAuth2TokenValidator` API:
|
Adding a check for the `aud` claim is simple with the `OAuth2TokenValidator` API:
|
||||||
|
|
||||||
|
@ -1192,7 +1192,7 @@ fun jwtDecoder(): JwtDecoder {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-claimsetmapping]]
|
[[oauth2resourceserver-jwt-claimsetmapping]]
|
||||||
=== Configuring Claim Set Mapping
|
== Configuring Claim Set Mapping
|
||||||
|
|
||||||
Spring Security uses the https://bitbucket.org/connect2id/nimbus-jose-jwt/wiki/Home[Nimbus] library for parsing JWTs and validating their signatures.
|
Spring Security uses the https://bitbucket.org/connect2id/nimbus-jose-jwt/wiki/Home[Nimbus] library for parsing JWTs and validating their signatures.
|
||||||
Consequently, Spring Security is subject to Nimbus's interpretation of each field value and how to coerce each into a Java type.
|
Consequently, Spring Security is subject to Nimbus's interpretation of each field value and how to coerce each into a Java type.
|
||||||
|
@ -1206,7 +1206,7 @@ Or, quite simply, a resource server may want to add or remove claims from a JWT
|
||||||
For these purposes, Resource Server supports mapping the JWT claim set with `MappedJwtClaimSetConverter`.
|
For these purposes, Resource Server supports mapping the JWT claim set with `MappedJwtClaimSetConverter`.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-claimsetmapping-singleclaim]]
|
[[oauth2resourceserver-jwt-claimsetmapping-singleclaim]]
|
||||||
==== Customizing the Conversion of a Single Claim
|
=== Customizing the Conversion of a Single Claim
|
||||||
|
|
||||||
By default, `MappedJwtClaimSetConverter` will attempt to coerce claims into the following types:
|
By default, `MappedJwtClaimSetConverter` will attempt to coerce claims into the following types:
|
||||||
|
|
||||||
|
@ -1257,7 +1257,7 @@ fun jwtDecoder(): JwtDecoder {
|
||||||
This will keep all the defaults, except it will override the default claim converter for `sub`.
|
This will keep all the defaults, except it will override the default claim converter for `sub`.
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-claimsetmapping-add]]
|
[[oauth2resourceserver-jwt-claimsetmapping-add]]
|
||||||
==== Adding a Claim
|
=== Adding a Claim
|
||||||
|
|
||||||
`MappedJwtClaimSetConverter` can also be used to add a custom claim, for example, to adapt to an existing system:
|
`MappedJwtClaimSetConverter` can also be used to add a custom claim, for example, to adapt to an existing system:
|
||||||
|
|
||||||
|
@ -1276,7 +1276,7 @@ MappedJwtClaimSetConverter.withDefaults(mapOf("custom" to Converter<Any, String>
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-claimsetmapping-remove]]
|
[[oauth2resourceserver-jwt-claimsetmapping-remove]]
|
||||||
==== Removing a Claim
|
=== Removing a Claim
|
||||||
|
|
||||||
And removing a claim is also simple, using the same API:
|
And removing a claim is also simple, using the same API:
|
||||||
|
|
||||||
|
@ -1295,7 +1295,7 @@ MappedJwtClaimSetConverter.withDefaults(mapOf("legacyclaim" to Converter<Any, An
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-claimsetmapping-rename]]
|
[[oauth2resourceserver-jwt-claimsetmapping-rename]]
|
||||||
==== Renaming a Claim
|
=== Renaming a Claim
|
||||||
|
|
||||||
In more sophisticated scenarios, like consulting multiple claims at once or renaming a claim, Resource Server accepts any class that implements `Converter<Map<String, Object>, Map<String,Object>>`:
|
In more sophisticated scenarios, like consulting multiple claims at once or renaming a claim, Resource Server accepts any class that implements `Converter<Map<String, Object>, Map<String,Object>>`:
|
||||||
|
|
||||||
|
@ -1360,7 +1360,7 @@ fun jwtDecoder(): JwtDecoder {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-jwt-timeouts]]
|
[[oauth2resourceserver-jwt-timeouts]]
|
||||||
=== Configuring Timeouts
|
== Configuring Timeouts
|
||||||
|
|
||||||
By default, Resource Server uses connection and socket timeouts of 30 seconds each for coordinating with the authorization server.
|
By default, Resource Server uses connection and socket timeouts of 30 seconds each for coordinating with the authorization server.
|
||||||
|
|
||||||
|
@ -1436,14 +1436,14 @@ NOTE: Whether it's socket or cache timeouts, you may instead want to work with N
|
||||||
To do so, remember that `NimbusJwtDecoder` ships with a constructor that takes Nimbus's `JWTProcessor`.
|
To do so, remember that `NimbusJwtDecoder` ships with a constructor that takes Nimbus's `JWTProcessor`.
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-minimaldependencies]]
|
[[oauth2resourceserver-opaque-minimaldependencies]]
|
||||||
=== Minimal Dependencies for Introspection
|
== Minimal Dependencies for Introspection
|
||||||
As described in <<oauth2resourceserver-jwt-minimaldependencies,Minimal Dependencies for JWT>> most of Resource Server support is collected in `spring-security-oauth2-resource-server`.
|
As described in <<oauth2resourceserver-jwt-minimaldependencies,Minimal Dependencies for JWT>> most of Resource Server support is collected in `spring-security-oauth2-resource-server`.
|
||||||
However unless a custom <<oauth2resourceserver-opaque-introspector,`OpaqueTokenIntrospector`>> is provided, the Resource Server will fallback to NimbusOpaqueTokenIntrospector.
|
However unless a custom <<oauth2resourceserver-opaque-introspector,`OpaqueTokenIntrospector`>> is provided, the Resource Server will fallback to NimbusOpaqueTokenIntrospector.
|
||||||
Meaning that both `spring-security-oauth2-resource-server` and `oauth2-oidc-sdk` are necessary in order to have a working minimal Resource Server that supports opaque Bearer Tokens.
|
Meaning that both `spring-security-oauth2-resource-server` and `oauth2-oidc-sdk` are necessary in order to have a working minimal Resource Server that supports opaque Bearer Tokens.
|
||||||
Please refer to `spring-security-oauth2-resource-server` in order to determin the correct version for `oauth2-oidc-sdk`.
|
Please refer to `spring-security-oauth2-resource-server` in order to determin the correct version for `oauth2-oidc-sdk`.
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-minimalconfiguration]]
|
[[oauth2resourceserver-opaque-minimalconfiguration]]
|
||||||
=== Minimal Configuration for Introspection
|
== Minimal Configuration for Introspection
|
||||||
|
|
||||||
Typically, an opaque token can be verified via an https://tools.ietf.org/html/rfc7662[OAuth 2.0 Introspection Endpoint], hosted by the authorization server.
|
Typically, an opaque token can be verified via an https://tools.ietf.org/html/rfc7662[OAuth 2.0 Introspection Endpoint], hosted by the authorization server.
|
||||||
This can be handy when revocation is a requirement.
|
This can be handy when revocation is a requirement.
|
||||||
|
@ -1452,7 +1452,7 @@ When using https://spring.io/projects/spring-boot[Spring Boot], configuring an a
|
||||||
First, include the needed dependencies and second, indicate the introspection endpoint details.
|
First, include the needed dependencies and second, indicate the introspection endpoint details.
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-introspectionuri]]
|
[[oauth2resourceserver-opaque-introspectionuri]]
|
||||||
==== Specifying the Authorization Server
|
=== Specifying the Authorization Server
|
||||||
|
|
||||||
To specify where the introspection endpoint is, simply do:
|
To specify where the introspection endpoint is, simply do:
|
||||||
|
|
||||||
|
@ -1477,13 +1477,13 @@ If the authorization server responses that the token is valid, then it is.
|
||||||
|
|
||||||
And that's it!
|
And that's it!
|
||||||
|
|
||||||
==== Startup Expectations
|
=== Startup Expectations
|
||||||
|
|
||||||
When this property and these dependencies are used, Resource Server will automatically configure itself to validate Opaque Bearer Tokens.
|
When this property and these dependencies are used, Resource Server will automatically configure itself to validate Opaque Bearer Tokens.
|
||||||
|
|
||||||
This startup process is quite a bit simpler than for JWTs since no endpoints need to be discovered and no additional validation rules get added.
|
This startup process is quite a bit simpler than for JWTs since no endpoints need to be discovered and no additional validation rules get added.
|
||||||
|
|
||||||
==== Runtime Expectations
|
=== Runtime Expectations
|
||||||
|
|
||||||
Once the application is started up, Resource Server will attempt to process any request containing an `Authorization: Bearer` header:
|
Once the application is started up, Resource Server will attempt to process any request containing an `Authorization: Bearer` header:
|
||||||
|
|
||||||
|
@ -1510,7 +1510,7 @@ From here, you may want to jump to:
|
||||||
* <<oauth2resourceserver-opaque-jwt-introspector,Using Introspection with JWTs>>
|
* <<oauth2resourceserver-opaque-jwt-introspector,Using Introspection with JWTs>>
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-architecture]]
|
[[oauth2resourceserver-opaque-architecture]]
|
||||||
=== How Opaque Token Authentication Works
|
== How Opaque Token Authentication Works
|
||||||
|
|
||||||
Next, let's see the architectural components that Spring Security uses to support https://tools.ietf.org/html/rfc7662[opaque token] Authentication in servlet-based applications, like the one we just saw.
|
Next, let's see the architectural components that Spring Security uses to support https://tools.ietf.org/html/rfc7662[opaque token] Authentication in servlet-based applications, like the one we just saw.
|
||||||
|
|
||||||
|
@ -1532,7 +1532,7 @@ When authentication is successful, the <<servlet-authentication-authentication,`
|
||||||
Ultimately, the returned `BearerTokenAuthentication` will be set on the <<servlet-authentication-securitycontextholder,`SecurityContextHolder`>> by the authentication `Filter`.
|
Ultimately, the returned `BearerTokenAuthentication` will be set on the <<servlet-authentication-securitycontextholder,`SecurityContextHolder`>> by the authentication `Filter`.
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-attributes]]
|
[[oauth2resourceserver-opaque-attributes]]
|
||||||
=== Looking Up Attributes Post-Authentication
|
== Looking Up Attributes Post-Authentication
|
||||||
|
|
||||||
Once a token is authenticated, an instance of `BearerTokenAuthentication` is set in the `SecurityContext`.
|
Once a token is authenticated, an instance of `BearerTokenAuthentication` is set in the `SecurityContext`.
|
||||||
|
|
||||||
|
@ -1580,7 +1580,7 @@ fun foo(@AuthenticationPrincipal principal: OAuth2AuthenticatedPrincipal): Strin
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
==== Looking Up Attributes Via SpEL
|
=== Looking Up Attributes Via SpEL
|
||||||
|
|
||||||
Of course, this also means that attributes can be accessed via SpEL.
|
Of course, this also means that attributes can be accessed via SpEL.
|
||||||
|
|
||||||
|
@ -1607,7 +1607,7 @@ fun forFoosEyesOnly(): String {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-sansboot]]
|
[[oauth2resourceserver-opaque-sansboot]]
|
||||||
=== Overriding or Replacing Boot Auto Configuration
|
== Overriding or Replacing Boot Auto Configuration
|
||||||
|
|
||||||
There are two ``@Bean``s that Spring Boot generates on Resource Server's behalf.
|
There are two ``@Bean``s that Spring Boot generates on Resource Server's behalf.
|
||||||
|
|
||||||
|
@ -1758,7 +1758,7 @@ And the <<oauth2resourceserver-opaque-architecture-introspector,`OpaqueTokenIntr
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-introspectionuri-dsl]]
|
[[oauth2resourceserver-opaque-introspectionuri-dsl]]
|
||||||
==== Using `introspectionUri()`
|
=== Using `introspectionUri()`
|
||||||
|
|
||||||
An authorization server's Introspection Uri can be configured <<oauth2resourceserver-opaque-introspectionuri,as a configuration property>> or it can be supplied in the DSL:
|
An authorization server's Introspection Uri can be configured <<oauth2resourceserver-opaque-introspectionuri,as a configuration property>> or it can be supplied in the DSL:
|
||||||
|
|
||||||
|
@ -1820,7 +1820,7 @@ class DirectlyConfiguredIntrospectionUri : WebSecurityConfigurerAdapter() {
|
||||||
Using `introspectionUri()` takes precedence over any configuration property.
|
Using `introspectionUri()` takes precedence over any configuration property.
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-introspector-dsl]]
|
[[oauth2resourceserver-opaque-introspector-dsl]]
|
||||||
==== Using `introspector()`
|
=== Using `introspector()`
|
||||||
|
|
||||||
More powerful than `introspectionUri()` is `introspector()`, which will completely replace any Boot auto configuration of <<oauth2resourceserver-opaque-architecture-introspector,`OpaqueTokenIntrospector`>>:
|
More powerful than `introspectionUri()` is `introspector()`, which will completely replace any Boot auto configuration of <<oauth2resourceserver-opaque-architecture-introspector,`OpaqueTokenIntrospector`>>:
|
||||||
|
|
||||||
|
@ -1880,7 +1880,7 @@ class DirectlyConfiguredIntrospector : WebSecurityConfigurerAdapter() {
|
||||||
This is handy when deeper configuration, like <<oauth2resourceserver-opaque-authorization-extraction,authority mapping>>, <<oauth2resourceserver-opaque-jwt-introspector,JWT revocation>>, or <<oauth2resourceserver-opaque-timeouts,request timeouts>>, is necessary.
|
This is handy when deeper configuration, like <<oauth2resourceserver-opaque-authorization-extraction,authority mapping>>, <<oauth2resourceserver-opaque-jwt-introspector,JWT revocation>>, or <<oauth2resourceserver-opaque-timeouts,request timeouts>>, is necessary.
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-introspector-bean]]
|
[[oauth2resourceserver-opaque-introspector-bean]]
|
||||||
==== Exposing a `OpaqueTokenIntrospector` `@Bean`
|
=== Exposing a `OpaqueTokenIntrospector` `@Bean`
|
||||||
|
|
||||||
Or, exposing a <<oauth2resourceserver-opaque-architecture-introspector,`OpaqueTokenIntrospector`>> `@Bean` has the same effect as `introspector()`:
|
Or, exposing a <<oauth2resourceserver-opaque-architecture-introspector,`OpaqueTokenIntrospector`>> `@Bean` has the same effect as `introspector()`:
|
||||||
|
|
||||||
|
@ -1893,7 +1893,7 @@ public OpaqueTokenIntrospector introspector() {
|
||||||
----
|
----
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-authorization]]
|
[[oauth2resourceserver-opaque-authorization]]
|
||||||
=== Configuring Authorization
|
== Configuring Authorization
|
||||||
|
|
||||||
An OAuth 2.0 Introspection endpoint will typically return a `scope` attribute, indicating the scopes (or authorities) it's been granted, for example:
|
An OAuth 2.0 Introspection endpoint will typically return a `scope` attribute, indicating the scopes (or authorities) it's been granted, for example:
|
||||||
|
|
||||||
|
@ -1974,7 +1974,7 @@ fun getMessages(): List<Message?> {}
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-authorization-extraction]]
|
[[oauth2resourceserver-opaque-authorization-extraction]]
|
||||||
==== Extracting Authorities Manually
|
=== Extracting Authorities Manually
|
||||||
|
|
||||||
By default, Opaque Token support will extract the scope claim from an introspection response and parse it into individual `GrantedAuthority` instances.
|
By default, Opaque Token support will extract the scope claim from an introspection response and parse it into individual `GrantedAuthority` instances.
|
||||||
|
|
||||||
|
@ -2058,7 +2058,7 @@ fun introspector(): OpaqueTokenIntrospector {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-timeouts]]
|
[[oauth2resourceserver-opaque-timeouts]]
|
||||||
=== Configuring Timeouts
|
== Configuring Timeouts
|
||||||
|
|
||||||
By default, Resource Server uses connection and socket timeouts of 30 seconds each for coordinating with the authorization server.
|
By default, Resource Server uses connection and socket timeouts of 30 seconds each for coordinating with the authorization server.
|
||||||
|
|
||||||
|
@ -2099,7 +2099,7 @@ fun introspector(builder: RestTemplateBuilder, properties: OAuth2ResourceServerP
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-jwt-introspector]]
|
[[oauth2resourceserver-opaque-jwt-introspector]]
|
||||||
=== Using Introspection with JWTs
|
== Using Introspection with JWTs
|
||||||
|
|
||||||
A common question is whether or not introspection is compatible with JWTs.
|
A common question is whether or not introspection is compatible with JWTs.
|
||||||
Spring Security's Opaque Token support has been designed to not care about the format of the token -- it will gladly pass any token to the introspection endpoint provided.
|
Spring Security's Opaque Token support has been designed to not care about the format of the token -- it will gladly pass any token to the introspection endpoint provided.
|
||||||
|
@ -2204,7 +2204,7 @@ fun introspector(): OpaqueTokenIntrospector {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-opaque-userinfo]]
|
[[oauth2resourceserver-opaque-userinfo]]
|
||||||
=== Calling a `/userinfo` Endpoint
|
== Calling a `/userinfo` Endpoint
|
||||||
|
|
||||||
Generally speaking, a Resource Server doesn't care about the underlying user, but instead about the authorities that have been granted.
|
Generally speaking, a Resource Server doesn't care about the underlying user, but instead about the authorities that have been granted.
|
||||||
|
|
||||||
|
@ -2324,7 +2324,7 @@ fun introspector(): OpaqueTokenIntrospector {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2reourceserver-opaqueandjwt]]
|
[[oauth2reourceserver-opaqueandjwt]]
|
||||||
=== Supporting both JWT and Opaque Token
|
== Supporting both JWT and Opaque Token
|
||||||
|
|
||||||
In some cases, you may have a need to access both kinds of tokens.
|
In some cases, you may have a need to access both kinds of tokens.
|
||||||
For example, you may support more than one tenant where one tenant issues JWTs and the other issues opaque tokens.
|
For example, you may support more than one tenant where one tenant issues JWTs and the other issues opaque tokens.
|
||||||
|
@ -2407,7 +2407,7 @@ http {
|
||||||
====
|
====
|
||||||
|
|
||||||
[[oauth2resourceserver-multitenancy]]
|
[[oauth2resourceserver-multitenancy]]
|
||||||
=== Multi-tenancy
|
== Multi-tenancy
|
||||||
|
|
||||||
A resource server is considered multi-tenant when there are multiple strategies for verifying a bearer token, keyed by some tenant identifier.
|
A resource server is considered multi-tenant when there are multiple strategies for verifying a bearer token, keyed by some tenant identifier.
|
||||||
|
|
||||||
|
@ -2419,7 +2419,7 @@ In each case, there are two things that need to be done and trade-offs associate
|
||||||
1. Resolve the tenant
|
1. Resolve the tenant
|
||||||
2. Propagate the tenant
|
2. Propagate the tenant
|
||||||
|
|
||||||
==== Resolving the Tenant By Claim
|
=== Resolving the Tenant By Claim
|
||||||
|
|
||||||
One way to differentiate tenants is by the issuer claim. Since the issuer claim accompanies signed JWTs, this can be done with the `JwtIssuerAuthenticationManagerResolver`, like so:
|
One way to differentiate tenants is by the issuer claim. Since the issuer claim accompanies signed JWTs, this can be done with the `JwtIssuerAuthenticationManagerResolver`, like so:
|
||||||
|
|
||||||
|
@ -2478,7 +2478,7 @@ This is nice because the issuer endpoints are loaded lazily.
|
||||||
In fact, the corresponding `JwtAuthenticationProvider` is instantiated only when the first request with the corresponding issuer is sent.
|
In fact, the corresponding `JwtAuthenticationProvider` is instantiated only when the first request with the corresponding issuer is sent.
|
||||||
This allows for an application startup that is independent from those authorization servers being up and available.
|
This allows for an application startup that is independent from those authorization servers being up and available.
|
||||||
|
|
||||||
===== Dynamic Tenants
|
==== Dynamic Tenants
|
||||||
|
|
||||||
Of course, you may not want to restart the application each time a new tenant is added.
|
Of course, you may not want to restart the application each time a new tenant is added.
|
||||||
In this case, you can configure the `JwtIssuerAuthenticationManagerResolver` with a repository of `AuthenticationManager` instances, which you can edit at runtime, like so:
|
In this case, you can configure the `JwtIssuerAuthenticationManagerResolver` with a repository of `AuthenticationManager` instances, which you can edit at runtime, like so:
|
||||||
|
@ -2538,7 +2538,7 @@ This approach allows us to add and remove elements from the repository (shown as
|
||||||
NOTE: It would be unsafe to simply take any issuer and construct an `AuthenticationManager` from it.
|
NOTE: It would be unsafe to simply take any issuer and construct an `AuthenticationManager` from it.
|
||||||
The issuer should be one that the code can verify from a trusted source like a list of allowed issuers.
|
The issuer should be one that the code can verify from a trusted source like a list of allowed issuers.
|
||||||
|
|
||||||
===== Parsing the Claim Only Once
|
==== Parsing the Claim Only Once
|
||||||
|
|
||||||
You may have observed that this strategy, while simple, comes with the trade-off that the JWT is parsed once by the `AuthenticationManagerResolver` and then again by the <<oauth2resourceserver-jwt-architecture-jwtdecoder,`JwtDecoder`>> later on in the request.
|
You may have observed that this strategy, while simple, comes with the trade-off that the JWT is parsed once by the `AuthenticationManagerResolver` and then again by the <<oauth2resourceserver-jwt-architecture-jwtdecoder,`JwtDecoder`>> later on in the request.
|
||||||
|
|
||||||
|
@ -2768,12 +2768,12 @@ For example, if you are resolving it by subdomain, you may need to address the d
|
||||||
However, if you resolve it by a claim in the bearer token, read on to learn about <<oauth2resourceserver-bearertoken-resolver,Spring Security's support for bearer token propagation>>.
|
However, if you resolve it by a claim in the bearer token, read on to learn about <<oauth2resourceserver-bearertoken-resolver,Spring Security's support for bearer token propagation>>.
|
||||||
|
|
||||||
[[oauth2resourceserver-bearertoken-resolver]]
|
[[oauth2resourceserver-bearertoken-resolver]]
|
||||||
=== Bearer Token Resolution
|
== Bearer Token Resolution
|
||||||
|
|
||||||
By default, Resource Server looks for a bearer token in the `Authorization` header.
|
By default, Resource Server looks for a bearer token in the `Authorization` header.
|
||||||
This, however, can be customized in a handful of ways.
|
This, however, can be customized in a handful of ways.
|
||||||
|
|
||||||
==== Reading the Bearer Token from a Custom Header
|
=== Reading the Bearer Token from a Custom Header
|
||||||
|
|
||||||
For example, you may have a need to read the bearer token from a custom header.
|
For example, you may have a need to read the bearer token from a custom header.
|
||||||
To achieve this, you can expose a `DefaultBearerTokenResolver` as a bean, or wire an instance into the DSL, as you can see in the following example:
|
To achieve this, you can expose a `DefaultBearerTokenResolver` as a bean, or wire an instance into the DSL, as you can see in the following example:
|
||||||
|
@ -2818,7 +2818,7 @@ fun bearerTokenResolver(): BearerTokenResolver {
|
||||||
|
|
||||||
Or, in circumstances where a provider is using both a custom header and value, you can use `HeaderBearerTokenResolver` instead.
|
Or, in circumstances where a provider is using both a custom header and value, you can use `HeaderBearerTokenResolver` instead.
|
||||||
|
|
||||||
==== Reading the Bearer Token from a Form Parameter
|
=== Reading the Bearer Token from a Form Parameter
|
||||||
|
|
||||||
Or, you may wish to read the token from a form parameter, which you can do by configuring the `DefaultBearerTokenResolver`, as you can see below:
|
Or, you may wish to read the token from a form parameter, which you can do by configuring the `DefaultBearerTokenResolver`, as you can see below:
|
||||||
|
|
||||||
|
@ -2861,7 +2861,7 @@ http {
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
=== Bearer Token Propagation
|
== Bearer Token Propagation
|
||||||
|
|
||||||
Now that you're resource server has validated the token, it might be handy to pass it to downstream services.
|
Now that you're resource server has validated the token, it might be handy to pass it to downstream services.
|
||||||
This is quite simple with `{security-api-url}org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunction.html[ServletBearerExchangeFilterFunction]`, which you can see in the following example:
|
This is quite simple with `{security-api-url}org/springframework/security/oauth2/server/resource/web/reactive/function/client/ServletBearerExchangeFilterFunction.html[ServletBearerExchangeFilterFunction]`, which you can see in the following example:
|
||||||
|
@ -2951,7 +2951,7 @@ In this case, the filter will fall back and simply forward the request onto the
|
||||||
Unlike the {security-api-url}org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.html[OAuth 2.0 Client filter function], this filter function makes no attempt to renew the token, should it be expired.
|
Unlike the {security-api-url}org/springframework/security/oauth2/client/web/reactive/function/client/ServletOAuth2AuthorizedClientExchangeFilterFunction.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, please use the OAuth 2.0 Client filter.
|
To obtain this level of support, please use the OAuth 2.0 Client filter.
|
||||||
|
|
||||||
==== `RestTemplate` support
|
=== `RestTemplate` support
|
||||||
|
|
||||||
There is no `RestTemplate` equivalent for `ServletBearerExchangeFilterFunction` at the moment, but you can propagate the request's bearer token quite simply with your own interceptor:
|
There is no `RestTemplate` equivalent for `ServletBearerExchangeFilterFunction` at the moment, but you can propagate the request's bearer token quite simply with your own interceptor:
|
||||||
|
|
||||||
|
@ -3011,7 +3011,7 @@ Unlike the {security-api-url}org/springframework/security/oauth2/client/OAuth2Au
|
||||||
To obtain this level of support, please create an interceptor using the <<oauth2client,OAuth 2.0 Authorized Client Manager>>.
|
To obtain this level of support, please create an interceptor using the <<oauth2client,OAuth 2.0 Authorized Client Manager>>.
|
||||||
|
|
||||||
[[oauth2resourceserver-bearertoken-failure]]
|
[[oauth2resourceserver-bearertoken-failure]]
|
||||||
=== Bearer Token Failure
|
== Bearer Token Failure
|
||||||
|
|
||||||
A bearer token may be invalid for a number of reasons. For example, the token may no longer be active.
|
A bearer token may be invalid for a number of reasons. For example, the token may no longer be active.
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,9 @@
|
||||||
|
|
||||||
This section describes the testing support provided by Spring Security.
|
This section describes the testing support provided by Spring Security.
|
||||||
|
|
||||||
[TIP]
|
|
||||||
====
|
|
||||||
To use the Spring Security test support, you must include `spring-security-test-{spring-security-version}.jar` as a dependency of your project.
|
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[]
|
At a high level Spring Security's test support provides integration for:
|
||||||
|
|
||||||
include::mockmvc.adoc[]
|
* xref:servlet/test/method.adoc[Method Security] - provides test support for Spring Security's method security.
|
||||||
|
* xref:servlet/test/mockmvc.adoc[MockMvc] - Provides test support to integrate with Spring's `MockMvc`.
|
||||||
|
|
Loading…
Reference in New Issue