Skip to content

Document How to Handle Method Security in Native Image #13226

@asavov

Description

@asavov

Expected Behavior

Security SPEL (such as @PreAuthozied) needs custom native-image hints (such as @RegisterReflectionForBinding) when using/referring custom beans by SPEL.

The expectation is to enhance the doc, providing guidelines to consumers of SPEL support within Security.

Current Behavior

Security SPEL (such as @PreAuthozied) works out-of-the-box only for default beans managed by Spring framework.

Context

The problem is reproduced with this simplified snippet run within @jlong’s spring-boot-3-aot project as repro env.

@Configuration
@EnableMethodSecurity(prePostEnabled = true)

// It works in native-image if this line is uncommented
// @RegisterReflectionForBinding(CustomAuthenticationImpl.class)

public class SecurityConfiguration {

	public interface CustomAuthentication extends Authentication {

		boolean isCloudAdmin();
	}

	public static class CustomAuthenticationImpl extends TestingAuthenticationToken implements CustomAuthentication {

		static CustomAuthentication CLOUD_ADMIN = new CustomAuthenticationImpl(true);

		static CustomAuthentication NOT_CLOUD_ADMIN = new CustomAuthenticationImpl(false);

		private final boolean isCloudAdmin;

		private CustomAuthenticationImpl(boolean isCA) {
			super("alex-principle-" + (isCA ? "CA" : "nonCA"), "alex-credentials");
			this.isCloudAdmin = isCA;
		}

		@Override
		public boolean isCloudAdmin() {
			return isCloudAdmin;
		}

	}

	@Service
	public static class MyService {

		public String basicMethod() {
			return "OK";
		}

		// Use method on our CustomAuthentication which seems to need Hint
		@PreAuthorize("authentication.isCloudAdmin()")
		public String isCloudAdminMethod() {
			return "OK";
		}

	}

	@Bean
	ApplicationListener<ApplicationReadyEvent> withSecurity(MyService myService) {
		return event -> {
			SecurityContextHolder.getContext().setAuthentication(CustomAuthenticationImpl.NOT_CLOUD_ADMIN);

			System.out.println("[Security] basicMethod with NOT_CLOUD_ADMIN: " + myService.basicMethod());

			try {
				myService.isCloudAdminMethod();

				System.out.println("[Security] isCloudAdminMethod with NOT_CLOUD_ADMIN: should not happen");
			}
			catch (Exception e) {
				System.out.println("[Security] isCloudAdminMethod with NOT_CLOUD_ADMIN: was secured");
			}

			SecurityContextHolder.getContext().setAuthentication(CustomAuthenticationImpl.CLOUD_ADMIN);

			System.out.println("[Security] isCloudAdminMethod with CLOUD_ADMIN: " + myService.isCloudAdminMethod());
		};
	}

}

which works on JRE and fails on native-image with:

java.lang.IllegalArgumentException: Failed to evaluate expression 'authentication.isCloudAdmin()'
        at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:33) ~[na:na]
        at org.springframework.security.authorization.method.PreAuthorizeAuthorizationManager.check(PreAuthorizeAuthorizationManager.java:68) ~[na:na]
at Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1004E: Method call: Method isCloudAdmin() cannot be found on type com.example.aot.security.SecurityConfiguration$CustomAuthenticationImpl
        at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:225) ~[na:na]

Here's link to the slack channel discussion.

Metadata

Metadata

Labels

in: docsAn issue in Documentation or samplestype: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions