2

I am using the latest spring security 4 version and it introduces a new feature to use the logged in user details directly in the query method using expression language. Here is my spring data repository code:

public interface UserRepository extends JpaRepository<User, Long> {
    @Query("select username from User u where u.username = ?#{ principal?.username }")
    User findByUsername(String username);
}

In the above code, I have an entity User as below: @Entity @Table(name = "users")

public class User { 

    @Id
    @Column(name = "username", nullable = false, unique = true)
    private String username;
    @Column(name = "password", nullable = false)
    @NotNull
    private String password;
    @Column(name = "enabled", nullable = false)
    @NotNull
    private Boolean enabled;

    @Column(name = "role", nullable = false)
    @Enumerated(EnumType.STRING)
    private Role role;
    //getters and setters

Also I have this entry for enabling this feature:

@Bean
public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
    return new SecurityEvaluationContextExtension();
}

When I run the application, I get the error:

Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Authentication object cannot be null; nested exception is java.lang.IllegalArgumentException: Authentication object cannot be null
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:381)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417) 
Caused by: java.lang.IllegalArgumentException: Authentication object cannot be null
    at org.springframework.security.access.expression.SecurityExpressionRoot.<init>(SecurityExpressionRoot.java:46)
    at org.springframework.security.data.repository.query.SecurityEvaluationContextExtension$1.<init>(SecurityEvaluationContextExtension.java:113)
    at org.springframework.security.data.repository.query.SecurityEvaluationContextExtension.getRootObject(SecurityEvaluationContextExtension.java:113)
    at org.springframework.data.repository.query.ExtensionAwareEvaluationContextProvider$EvaluationContextExtensionAdapter.<init>(ExtensionAwareEvaluationContextProvider.java:463)
    at org.springframework.data.repository.query.ExtensionAwareEvaluationContextProvider.toAdapters(ExtensionAwareEvaluationContextProvider.java:210)
    at org.springframework.data.repository.query.ExtensionAwareEvaluationContextProvider.access$000(ExtensionAwareEvaluationContextProvider.java:58)

What could be the issue. Here I am posting to check if there is any issue in using the query method. Can i use like principal.username, is that correct?

Update: When I removed the @Query from repository it works fine. That means its problem with the new spring security 4 using principal.username. Is there anything wrong in this expression?

@Query("select username from User u where u.username = ?#{ principal?.username }")

3 Answers 3

1

Pls try this custom class :-

class SecurityEvaluationContextExtension extends  EvaluationContextExtensionSupport  {

  @Override 
  public String getExtensionId() { 
    return "Security"; 
  }

  @Override 
  public SecurityExpressionRoot getRootObject() { 
    Authentication authentication =  SecurityContextHolder.getContext().getAuthentication(); 
    return new SecurityExpressionRoot(authentication){}; 
  } 
}
Sign up to request clarification or add additional context in comments.

1 Comment

I have added this custom class. Then also its not working.
0

Not sure whether you have solved the issue in the meantime, but I noticed that your query should look like:

select u from User u where u.username = ?#{ principal }

assuming your principal object is the plain username String.

Comments

0

If you created your own SecurityEvaluationContextExtension class, and did not implement getAuthentication() method, you might be getting this exception.

In this link, you can see original SecurityEvaluationContextExtension.java file, that implements all necessary methods.

So, you don't need to implement this class on your own. Instead, you can add below dependency to your pom file to have the original one;

<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-data -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-data</artifactId>
    <version>4.2.1.RELEASE</version>
</dependency>

If you are using any other dependency manager rather than maven, you can goto related maven repo and get the definition that you want.

I hope this helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.