(window.webpackJsonp=window.webpackJsonp||[]).push([[198],{624:function(e,t,i){"use strict";i.r(t);var r=i(56),n=Object(r.a)({},(function(){var e=this,t=e.$createElement,i=e._self._c||t;return i("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[i("h1",{attrs:{id:"core-interfaces-classes"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#core-interfaces-classes"}},[e._v("#")]),e._v(" Core Interfaces / Classes")]),e._v(" "),i("h2",{attrs:{id:"clientregistration"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#clientregistration"}},[e._v("#")]),e._v(" ClientRegistration")]),e._v(" "),i("p",[i("code",[e._v("ClientRegistration")]),e._v(" is a representation of a client registered with an OAuth 2.0 or OpenID Connect 1.0 Provider.")]),e._v(" "),i("p",[e._v("A client registration holds information, such as client id, client secret, authorization grant type, redirect URI, scope(s), authorization URI, token URI, and other details.")]),e._v(" "),i("p",[i("code",[e._v("ClientRegistration")]),e._v(" and its properties are defined as follows:")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("public final class ClientRegistration {\n\tprivate String registrationId;\t(1)\n\tprivate String clientId;\t(2)\n\tprivate String clientSecret;\t(3)\n\tprivate ClientAuthenticationMethod clientAuthenticationMethod;\t(4)\n\tprivate AuthorizationGrantType authorizationGrantType;\t(5)\n\tprivate String redirectUri;\t(6)\n\tprivate Set scopes;\t(7)\n\tprivate ProviderDetails providerDetails;\n\tprivate String clientName;\t(8)\n\n\tpublic class ProviderDetails {\n\t\tprivate String authorizationUri;\t(9)\n\t\tprivate String tokenUri;\t(10)\n\t\tprivate UserInfoEndpoint userInfoEndpoint;\n\t\tprivate String jwkSetUri;\t(11)\n\t\tprivate String issuerUri;\t(12)\n\t\tprivate Map configurationMetadata; (13)\n\n\t\tpublic class UserInfoEndpoint {\n\t\t\tprivate String uri;\t(14)\n\t\t\tprivate AuthenticationMethod authenticationMethod; (15)\n\t\t\tprivate String userNameAttributeName;\t(16)\n\n\t\t}\n\t}\n}\n")])])]),i("table",[i("thead",[i("tr",[i("th",[i("strong",[e._v("1")])]),e._v(" "),i("th",[i("code",[e._v("registrationId")]),e._v(": The ID that uniquely identifies the "),i("code",[e._v("ClientRegistration")]),e._v(".")])])]),e._v(" "),i("tbody",[i("tr",[i("td",[i("strong",[e._v("2")])]),e._v(" "),i("td",[i("code",[e._v("clientId")]),e._v(": The client identifier.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("3")])]),e._v(" "),i("td",[i("code",[e._v("clientSecret")]),e._v(": The client secret.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("4")])]),e._v(" "),i("td",[i("code",[e._v("clientAuthenticationMethod")]),e._v(": The method used to authenticate the Client with the Provider."),i("br"),e._v("The supported values are "),i("strong",[e._v("client_secret_basic")]),e._v(", "),i("strong",[e._v("client_secret_post")]),e._v(", "),i("strong",[e._v("private_key_jwt")]),e._v(", "),i("strong",[e._v("client_secret_jwt")]),e._v(" and "),i("strong",[e._v("none")]),e._v(" "),i("a",{attrs:{href:"https://tools.ietf.org/html/rfc6749#section-2.1",target:"_blank",rel:"noopener noreferrer"}},[e._v("(public clients)"),i("OutboundLink")],1),e._v(".")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("5")])]),e._v(" "),i("td",[i("code",[e._v("authorizationGrantType")]),e._v(": The OAuth 2.0 Authorization Framework defines four "),i("a",{attrs:{href:"https://tools.ietf.org/html/rfc6749#section-1.3",target:"_blank",rel:"noopener noreferrer"}},[e._v("Authorization Grant"),i("OutboundLink")],1),e._v(" types."),i("br"),e._v("The supported values are "),i("code",[e._v("authorization_code")]),e._v(", "),i("code",[e._v("client_credentials")]),e._v(", "),i("code",[e._v("password")]),e._v(", as well as, extension grant type "),i("code",[e._v("urn:ietf:params:oauth:grant-type:jwt-bearer")]),e._v(".")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("6")])]),e._v(" "),i("td",[i("code",[e._v("redirectUri")]),e._v(": The client’s registered redirect URI that the "),i("em",[e._v("Authorization Server")]),e._v(" redirects the end-user’s user-agent"),i("br"),e._v("to after the end-user has authenticated and authorized access to the client.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("7")])]),e._v(" "),i("td",[i("code",[e._v("scopes")]),e._v(": The scope(s) requested by the client during the Authorization Request flow, such as openid, email, or profile.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("8")])]),e._v(" "),i("td",[i("code",[e._v("clientName")]),e._v(": A descriptive name used for the client."),i("br"),e._v("The name may be used in certain scenarios, such as when displaying the name of the client in the auto-generated login page.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("9")])]),e._v(" "),i("td",[i("code",[e._v("authorizationUri")]),e._v(": The Authorization Endpoint URI for the Authorization Server.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("10")])]),e._v(" "),i("td",[i("code",[e._v("tokenUri")]),e._v(": The Token Endpoint URI for the Authorization Server.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("11")])]),e._v(" "),i("td",[i("code",[e._v("jwkSetUri")]),e._v(": The URI used to retrieve the "),i("a",{attrs:{href:"https://tools.ietf.org/html/rfc7517",target:"_blank",rel:"noopener noreferrer"}},[e._v("JSON Web Key (JWK)"),i("OutboundLink")],1),e._v(" Set from the Authorization Server,"),i("br"),e._v("which contains the cryptographic key(s) used to verify the "),i("a",{attrs:{href:"https://tools.ietf.org/html/rfc7515",target:"_blank",rel:"noopener noreferrer"}},[e._v("JSON Web Signature (JWS)"),i("OutboundLink")],1),e._v(" of the ID Token and optionally the UserInfo Response.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("12")])]),e._v(" "),i("td",[i("code",[e._v("issuerUri")]),e._v(": Returns the issuer identifier uri for the OpenID Connect 1.0 provider or the OAuth 2.0 Authorization Server.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("13")])]),e._v(" "),i("td",[i("code",[e._v("configurationMetadata")]),e._v(": The "),i("a",{attrs:{href:"https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig",target:"_blank",rel:"noopener noreferrer"}},[e._v("OpenID Provider Configuration Information"),i("OutboundLink")],1),e._v("."),i("br"),e._v("This information will only be available if the Spring Boot 2.x property "),i("code",[e._v("spring.security.oauth2.client.provider.[providerId].issuerUri")]),e._v(" is configured.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("14")])]),e._v(" "),i("td",[i("code",[e._v("(userInfoEndpoint)uri")]),e._v(": The UserInfo Endpoint URI used to access the claims/attributes of the authenticated end-user.")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("15")])]),e._v(" "),i("td",[i("code",[e._v("(userInfoEndpoint)authenticationMethod")]),e._v(": The authentication method used when sending the access token to the UserInfo Endpoint."),i("br"),e._v("The supported values are "),i("strong",[e._v("header")]),e._v(", "),i("strong",[e._v("form")]),e._v(" and "),i("strong",[e._v("query")]),e._v(".")])]),e._v(" "),i("tr",[i("td",[i("strong",[e._v("16")])]),e._v(" "),i("td",[i("code",[e._v("userNameAttributeName")]),e._v(": The name of the attribute returned in the UserInfo Response that references the Name or Identifier of the end-user.")])])])]),e._v(" "),i("p",[e._v("A "),i("code",[e._v("ClientRegistration")]),e._v(" can be initially configured using discovery of an OpenID Connect Provider’s "),i("a",{attrs:{href:"https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig",target:"_blank",rel:"noopener noreferrer"}},[e._v("Configuration endpoint"),i("OutboundLink")],1),e._v(" or an Authorization Server’s "),i("a",{attrs:{href:"https://tools.ietf.org/html/rfc8414#section-3",target:"_blank",rel:"noopener noreferrer"}},[e._v("Metadata endpoint"),i("OutboundLink")],1),e._v(".")]),e._v(" "),i("p",[i("code",[e._v("ClientRegistrations")]),e._v(" provides convenience methods for configuring a "),i("code",[e._v("ClientRegistration")]),e._v(" in this way, as can be seen in the following example:")]),e._v(" "),i("p",[e._v("Java")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v('ClientRegistration clientRegistration =\n\tClientRegistrations.fromIssuerLocation("https://idp.example.com/issuer").build();\n')])])]),i("p",[e._v("Kotlin")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v('val clientRegistration = ClientRegistrations.fromIssuerLocation("https://idp.example.com/issuer").build()\n')])])]),i("p",[e._v("The above code will query in series "),i("code",[e._v("[https://idp.example.com/issuer/.well-known/openid-configuration](https://idp.example.com/issuer/.well-known/openid-configuration)")]),e._v(", and then "),i("code",[e._v("[https://idp.example.com/.well-known/openid-configuration/issuer](https://idp.example.com/.well-known/openid-configuration/issuer)")]),e._v(", and finally "),i("code",[e._v("[https://idp.example.com/.well-known/oauth-authorization-server/issuer](https://idp.example.com/.well-known/oauth-authorization-server/issuer)")]),e._v(", stopping at the first to return a 200 response.")]),e._v(" "),i("p",[e._v("As an alternative, you can use "),i("code",[e._v("ClientRegistrations.fromOidcIssuerLocation()")]),e._v(" to only query the OpenID Connect Provider’s Configuration endpoint.")]),e._v(" "),i("h2",{attrs:{id:"reactiveclientregistrationrepository"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#reactiveclientregistrationrepository"}},[e._v("#")]),e._v(" ReactiveClientRegistrationRepository")]),e._v(" "),i("p",[e._v("The "),i("code",[e._v("ReactiveClientRegistrationRepository")]),e._v(" serves as a repository for OAuth 2.0 / OpenID Connect 1.0 "),i("code",[e._v("ClientRegistration")]),e._v("(s).")]),e._v(" "),i("table",[i("thead",[i("tr",[i("th"),e._v(" "),i("th",[e._v("Client registration information is ultimately stored and owned by the associated Authorization Server."),i("br"),e._v("This repository provides the ability to retrieve a sub-set of the primary client registration information, which is stored with the Authorization Server.")])])]),e._v(" "),i("tbody")]),e._v(" "),i("p",[e._v("Spring Boot 2.x auto-configuration binds each of the properties under "),i("code",[e._v("spring.security.oauth2.client.registration.*[registrationId]*")]),e._v(" to an instance of "),i("code",[e._v("ClientRegistration")]),e._v(" and then composes each of the "),i("code",[e._v("ClientRegistration")]),e._v(" instance(s) within a "),i("code",[e._v("ReactiveClientRegistrationRepository")]),e._v(".")]),e._v(" "),i("table",[i("thead",[i("tr",[i("th"),e._v(" "),i("th",[e._v("The default implementation of "),i("code",[e._v("ReactiveClientRegistrationRepository")]),e._v(" is "),i("code",[e._v("InMemoryReactiveClientRegistrationRepository")]),e._v(".")])])]),e._v(" "),i("tbody")]),e._v(" "),i("p",[e._v("The auto-configuration also registers the "),i("code",[e._v("ReactiveClientRegistrationRepository")]),e._v(" as a "),i("code",[e._v("@Bean")]),e._v(" in the "),i("code",[e._v("ApplicationContext")]),e._v(" so that it is available for dependency-injection, if needed by the application.")]),e._v(" "),i("p",[e._v("The following listing shows an example:")]),e._v(" "),i("p",[e._v("Java")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v('@Controller\npublic class OAuth2ClientController {\n\n\t@Autowired\n\tprivate ReactiveClientRegistrationRepository clientRegistrationRepository;\n\n\t@GetMapping("/")\n\tpublic Mono index() {\n\t\treturn this.clientRegistrationRepository.findByRegistrationId("okta")\n\t\t\t\t...\n\t\t\t\t.thenReturn("index");\n\t}\n}\n')])])]),i("p",[e._v("Kotlin")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v('@Controller\nclass OAuth2ClientController {\n\n @Autowired\n private lateinit var clientRegistrationRepository: ReactiveClientRegistrationRepository\n\n @GetMapping("/")\n fun index(): Mono {\n return this.clientRegistrationRepository.findByRegistrationId("okta")\n ...\n .thenReturn("index")\n }\n}\n')])])]),i("h2",{attrs:{id:"oauth2authorizedclient"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#oauth2authorizedclient"}},[e._v("#")]),e._v(" OAuth2AuthorizedClient")]),e._v(" "),i("p",[i("code",[e._v("OAuth2AuthorizedClient")]),e._v(" is a representation of an Authorized Client.\nA client is considered to be authorized when the end-user (Resource Owner) has granted authorization to the client to access its protected resources.")]),e._v(" "),i("p",[i("code",[e._v("OAuth2AuthorizedClient")]),e._v(" serves the purpose of associating an "),i("code",[e._v("OAuth2AccessToken")]),e._v(" (and optional "),i("code",[e._v("OAuth2RefreshToken")]),e._v(") to a "),i("code",[e._v("ClientRegistration")]),e._v(" (client) and resource owner, who is the "),i("code",[e._v("Principal")]),e._v(" end-user that granted the authorization.")]),e._v(" "),i("h2",{attrs:{id:"serveroauth2authorizedclientrepository-reactiveoauth2authorizedclientservice"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#serveroauth2authorizedclientrepository-reactiveoauth2authorizedclientservice"}},[e._v("#")]),e._v(" ServerOAuth2AuthorizedClientRepository / ReactiveOAuth2AuthorizedClientService")]),e._v(" "),i("p",[i("code",[e._v("ServerOAuth2AuthorizedClientRepository")]),e._v(" is responsible for persisting "),i("code",[e._v("OAuth2AuthorizedClient")]),e._v("(s) between web requests.\nWhereas, the primary role of "),i("code",[e._v("ReactiveOAuth2AuthorizedClientService")]),e._v(" is to manage "),i("code",[e._v("OAuth2AuthorizedClient")]),e._v("(s) at the application-level.")]),e._v(" "),i("p",[e._v("From a developer perspective, the "),i("code",[e._v("ServerOAuth2AuthorizedClientRepository")]),e._v(" or "),i("code",[e._v("ReactiveOAuth2AuthorizedClientService")]),e._v(" provides the capability to lookup an "),i("code",[e._v("OAuth2AccessToken")]),e._v(" associated with a client so that it may be used to initiate a protected resource request.")]),e._v(" "),i("p",[e._v("The following listing shows an example:")]),e._v(" "),i("p",[e._v("Java")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v('@Controller\npublic class OAuth2ClientController {\n\n\t@Autowired\n\tprivate ReactiveOAuth2AuthorizedClientService authorizedClientService;\n\n\t@GetMapping("/")\n\tpublic Mono index(Authentication authentication) {\n\t\treturn this.authorizedClientService.loadAuthorizedClient("okta", authentication.getName())\n\t\t\t\t.map(OAuth2AuthorizedClient::getAccessToken)\n\t\t\t\t...\n\t\t\t\t.thenReturn("index");\n\t}\n}\n')])])]),i("p",[e._v("Kotlin")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v('@Controller\nclass OAuth2ClientController {\n\n @Autowired\n private lateinit var authorizedClientService: ReactiveOAuth2AuthorizedClientService\n\n @GetMapping("/")\n fun index(authentication: Authentication): Mono {\n return this.authorizedClientService.loadAuthorizedClient("okta", authentication.name)\n .map { it.accessToken }\n ...\n .thenReturn("index")\n }\n}\n')])])]),i("table",[i("thead",[i("tr",[i("th"),e._v(" "),i("th",[e._v("Spring Boot 2.x auto-configuration registers an "),i("code",[e._v("ServerOAuth2AuthorizedClientRepository")]),e._v(" and/or "),i("code",[e._v("ReactiveOAuth2AuthorizedClientService")]),e._v(" "),i("code",[e._v("@Bean")]),e._v(" in the "),i("code",[e._v("ApplicationContext")]),e._v("."),i("br"),e._v("However, the application may choose to override and register a custom "),i("code",[e._v("ServerOAuth2AuthorizedClientRepository")]),e._v(" or "),i("code",[e._v("ReactiveOAuth2AuthorizedClientService")]),e._v(" "),i("code",[e._v("@Bean")]),e._v(".")])])]),e._v(" "),i("tbody")]),e._v(" "),i("p",[e._v("The default implementation of "),i("code",[e._v("ReactiveOAuth2AuthorizedClientService")]),e._v(" is "),i("code",[e._v("InMemoryReactiveOAuth2AuthorizedClientService")]),e._v(", which stores "),i("code",[e._v("OAuth2AuthorizedClient")]),e._v("(s) in-memory.")]),e._v(" "),i("p",[e._v("Alternatively, the R2DBC implementation "),i("code",[e._v("R2dbcReactiveOAuth2AuthorizedClientService")]),e._v(" may be configured for persisting "),i("code",[e._v("OAuth2AuthorizedClient")]),e._v("(s) in a database.")]),e._v(" "),i("table",[i("thead",[i("tr",[i("th"),e._v(" "),i("th",[i("code",[e._v("R2dbcReactiveOAuth2AuthorizedClientService")]),e._v(" depends on the table definition described in "),i("RouterLink",{attrs:{to:"/servlet/appendix/database-schema.html#dbschema-oauth2-client"}},[e._v(" OAuth 2.0 Client Schema")]),e._v(".")],1)])]),e._v(" "),i("tbody")]),e._v(" "),i("h2",{attrs:{id:"reactiveoauth2authorizedclientmanager-reactiveoauth2authorizedclientprovider"}},[i("a",{staticClass:"header-anchor",attrs:{href:"#reactiveoauth2authorizedclientmanager-reactiveoauth2authorizedclientprovider"}},[e._v("#")]),e._v(" ReactiveOAuth2AuthorizedClientManager / ReactiveOAuth2AuthorizedClientProvider")]),e._v(" "),i("p",[e._v("The "),i("code",[e._v("ReactiveOAuth2AuthorizedClientManager")]),e._v(" is responsible for the overall management of "),i("code",[e._v("OAuth2AuthorizedClient")]),e._v("(s).")]),e._v(" "),i("p",[e._v("The primary responsibilities include:")]),e._v(" "),i("ul",[i("li",[i("p",[e._v("Authorizing (or re-authorizing) an OAuth 2.0 Client, using a "),i("code",[e._v("ReactiveOAuth2AuthorizedClientProvider")]),e._v(".")])]),e._v(" "),i("li",[i("p",[e._v("Delegating the persistence of an "),i("code",[e._v("OAuth2AuthorizedClient")]),e._v(", typically using a "),i("code",[e._v("ReactiveOAuth2AuthorizedClientService")]),e._v(" or "),i("code",[e._v("ServerOAuth2AuthorizedClientRepository")]),e._v(".")])]),e._v(" "),i("li",[i("p",[e._v("Delegating to a "),i("code",[e._v("ReactiveOAuth2AuthorizationSuccessHandler")]),e._v(" when an OAuth 2.0 Client has been successfully authorized (or re-authorized).")])]),e._v(" "),i("li",[i("p",[e._v("Delegating to a "),i("code",[e._v("ReactiveOAuth2AuthorizationFailureHandler")]),e._v(" when an OAuth 2.0 Client fails to authorize (or re-authorize).")])])]),e._v(" "),i("p",[e._v("A "),i("code",[e._v("ReactiveOAuth2AuthorizedClientProvider")]),e._v(" implements a strategy for authorizing (or re-authorizing) an OAuth 2.0 Client.\nImplementations will typically implement an authorization grant type, eg. "),i("code",[e._v("authorization_code")]),e._v(", "),i("code",[e._v("client_credentials")]),e._v(", etc.")]),e._v(" "),i("p",[e._v("The default implementation of "),i("code",[e._v("ReactiveOAuth2AuthorizedClientManager")]),e._v(" is "),i("code",[e._v("DefaultReactiveOAuth2AuthorizedClientManager")]),e._v(", which is associated with a "),i("code",[e._v("ReactiveOAuth2AuthorizedClientProvider")]),e._v(" that may support multiple authorization grant types using a delegation-based composite.\nThe "),i("code",[e._v("ReactiveOAuth2AuthorizedClientProviderBuilder")]),e._v(" may be used to configure and build the delegation-based composite.")]),e._v(" "),i("p",[e._v("The following code shows an example of how to configure and build a "),i("code",[e._v("ReactiveOAuth2AuthorizedClientProvider")]),e._v(" composite that provides support for the "),i("code",[e._v("authorization_code")]),e._v(", "),i("code",[e._v("refresh_token")]),e._v(", "),i("code",[e._v("client_credentials")]),e._v(" and "),i("code",[e._v("password")]),e._v(" authorization grant types:")]),e._v(" "),i("p",[e._v("Java")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("@Bean\npublic ReactiveOAuth2AuthorizedClientManager authorizedClientManager(\n\t\tReactiveClientRegistrationRepository clientRegistrationRepository,\n\t\tServerOAuth2AuthorizedClientRepository authorizedClientRepository) {\n\n\tReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =\n\t\t\tReactiveOAuth2AuthorizedClientProviderBuilder.builder()\n\t\t\t\t\t.authorizationCode()\n\t\t\t\t\t.refreshToken()\n\t\t\t\t\t.clientCredentials()\n\t\t\t\t\t.password()\n\t\t\t\t\t.build();\n\n\tDefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =\n\t\t\tnew DefaultReactiveOAuth2AuthorizedClientManager(\n\t\t\t\t\tclientRegistrationRepository, authorizedClientRepository);\n\tauthorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);\n\n\treturn authorizedClientManager;\n}\n")])])]),i("p",[e._v("Kotlin")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("@Bean\nfun authorizedClientManager(\n clientRegistrationRepository: ReactiveClientRegistrationRepository,\n authorizedClientRepository: ServerOAuth2AuthorizedClientRepository): ReactiveOAuth2AuthorizedClientManager {\n val authorizedClientProvider: ReactiveOAuth2AuthorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()\n .authorizationCode()\n .refreshToken()\n .clientCredentials()\n .password()\n .build()\n val authorizedClientManager = DefaultReactiveOAuth2AuthorizedClientManager(\n clientRegistrationRepository, authorizedClientRepository)\n authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)\n return authorizedClientManager\n}\n")])])]),i("p",[e._v("When an authorization attempt succeeds, the "),i("code",[e._v("DefaultReactiveOAuth2AuthorizedClientManager")]),e._v(" will delegate to the "),i("code",[e._v("ReactiveOAuth2AuthorizationSuccessHandler")]),e._v(", which (by default) will save the "),i("code",[e._v("OAuth2AuthorizedClient")]),e._v(" via the "),i("code",[e._v("ServerOAuth2AuthorizedClientRepository")]),e._v(".\nIn the case of a re-authorization failure, eg. a refresh token is no longer valid, the previously saved "),i("code",[e._v("OAuth2AuthorizedClient")]),e._v(" will be removed from the "),i("code",[e._v("ServerOAuth2AuthorizedClientRepository")]),e._v(" via the "),i("code",[e._v("RemoveAuthorizedClientReactiveOAuth2AuthorizationFailureHandler")]),e._v(".\nThe default behaviour may be customized via "),i("code",[e._v("setAuthorizationSuccessHandler(ReactiveOAuth2AuthorizationSuccessHandler)")]),e._v(" and "),i("code",[e._v("setAuthorizationFailureHandler(ReactiveOAuth2AuthorizationFailureHandler)")]),e._v(".")]),e._v(" "),i("p",[e._v("The "),i("code",[e._v("DefaultReactiveOAuth2AuthorizedClientManager")]),e._v(" is also associated with a "),i("code",[e._v("contextAttributesMapper")]),e._v(" of type "),i("code",[e._v("Function>>")]),e._v(", which is responsible for mapping attribute(s) from the "),i("code",[e._v("OAuth2AuthorizeRequest")]),e._v(" to a "),i("code",[e._v("Map")]),e._v(" of attributes to be associated to the "),i("code",[e._v("OAuth2AuthorizationContext")]),e._v(".\nThis can be useful when you need to supply a "),i("code",[e._v("ReactiveOAuth2AuthorizedClientProvider")]),e._v(" with required (supported) attribute(s), eg. the "),i("code",[e._v("PasswordReactiveOAuth2AuthorizedClientProvider")]),e._v(" requires the resource owner’s "),i("code",[e._v("username")]),e._v(" and "),i("code",[e._v("password")]),e._v(" to be available in "),i("code",[e._v("OAuth2AuthorizationContext.getAttributes()")]),e._v(".")]),e._v(" "),i("p",[e._v("The following code shows an example of the "),i("code",[e._v("contextAttributesMapper")]),e._v(":")]),e._v(" "),i("p",[e._v("Java")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("@Bean\npublic ReactiveOAuth2AuthorizedClientManager authorizedClientManager(\n\t\tReactiveClientRegistrationRepository clientRegistrationRepository,\n\t\tServerOAuth2AuthorizedClientRepository authorizedClientRepository) {\n\n\tReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =\n\t\t\tReactiveOAuth2AuthorizedClientProviderBuilder.builder()\n\t\t\t\t\t.password()\n\t\t\t\t\t.refreshToken()\n\t\t\t\t\t.build();\n\n\tDefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =\n\t\t\tnew DefaultReactiveOAuth2AuthorizedClientManager(\n\t\t\t\t\tclientRegistrationRepository, authorizedClientRepository);\n\tauthorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);\n\n\t// Assuming the `username` and `password` are supplied as `ServerHttpRequest` parameters,\n\t// map the `ServerHttpRequest` parameters to `OAuth2AuthorizationContext.getAttributes()`\n\tauthorizedClientManager.setContextAttributesMapper(contextAttributesMapper());\n\n\treturn authorizedClientManager;\n}\n\nprivate Function>> contextAttributesMapper() {\n\treturn authorizeRequest -> {\n\t\tMap contextAttributes = Collections.emptyMap();\n\t\tServerWebExchange exchange = authorizeRequest.getAttribute(ServerWebExchange.class.getName());\n\t\tServerHttpRequest request = exchange.getRequest();\n\t\tString username = request.getQueryParams().getFirst(OAuth2ParameterNames.USERNAME);\n\t\tString password = request.getQueryParams().getFirst(OAuth2ParameterNames.PASSWORD);\n\t\tif (StringUtils.hasText(username) && StringUtils.hasText(password)) {\n\t\t\tcontextAttributes = new HashMap<>();\n\n\t\t\t// `PasswordReactiveOAuth2AuthorizedClientProvider` requires both attributes\n\t\t\tcontextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);\n\t\t\tcontextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);\n\t\t}\n\t\treturn Mono.just(contextAttributes);\n\t};\n}\n")])])]),i("p",[e._v("Kotlin")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("@Bean\nfun authorizedClientManager(\n clientRegistrationRepository: ReactiveClientRegistrationRepository,\n authorizedClientRepository: ServerOAuth2AuthorizedClientRepository): ReactiveOAuth2AuthorizedClientManager {\n val authorizedClientProvider: ReactiveOAuth2AuthorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()\n .password()\n .refreshToken()\n .build()\n val authorizedClientManager = DefaultReactiveOAuth2AuthorizedClientManager(\n clientRegistrationRepository, authorizedClientRepository)\n authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)\n\n // Assuming the `username` and `password` are supplied as `ServerHttpRequest` parameters,\n // map the `ServerHttpRequest` parameters to `OAuth2AuthorizationContext.getAttributes()`\n authorizedClientManager.setContextAttributesMapper(contextAttributesMapper())\n return authorizedClientManager\n}\n\nprivate fun contextAttributesMapper(): Function>> {\n return Function { authorizeRequest ->\n var contextAttributes: MutableMap = mutableMapOf()\n val exchange: ServerWebExchange = authorizeRequest.getAttribute(ServerWebExchange::class.java.name)!!\n val request: ServerHttpRequest = exchange.request\n val username: String? = request.queryParams.getFirst(OAuth2ParameterNames.USERNAME)\n val password: String? = request.queryParams.getFirst(OAuth2ParameterNames.PASSWORD)\n if (StringUtils.hasText(username) && StringUtils.hasText(password)) {\n contextAttributes = hashMapOf()\n\n // `PasswordReactiveOAuth2AuthorizedClientProvider` requires both attributes\n contextAttributes[OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME] = username!!\n contextAttributes[OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME] = password!!\n }\n Mono.just(contextAttributes)\n }\n}\n")])])]),i("p",[e._v("The "),i("code",[e._v("DefaultReactiveOAuth2AuthorizedClientManager")]),e._v(" is designed to be used "),i("em",[i("strong",[e._v("within")])]),e._v(" the context of a "),i("code",[e._v("ServerWebExchange")]),e._v(".\nWhen operating "),i("em",[i("strong",[e._v("outside")])]),e._v(" of a "),i("code",[e._v("ServerWebExchange")]),e._v(" context, use "),i("code",[e._v("AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager")]),e._v(" instead.")]),e._v(" "),i("p",[e._v("A "),i("em",[e._v("service application")]),e._v(" is a common use case for when to use an "),i("code",[e._v("AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager")]),e._v(".\nService applications often run in the background, without any user interaction, and typically run under a system-level account instead of a user account.\nAn OAuth 2.0 Client configured with the "),i("code",[e._v("client_credentials")]),e._v(" grant type can be considered a type of service application.")]),e._v(" "),i("p",[e._v("The following code shows an example of how to configure an "),i("code",[e._v("AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager")]),e._v(" that provides support for the "),i("code",[e._v("client_credentials")]),e._v(" grant type:")]),e._v(" "),i("p",[e._v("Java")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("@Bean\npublic ReactiveOAuth2AuthorizedClientManager authorizedClientManager(\n\t\tReactiveClientRegistrationRepository clientRegistrationRepository,\n\t\tReactiveOAuth2AuthorizedClientService authorizedClientService) {\n\n\tReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =\n\t\t\tReactiveOAuth2AuthorizedClientProviderBuilder.builder()\n\t\t\t\t\t.clientCredentials()\n\t\t\t\t\t.build();\n\n\tAuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =\n\t\t\tnew AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(\n\t\t\t\t\tclientRegistrationRepository, authorizedClientService);\n\tauthorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);\n\n\treturn authorizedClientManager;\n}\n")])])]),i("p",[e._v("Kotlin")]),e._v(" "),i("div",{staticClass:"language- extra-class"},[i("pre",{pre:!0,attrs:{class:"language-text"}},[i("code",[e._v("@Bean\nfun authorizedClientManager(\n clientRegistrationRepository: ReactiveClientRegistrationRepository,\n authorizedClientService: ReactiveOAuth2AuthorizedClientService): ReactiveOAuth2AuthorizedClientManager {\n val authorizedClientProvider: ReactiveOAuth2AuthorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()\n .clientCredentials()\n .build()\n val authorizedClientManager = AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(\n clientRegistrationRepository, authorizedClientService)\n authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)\n return authorizedClientManager\n}\n")])])]),i("p",[i("RouterLink",{attrs:{to:"/en/spring-security/index.html"}},[e._v("OAuth2 Client")]),i("RouterLink",{attrs:{to:"/en/spring-security/authorization-grants.html"}},[e._v("OAuth2 Authorization Grants")])],1)])}),[],!1,null,null,null);t.default=n.exports}}]);