-- Find all clients using authorization_code
select id, client_id, client_authentication_methods
from blc_client
where id IN (SELECT id FROM blc_client_grant_types WHERE grant_type = 'authorization_code')
The database schema has changed as part of this version.
Create/update changes (new tables, new columns, etc) are automatically included in the updated *changelog-master.xml
after you upgrade to the new Authentication Services JAR.
The new changesets inside will run automatically to migrate existing data.
Database Platform | Create/Update Changelog File Name |
---|---|
PostgreSQL |
|
MariaDB |
|
MySQL |
|
Oracle |
|
YugabyteDB |
|
Important
|
In this particular release, some of the automated upgrade migration changesets produce results that may require further verification. Please review this section carefully. |
This is if you are using application properties to define client_secret
values for each AuthorizedClient
(ex: via broadleaf.{clientId}.hash
) instead of exclusively using persisted values in the blc_client.client_secret
column in the database.
In such scenarios, the Liquibase migration script responsible for initializing the new blc_client.client_authentication_methods
column on existing rows cannot definitively identify whether a client was a 'public' client or a 'confidential' client.
By default, the script looks for any blc_client
using a grant type of authorization_code
which does not have a blc_client.client_secret
value.
Such clients are considered 'public' clients, and the script will set their blc_client.client_authentication_methods
to ["none"]
.
All other clients are considered 'confidential', and the script will set their blc_client.client_authentication_methods
to ["client_secret_basic"]
.
This means if you had confidential clients using authorization_code
flows where the client secret was provided via an application property and blc_client.client_secret
was null
, the script would have incorrectly assigned blc_client.client_authentication_methods
as ["none"]
.
Verification Steps:
Note
|
In most cases, this should be a fairly short process, since typical BLC deployments only use Furthermore, typical BLC deployments would more often use |
After the migration scripts are executed, run the following SQL against the database to see the value set for client_authentication_methods
for all clients using the authorization_code
grant type
-- Find all clients using authorization_code
select id, client_id, client_authentication_methods
from blc_client
where id IN (SELECT id FROM blc_client_grant_types WHERE grant_type = 'authorization_code')
For each client in the result, check if the client is intended to be a 'public' client and doesn’t use a client_secret
anywhere (neither provided via application properties nor through the DB column).
Examples of public clients include SPA web applications such as those for the admin and storefront.
If the client is supposed to be a 'public' application, then ensure its client_authentication_methods
value is ["none"]
(JSON array).
If the client is supposed to be a 'confidential' application, then ensure its client_authentication_methods
value is ["client_secret_basic"]
(JSON array).
Drop changes (removed tables, removed columns, etc) are defined in a dedicated drop changelog, and are not automatically included or run.
Thus, after verifying a successful upgrade to the new version, you must manually include the drop changelog in your *changelog-master.xml
file like so:
*changelog-master.xml
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
<!-- ... (other changelogs) ... -->
<include file="{DROP-CHANGELOG-FILENAME}" />
</databaseChangeLog>
Database Platform | Drop Changelog File Name |
---|---|
PostgreSQL |
|
MariaDB |
|
MySQL |
|
Oracle |
|
YugabyteDB |
|
Broadleaf has introduced an upgrade tool to assist with upgrading client projects. There is a new Maven plugin, com.broadleafcommerce.microservices:ms-upgrade-maven-plugin
, that can greatly reduce the burden of manually applying many of the required boilerplate changes.
When run, the plugin will automatically apply various changes to your source code that you can subsequently verify and commit. For more information about the upgrade tool with instructions, see Automated upgrade tool documentation.
Due to the nature of AuthenticationServices and the upgrade from Spring Security 5 to Spring Security 6, it is likely that any customizations to AuthenticationServices will need a more substantial migration than what the upgrade tool can do alone.
The Migration Notes below list the changes in AuthenticationServices 2.0. During your upgrade, consult the Migration Notes for more information about problems you encounter. Some things that may affect the migration:
Moved or renamed classes
Deleted classes (see Removals)
New Spring Security classes for OAuth2 authorization server functionality (see Authentication Providers and Configuration)
Refactored web security configuration (see Security Configuration)
One key difference between the OAuth2.1 and OAuth2.0 specifications is how redirect URLs are validated. In OAuth2.1, redirect URLs on an authentication request must have an exact match on one of the registered client’s redirect URLs. With Broadleaf, we want to support this requirement, but also ease the transition for a client. We added a flag in AuthorizedClient to allow for relaxed redirect URL validation.
With relaxed redirect URL validation, when converting Broadleaf’s AuthorizedClient to Spring’s RegisteredClient, the redirect URLs are expanded with allowed variants. For instance, adding variants that include a trailing slash; also adding variants that are all lower-case. By expanding the registered URLs with these known variants, we make it easier on clients without sacrificing security.
AuthorizedClient
has a flag relaxRedirectUrisValidation
(default true) that controls whether the redirect URLs are expanded. The actual expansion logic is in DefaultAuthorizedClientService.preProcessRedirectUris
.
Another new requirement on redirect URLs from the OAuth2.1 specification is that redirect URLs must be absolute and not relative. One result of that is that Springs RedirectResolver
is no longer necessary, and further, our customizations to redirect resolution are no longer necessary. Redirect resolving logic has been removed from OAuth2AuthenticationEntryPoint
, and the OAuthRedirectHelper
has been deleted.
As a consequence of this change, the redirect URL on the authorization request should include any necessary port numbers. Previously, port numbers were automatically applied to the redirect based on the host name in the request URL. Now the port number should be included in the redirect URL.
Previously, AuthorizedClient only had fields redirectUris
and defaultRedirectUri
to specify any redirects that were allowed for any flow. Crucially, this meant that redirects for OAuth flows were mixed with redirects for authentication success and logout.
In the new version, we have added new fields to AuthorizedClient to better support the multiple reasons a user might need to be redirected. The new fields are `
postLogoutRedirectUris` and postAuthenticationSuccessRedirectUris
. Here are all the redirect URI related fields on AuthorizedClient:
redirectUris - Now specifically for Authorization Grant Flow redirects. May be relative, in which case it will be expanded to an absolute URL during validation.
postAuthenticationSuccessRedirectUris - New field for redirect URIs used after login. May be relative.
postLogoutRedirectUris - New field for redirect URIs used after logout.
defaultRedirectUri - Existing field to indicate a default redirect URI to use if no other redirect URI is available. For a storefront client, this would generally be the homepage URL.
Note:
The existing values in redirectUris
are used as the initial values for postAuthenticationSuccessRedirectUris
. After migration, these fields should be pruned such that redirectUris
only contains URIs for OAuth Authorization Grant redirects, and postAuthenticationSuccessRedirectUris
only contains URIs for post-login destinations.
Note:
You may need to add new values to postAuthenticationSuccessRedirectUris
, as the DefaultClientRedirectService
no longer allows arbitrary relative values. If a relative redirectUri parameter is sent with a login request, that relative URI must be registered in postAuthenticationSuccessRedirectUris
.
Previously, Spring Security provided the interface org.springframework.security.oauth2.provider.token.TokenEnhancer
to enable customizing JWT access tokens. That interface has been removed from Spring Security. Spring Authorization Server delegates to a single OAuth2TokenCustomizer
bean to handle access token customization.
Broadleaf has added the DefaultTokenCustomizer
which delegates to a List of JwtAccessTokenEnhancer
to customize access tokens. Our new JwtAccessTokenEnhancer
interface fills the gap left by the removal of Spring’s TokenEnhancer
. All of our existing TokenEnhancers
have been migrated to JwtAccessTokenEnhancer
. If you have added any additional TokenEnhancers
, they should be migrated as well.
There are a few differences between Spring’s TokenEnhancer
and our JwtAccessTokenEnhancer
. Instead of operating directly on a token, a context object (TokenEnhancerContext
) is used to hold authentication and claim information during token customization. Here are some tips on migrating your token enhancers:
Instead of using the authentication
parameter, use TokenEnhancerContext#getPrincipal()
.
Instead of getting an "enhanceable token" and putting new claims in the additionalInformation
map, use context.getClaims().claim()
to register new claims on the token.
Compare the previous com.broadleafcommerce.auth.user.session.token.enhancer.CustomerSegmentsTokenEnhancer
to the new com.broadleafcommerce.auth.user.session.token.enhancer.CustomerSegmentsAccessTokenEnhancer
to see an example of a straightforward migration.
Previously, in the Access Token Response, the Spring Security OAuth Server included most of the access token claims in the plaintext JSON object with the access token. The Spring Authorization Server does not include any envelope fields by default. The TokenEndpointFilterPostProcessor
has been added to facilitate adding claims from the access token to the JSON envelope.
The OAuth2 grant flow implementations in Spring Authorization Server have significant differences from the ones in the deprecated Spring Security OAuth2 library.
In Spring Authorization Server, each grant type has its own AuthenticationFilter. The filters delegate to member beans to perform the authorization logic. There are 2 types of these beans that are especially important to us:
An AuthenticationConverter
to convert the request parameters into a token
An AuthenticationProvider
to evaluate the token and mark authorized if it meets requirements
The package com.broadleafcommerce.auth.authorization.security.spring
contains AuthenticationConverters
and AuthenticationProviders
for each of the authorization grant flows supported by Broadleaf AuthenticationServices. These are applied to the security configuration via the OAuth2AuthorizationServerConfigurerCustomizer
.
See also Authorization Server Configuration.
The classes for Embedded Login have been moved to the package com.broadleafcommerce.auth.authorization.security.embedded
. The bean definitions have been moved to EmbeddedLoginAutoConfiguration
. All embedded login functionality is gated behind the property broadleaf.auth.login.embedded.enabled
. The components have been refactored to fit the new patterns in Spring Authorization Server.
Important
|
As noted in the section discussing PKCE is not supported when using embedded login, so please see the configuration recommendations in the embedded login documentation to ensure it is disabled appropriately. |
Spring Security 6 removes WebSecurityConfigurerAdapter and AuthorizationServerConfigurerAdapter in favor of creating SecurityFilterChain beans as needed. Additionally, the new Spring Authorization Server further changes how web security should be configured. Because of this, Broadleaf has significantly refactored and enhanced the web security and filter chain configuration.
The beans and logic from AuthorizationServerWebSecurityConfiguration
have largely been migrated to SecurityAutoConfiguration
. This class configures the SecurityFilterChain for authentication (authenticationSecurityFilterChain
). This chain is responsible for the login form and also any request not handled by other SecurityFilterChains.
The authenticationSecurityFilterChain
can be customized with an EarlyAuthenticationSecurityChainCustomizer
or LateAuthenticationSecurityChainCustomizer
. These Customizers
accept an HttpSecurity
parameter. All beans of these types will be injected as a list and executed iteratively.
SpringAuthorizationServerComponentsConfiguration
creates a SecurityFilterChain for authorization (authorizationServerSecurityFilterChain
). This chain is responsible for the OAuth grant flows.
SpringAuthorizationServerComponentsConfiguration.authorizationServerSecurityFilterChain
delegates to multiple other configurer beans.
EarlyAuthorizationServerSecurityChainCustomizer
and LateAuthorizationServerSecurityChainCustomizer
- all beans of these types will be injected as a list and executed at the beginning or end of the security chain configuration.
OAuth2AuthorizationServerConfigurer
- org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer
- Spring’s authorization server configurer. It is essentially a map that holds other configurers.
AuthorizationServerTokenGeneratorConfigurationCustomizer
- Extension point to customize the OAuth2TokenGenerator used to generate access and refresh tokens.
AuthorizationServerAuthenticationFilterConfigurationCustomizer
- Add session filter to Authorization SecurityFilterChain.
OAuth2AuthorizationServerConfigurerCustomizer
- A customizer for Spring’s OAuth2AuthorizationServerConfigurer
. Spring’s configurer handles the configuration for the OAuth2 endpoints, such as the authorization endpoint and the token endpoint. Each endpoint has its own configurer, and we utilize these to set our specialized AuthenticationConverters and AuthenticationProviders for each grant type. Broadleaf’s OAuth2AuthorizationServerConfigurerCustomizer
exposes extension points to allow implementors to customize authorization server beans and logic.
By using customizers and configurers, Broadleaf enables implementors to simply override framework beans to customize authorization behavior.
Note: If your AuthenticationServices app has an extension of AuthorizationServerWebSecurityConfiguration
to add a ForwardedHeaderFilter
to the HttpSecurity
, that entire class can now be replaced by these two beans:
@Bean
public LateAuthenticationSecurityChainCustomizer forwardHeaderFilterContributorAuthentication() {
return http -> http.addFilterAfter(new ForwardedHeaderFilter(), HeaderWriterFilter.class);
}
@Bean
public LateAuthorizationServerSecurityChainCustomizer forwardHeaderFilterContributorAuthorizationServer() {
return http -> http.addFilterAfter(new ForwardedHeaderFilter(), HeaderWriterFilter.class);
}
Due to the move to Spring Authorization Server, adding the oid
to a refresh token is now handled by the AdvancedOAuth2RefreshTokenGenerator
.
Additionally, the format of the refresh token is now an opaque string, instead of a signed JWT value.
The SecurityService
and DefaultSecurityService
were significantly refactored.
Rename public methods to more clearly indicate what they do
Do not use the SecurityContext to get User’s authorities. Expect all data to be passed as arguments.
Refactor logic into discrete methods to facilitate extensions.
Broadleaf’s AuthorizedClient
and JpaAuthorizedClient
have significant changes.
As discussed above, there are additional fields for registering allowed redirect URIs. The new fields are `
postLogoutRedirectUris` and postAuthenticationSuccessRedirectUris
. Here are all the redirect URI related fields on AuthorizedClient:
redirectUris - Now specifically for Authorization Grant Flow redirects. May be relative, in which case it will be expanded to an absolute URL during validation.
postAuthenticationSuccessRedirectUris - New field for redirect URIs used after login. May be relative.
postLogoutRedirectUris - New field for redirect URIs used after logout.
defaultRedirectUri - Existing field to indicate a default redirect URI to use if no other redirect URI is available. For a storefront client, this would generally be the homepage URL.
Note:
The existing values in redirectUris
are used as the initial values for postAuthenticationSuccessRedirectUris
. After migration, these fields should be pruned such that redirectUris
only contains URIs for OAuth Authorization Grant redirects, and postAuthenticationSuccessRedirectUris
only contains URIs for post-login destinations.
Note:
You may need to add new values to postAuthenticationSuccessRedirectUris
, as the DefaultClientRedirectService
no longer allows arbitrary relative values. If a relative redirectUri parameter is sent with a login request, that relative URI must be registerded in postAuthenticationSuccessRedirectUris
.
With Spring Authorization Server, there is a new server object that holds the client’s configuration data, such as client id and allowed scopes. Previously, the ClientDetails
class was used. Now, Spring Authorization Server uses RegisteredClient
instead. Broadleaf’s AuthorizationServer class has been updated to convert to a RegisteredClient. Similarly, the ClientDetailsService has been replaced with the RegisteredClientRepository
.
The new boolean authoritativeResourceIds
controls whether the system default resource IDs are included in access tokens created for this client. When false (default), any resource ids listed in AuthorizedClient.resourceIds
will be included with the system default resource ids when issuing tokens. If authoritativeResourceIds
is set to true, then only the resource ids configured in AuthorizedClient.resourceIds
will be included in the token.
Here is a quick list of all the new fields available on AuthorizedClient:
clientIdIssuedAt
clientSecretExpiresAt
authCodeTimeoutSeconds
authoritativeResourceIds
clientAuthenticationMethods
requireAuthorizationConsent
relaxRedirectUrisValidation
postAuthenticationSuccessRedirectUris
postLogoutRedirectUris
proofKeyRequired
Previously, PKCE behavior was gated on the property broadleaf.auth.security.pkce-enabled
.
Now, PKCE is configured on a per-client basis through this field.
This field defaults to null
(unset), which is interpreted as true
by the system by default.
This effectively enables PKCE by default on all clients.
Additionally, the unused field refreshTokenRotationIntervalSeconds was removed from JpaAuthorizedClient.
Spring Authorization Server uses the org.springframework.security.oauth2.server.authorization.OAuth2Authorization
object to encapsulate data related to a user’s authorization, such as client name, principal name, authorized scopes, and access token. Broadleaf provides JpaOAuth2Authorization
to store that in the new table, oauth2_authorization
. See the Auth Data Model for more information.
Handling cryptographic keys for signing and verifying JWTs has been consolidated and streamlined. Previously, there were a few different places that would read the encoded key values from properties and build the key instances they needed. Now, this logic has been consolidated to the classes DynamicPropertyPublicKey
and DynamicPropertyPrivateKey
, for public and private keys, respectfully. Additionally, we now provide a DynamicPropertyKeyJWKSource
bean that can be used by any component to retrieve the current encryption keys.
Our customized AuthorizationCodeServices
has been removed in favor of the default Authorization Code functionality from Spring Authorization Server.
Our customized OAuth2TokenEndpointAuthenticationFilter
has been removed in favor of the default OAuth2TokenEndpointAuthenticationFilter
from Spring Authorization Server.
It was possible during registration of a new user from a 3rd Party OAuth2 provider that the randomly generated password did not pass validation. The interface PasswordGenerator
and implementation DefaultPasswordGenerator
have been added to facilitate generating random password values.
Fixed bug where a deleted customer cannot register with the same email address
Archived the auth user if the corresponding customer is archived
Removed unique database constraint from user’s email and username, so that archived records can be ignored when checking if an email is already registered