Skip to content

Authorization Granted Events sample cannot work as documented #19584

Description

@patbaumgartner

Summary

The Authorization Granted Events section documents a capability that SpringAuthorizationEventPublisher does not have. The sample also does not compile.

Source: docs/modules/ROOT/pages/servlet/authorization/events.adoc

The sample does not compile

@Bean
AuthorizationEventPublisher authorizationEventPublisher() {
    SpringAuthorizationEventPublisher eventPublisher = new SpringAuthorizationEventPublisher();
    eventPublisher.setShouldPublishEvent((result) -> { ... });
    return eventPublisher;
}

Two issues against main:

  1. new SpringAuthorizationEventPublisher() — the only constructor is SpringAuthorizationEventPublisher(ApplicationEventPublisher).
  2. setShouldPublishEvent(...) — the method is setShouldPublishResult(Predicate<AuthorizationResult>) (@since 7.0). It looks like the rename landed but the docs were not updated.

The bigger problem: the predicate cannot produce granted events

Even with both names corrected, the sample cannot do what the surrounding prose promises — "the following publisher only publishes authorization grants where ROLE_ADMIN was required".

publishAuthorizationEvent only ever constructs AuthorizationDeniedEvent:

public <T> void publishAuthorizationEvent(Supplier<Authentication> authentication, T object,
        @Nullable AuthorizationResult result) {
    if (result == null) {
        return;
    }
    if (!this.shouldPublishResult.test(result)) {
        return;
    }
    AuthorizationDeniedEvent<T> failure = new AuthorizationDeniedEvent<>(authentication, object, result);
    this.eventPublisher.publishEvent(failure);
}

AuthorizationGrantedEvent is imported but never instantiated. So a predicate that returns true for a granted result publishes an AuthorizationDeniedEvent carrying a granted AuthorizationResult, not an AuthorizationGrantedEvent. A listener on AuthorizationGrantedEvent never fires.

The class Javadoc agrees with the code, and contradicts the reference docs:

Because AuthorizationGrantedEvents typically require additional business logic to decide whether to publish, this implementation only publishes AuthorizationDeniedEvents.

I verified this empirically on 7.1.1: with a corrected predicate returning true for an AuthorityAuthorizationDecision where granted=true, a @RecordApplicationEvents test observed zero AuthorizationGrantedEvents. Implementing AuthorizationEventPublisher directly and publishing AuthorizationGrantedEvent works.

Possible resolutions

Either could be right, hence an issue rather than a PR:

  1. Docs-only — rewrite the section to say granted events require your own AuthorizationEventPublisher, and show that instead. Also fix the constructor and setShouldPublishResult name.
  2. Code — make SpringAuthorizationEventPublisher.publishAuthorizationEvent emit AuthorizationGrantedEvent when result.isGranted() and the predicate passes. That would make the existing documentation correct and give setShouldPublishResult an obvious purpose, since today it can only suppress denied events.

Happy to submit a PR for whichever direction you prefer.

Minor

The same page has a typo in the intro: "It comes publishes authorization events using Spring's ApplicationEventPublisher".

Context

Found while reconciling a Spring Security training lab against the 7.1 reference docs. Related but separate: #19583 fixes two non-compiling calls in the observability docs.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions