Broadleaf Microservices
  • v1.0.0-latest-prod

Auth Release Notes for 2.0.0-GA

Upgrade Guide

Liquibase Change Sets

The database schema has changed as part of this version.

'Create/Update' Changes

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

db/changelog/auth.postgresql.changelog-master.xml

MariaDB

db/changelog/auth.mariadb.changelog-master.xml

MySQL

db/changelog/auth.mysql.changelog-master.xml

Oracle

db/changelog/auth.oracle.changelog-master.xml and db/changelog/auth.oracle.short.changelog-master.xml

YugabyteDB

db/changelog/auth.yugabytedb.changelog-master.xml

Cases Requiring Manual Verification
Important

In this particular release, some of the automated upgrade migration changesets produce results that may require further verification. Please review this section carefully.

Client secrets defined through application properties

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 authorization_code for a small minority of AuthorizedClients. The vast majority would be using client_credentials. Thus, the number of rows to audit should be fairly small.

Furthermore, typical BLC deployments would more often use authorization_code in public clients rather than confidential clients. Thus, the migration script will most likely make the right changes in most scenarios, and actual corrections required should be small.

  1. 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')
  2. 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

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:

Example 1. How to include drop changelogs in your *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

db/changelog/auth.postgresql.drop.changelog-2.0.0.xml

MariaDB

db/changelog/auth.mariadb.drop.changelog-2.0.0.xml

MySQL

db/changelog/auth.mysql.drop.changelog-2.0.0.xml

Oracle

db/changelog/auth.oracle.drop.changelog-2.0.0.xml

YugabyteDB

db/changelog/auth.yugabytedb.drop.changelog-2.0.0.xml

Upgrade Tool

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.

Upgrade tool with AuthenticationServices

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:

Migration Notes

Redirect URIs

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.

Resolving Redirect URLs in the AuthenticationEntryPoint

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.

More specific redirect URI fields

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.

JWT Access Token Enhancers

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.

Migrating to JwtAccessTokenEnhancer

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.

Authorities

The authorities claim of the access token is now added with the AuthoritiesAccessTokenEnhancer, instead of internally in Spring Security.

Access Token Envelope Fields

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.

Authentication Providers and Configuration

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.

Embedded Login and Authorization

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 AuthorizedClient changes, there is a new proofKeyRequired field that is interpreted as true by default.

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.

Security Configuration

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.

Authentication

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.

Authorization

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.

ForwardedHeaderFilter

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);
}

Refresh Tokens

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.

SecurityService

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.

AuthorizedClient

Broadleaf’s AuthorizedClient and JpaAuthorizedClient have significant changes.

Redirect URI fields

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.

RegisteredClient

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.

Authoritative Resource Ids

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.

New Fields

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.

Authorization Persistence

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.

Cryptographic Key Management

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.

Removals

  • 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.

Bug Fixes

  • 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