How to do workflow api authentication using jwt in java, please help me on this.i need required code changes for client ad server side for this?

how to do workflow api authentication using jwt in java, please help me on this.i need required code changes for client ad server side for this?

Have you already looked at Temporal Server security / Authorization?

@SergeyBykov
Yes, I have gone through this (Temporal Server security | Temporal)?
but i am using java sdk so i am looking for java library only, so i could make changes for client/server side changes in java lang only to achieve authentication.

I have found these but all are in go lang only
[common/authorization/authorizer.go]
[common/authorization/claimMapper.go]

i have found this sample git project to do authorizer but this is also in go lang

is java support for this is work in process or some exists in some other code base/documentation?

Authorizer and ClaimMapper are server plugin interfaces, and hence the plugins need to be written in Go. Default plugins, NewDefaultJWTClaimMapper() and NewDefaultAuthorizer(), we hope, cover most of the typical authorization scenarios or, worst case, can be tweaked to fit somebody’s needs easily.

You can use Java SDK to send Bearer tokens to the server for authorization via a gRPC interceptor.

@SergeyBykov Thanks for the quick response, I have some more questions on implementing JWT based authentication.

I am using the docker image and have gone through the information provided at customization-samples/extensibility/authorizer at master · temporalio/customization-samples · GitHub.

Do we have to build our own temporal image to enable golang plugins?

We do not use go lang for development, is it possible to enable authentication with some server configurations? Like some property/configuration files?

@SergeyBykov Could you please suggest the solution of my last query?
I am waiting for your response.Thanks.

In general, yes, building your own image is a more flexible way to configure Temporal server with all the available Server Options. To make cases like yours easier though, I’ll submit soon a long overdue PR for selecting noop or default authorizer and claim mapper via config settings.

I submitted a draft PR - Add config parameters for selecting authorizer and claim mapper by sergeybykov · Pull Request #1291 · temporalio/temporal · GitHub. Will work on getting it merged after we return from the long weekend.

PR has been merged.

1 Like

@SergeyBykov - is golang still the only option for server security plugins? Does providing a plugin require building our own instance of the server?

What is the current suggested approach for Java users to enable JWT-based auth on the temporal server?

What is the current suggested approach for Java users to enable alternate/custom auth on the temporal server?

Thank you

is golang still the only option for server security plugins?

Since server code is in Go, and Go plugins story is very limited even for plugins written in Go, this is the only feasible option at the moment.

Does providing a plugin require building our own instance of the server?

Yes, again primarily because of Go’s poor support for plugins.

What is the current suggested approach for Java users to enable JWT-based auth on the temporal server?

I see two options here.

  1. Implement the whole logic in Go. Conceptually, such logic is simple - comparing a set of claims to the ACL.
  2. Implement a proxy-like plugin that would channel calls to a separate JVM process via an IPC mechanism, and have that JVM process handle all the logic.

I’m biased towards option 1.

@SergeyBykov - thank you for the input.

If we wrote the plugins to support our JWT, how would we configure the Java client to send the Authorization header?

There is probably only one way to do that right now and it’s not ideal:
Implement two Grpc Stubs interceptors that set the right header and specify them in WorkflowServiceStubsOptions#Builder#setBlockingStubInterceptor and WorkflowServiceStubsOptions#Builder#setFutureStubInterceptor

It’s a little bit painful, I know. I submitted an issue to make it better: Add an easy way to provide JWT tokens to java-sdk for server calls · Issue #671 · temporalio/sdk-java · GitHub

@spikhalskiy - thank you for the tip.

What field in the WorkflowServiceStub do I need to modify to set the Authorization header? .withCallCredentials? .withOption? Something else?

Let me just implement a more straightforward Temporal Server JWT tokens support in Java SDK and it will become a part of the next SDK (1.3.0) release hopefully next week.

Temporal java-sdk 1.3.0 was just released with added simple support for Auth tokens.

  AuthorizationTokenSupplier tokenSupplier = //... your implementation of token supplier
  WorkflowServiceStubsOptions serviceStubOptions =
    WorkflowServiceStubsOptions.newBuilder()
      //...
      .addGrpcMetadataProvider(new AuthorizationGrpcMetadataProvider(tokenSupplier))
      .build();

@SergeyBykov, you may consider looking into Hashicorp’s go-plugin project (which I am looking for in my use case). It has a slight overhead as it uses gRPC to communicate between plugins, but you get dynamic pluggability and polyglot plugins in return.

Yes, we considered go-plugin. It’s a way to implement option 2 I mentioned above.

  1. Implement a proxy-like plugin that would channel calls to a separate JVM process via an IPC mechanism, and have that JVM process handle all the logic.

We couldn’t use it as a general purpose plugin mechanism because the overhead would be too big for popular use cases like authorization where the plugin is invoked on every request. But it can be used by one of the custom plugins if the overhead is acceptable for that use case.

1 Like

The AuthorizationGrpcMetadataProvider has protected constructor the below code wont work.
Is it a bug ?

AuthorizationTokenSupplier tokenSupplier = //… your implementation of token supplier
WorkflowServiceStubsOptions serviceStubOptions =
WorkflowServiceStubsOptions.newBuilder()
//…
.addGrpcMetadataProvider(new AuthorizationGrpcMetadataProvider(tokenSupplier))
.build();

I believe it was address in this PR.