I have a problem setting up spring security and disabling/enabling access to jwt-authenticated role-based users for graphql
services. All other REST
endpoints are properly protected and JWT
authentication and role-based authorization are working correctly.
What I have so far:
In my WebSecurityConfigurerAdapter
class, I have following code:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().cors()
.and()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "**/student-service/auth/**").permitAll().antMatchers("**/student-service/auth/**").authenticated()
.and()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "**/graphql/**").permitAll().antMatchers("**/graphql/**").authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(entryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
http.headers().cacheControl();
}
And on graphql
service, I have a @PreAuthorize
:
@Component
public class UserResolver implements GraphQLQueryResolver{
@Autowired
UserRepo repo;
@PreAuthorize("hasAnyAuthority('ADMIN')")
public User findUser(int id) {
return User.builder()
.id(1)
.email("test@grr.la")
.password("123")
.username("John")
.bankAccount(BankAccount.builder()
.id(1)
.accountName("some account name")
.accountNumber("some account number")
.build())
.build();
}
}
After getting JWT on localhost:8080/login
and sending graphql
query, with above configuration and code, I got:
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:73) ~[spring-security-core-5.4.5.jar:5.4.5]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.attemptAuthorization(AbstractSecurityInterceptor.java:238) ~[spring-security-core-5.4.5.jar:5.4.5]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:208) ~[spring-security-core-5.4.5.jar:5.4.5]
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:58) ~[spring-security-core-5.4.5.jar:5.4.5]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.5.jar:5.3.5]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.5.jar:5.3.5]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.5.jar:5.3.5]
This is how request looks like from Postman
:
GraphQL query:
query {
findUser(id : 1) {
id
email
}
}
And response:
{
"errors": [
{
"message": "Access is denied",
"locations": [
{
"line": 2,
"column": 1
}
],
"path": [
"findUser"
],
"extensions": {
"type": "AccessDeniedException",
"classification": "DataFetchingException"
}
}
],
"data": {
"findUser": null
}
}
application.yml
file:
graphql:
servlet:
max-query-depth: 100
exception-handlers-enabled: true
playground:
headers:
Authorization: Bearer TOKEN
query.graphqls
file:
type Query {
findUser(id: ID): User
}
type User {
id: ID!
username: String
password: String
email: String
bankAccount: BankAccount
}
type BankAccount {
id: ID!
accountName: String
accountNumber: String
}