You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First, let's a big thank you for you great support and library 👏
I implemented a directive-based authentication with Spring Security.
This issue related to #663#692 where the code/examples were taking as a starting point
An important difference to the example from previous issues: securityContext is a Mono<SecurityContext>)
The implementation for the Authorisation checking:
/** * Wraps the original Data Fetcher * Check the Security Context for the required roles*/classAuthorizationDataFetcher(
/** * Original Data fetcher which should be executed*/privatevaloriginalDataFetcher:DataFetcher<Any>,
/** * Required Roles for this Data Fetcher Field*/privatevalrequiredRoles:Collection<String>
) : DataFetcher<Any> {
overridefunget(environment:DataFetchingEnvironment): Any {
if (requiredRoles.isEmpty()) {
return originalDataFetcher.get(environment)
}
val context:GraphQLSecurityContext?= environment.getContext<GraphQLSecurityContext>()
val securityContext:Mono<SecurityContext> =
context?.securityContext ?:throwAccessDeniedException("SecurityContext not present")
val accessCheck = checkRoles(securityContext)
return accessCheck
.filter { it.isGranted }
.map { createResult(originalDataFetcher.get(environment)) }
.switchIfEmpty(Mono.just(createGraphQLError(environment)))
.toFuture() // FIXME: how to avoid .block() also not allowed
}
privatefuncheckRoles(securityContext:Mono<SecurityContext>): Mono<AuthorizationDecision> {
val voter = hasAnyAuthority<Any>(*requiredRoles.toTypedArray())
return voter.check(securityContext.map { it.authentication }, null).defaultIfEmpty(AuthorizationDecision(false))
}
privatefuncreateGraphQLError(environment:DataFetchingEnvironment): DataFetcherResult<Any> {
val error =SimpleKotlinGraphQLError(
AccessDeniedException("Role(s) ${requiredRoles.joinToString(separator =",")} required"),
listOf(environment.field.sourceLocation),
environment.executionStepInfo.path.toList()
)
returnDataFetcherResult.newResult<Any>()
.error(error)
.build()
}
privatefuncreateResult(data:Any): DataFetcherResult<*> {
returnDataFetcherResult.newResult<Any>()
.data((data as?CompletableFuture<*>)?.get() ?: data) // FIXME: how to avoid
.build()
}
}
To problem/thing I don't like:
How to properly Map the ´Mono` (which could be a mono of any type to indicate Authorization result.
Instead of .toFuture().block()would return the actual value of original data fetcher => which throws block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2",
If the orginalDataFetcher is FunctionDataFetcher it return CompletableFuture
The text was updated successfully, but these errors were encountered:
I'd recommend to NOT store the Mono and instead store the underlying object, e.g. use null (getOrDefault(xyz, null)) or Optional<SecurityContext> (getOrEmpty(xyz)) instead. This would allow you to await for value in the factory. With the unwrapped value in the GraphQL context, you could still do the same logic in your AuthorizationDataFetcher (i.e. throw AccessDeniedException if it is not present).
First, let's a big thank you for you great support and library 👏
I implemented a directive-based authentication with Spring Security.
This issue related to
#663 #692 where the code/examples were taking as a starting point
Factory for the Security Context:
An important difference to the example from previous issues:
securityContext
is aMono<SecurityContext>)
The implementation for the Authorisation checking:
To problem/thing I don't like:
How to properly Map the ´Mono` (which could be a mono of any type to indicate Authorization result.
.toFuture()
.block()
would return the actual value of original data fetcher => which throwsblock()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2",
The text was updated successfully, but these errors were encountered: