microsoft / kiota-java

Java libraries for Kiota-generated API clients.
https://aka.ms/kiota/docs
MIT License
27 stars 29 forks source link

Oidc Access Token Provider #771

Open andreaTP opened 1 year ago

andreaTP commented 1 year ago

I have now implemented quite a few times OidcTokenAccessProvider, for example here.

Despite it being almost trivial in the end user codebase it turns out that is difficult to refactor the mechanism up to this repository. More specifically the challenges are:

I'm here looking for guidance on how we can approach the problem. I have attempted at first to add an initialize method to AccessTokenProvider and to AuthenticationProvider so that it can be eventually triggered by the RequestAdapter implementation. I started having too many things to pull in and thought that it was not a great design ...

baywet commented 1 year ago

Thanks for starting the conversation here. Have you considered standing a new package like we have azure identity today? This way you could pull the require dependencies, and use a native http client.

andreaTP commented 1 year ago

Right, standing an external package's always viable, still I think that it doesn't, easily, enable all of the scenarios. E.g.: it's still going to be tricky to share the native client between the "standard" HTTP calls and the authentication layer.

In addition it might cause issues on the user's classpath, I love how Kiota separates the concerns and you end up with very minimal dependencies; providing an external library locks the user to specific core libraries or they are going to end up with multiple HTTP client, serialization libraries etc.

andreaTP commented 11 months ago

Sorry for the delay, I have not forgotten about this, but I wanted to try out a different approach to see how it plays out.

The consideration I have made is:

Hence we can directly leverage the specific HTTP Client, built-in, authentication implementation. The biggest downside would be fragmentation in the ecosystem, but, if there are no alternatives other than having to re-write the authentication provider implementation for the different HTTP Client, I think, it's the most pragmatic option.

I have experimented with this approach and the Vert.X client, here you can see how it looks like from a user's perspective.

Thoughts?

andreaTP commented 11 months ago

Just to state it explicitly, my favorite option would be to have a Kiota Auth layer that can be reused across implementations. I appreciate that the current design doesn't easily allow for this use-case, but in this case, I prefer to rely on the "native" authentication mechanism instead of having to re-write it in a non-portable way.

baywet commented 11 months ago

Thanks for providing more context here. I don't think I have a strong opinion for people using:

In my experience, while "easy" and already existing, authentication providers that are tied to the http client often lack features:

All those features can be provided by the underlying authentication library we'd be using to implement the different authentication scenarios (like a generic OIDC lib for java for example), or in a generic way through a proxy design pattern in kiota's abstractions.

But I agree that building authentication providers across languages is a big task, on the other hand, if we don't do it, it'll add friction to people using kiota clients to talk to their favorite API.

I think a first step would be to:

From there we should see where customers demand takes us: do they want more "first party" authentication providers for additional scenarios (basic, API key, cookie, NTLM/kerberos, OIDC, certificate exchange, etc...), an eco-system of third party providers, the client to be somehow already generated with authentication setup for them, something else?

What do you think?

andreaTP commented 11 months ago

authentication providers that are tied to the http client often lack features

Correct, I agree, but, at the same time, the current API is limiting the opportunity to write generic AuthenticationProviders, especially for very valid use-cases like OIDC. In addition, the current design makes it difficult to do some things like sharing the same Http client etc. etc.

or in a generic way through a proxy design pattern in kiota's abstractions

I'm interested in hearing more about this!

I think a first step would be to:

I agree that we need some more documentation on this aspect, but I don't think that we should "officially" state that people can mix and match options for authentication. Authentication is a notoriously time consuming task, and, in my experience, people expect to have something opinionated and pre-built to be used.

I'm all in for collecting community, user and customer feedback on this aspect, but I think that we have to make an opinionated call here and decide either:

Taking any in-between position is likely going to cause fragmentation in the ecosystem and overall confusion, at least in my opinion.

baywet commented 11 months ago

or in a generic way through a proxy design pattern in kiota's abstractions

Implementing token caching generically for all oauth providers would only be a matter of re-implementing AuthenticationProvider, while accepting an AuthenticationProvider as a constructor argument, as well as a couple of settings (how to build the cache key from the request information with things like path/query parameters/headers) . This implementation would then:

  1. forward the call to the original implementation on the first call.
  2. build the key based of the settings.
  3. store the token in the cache (let's suppose in memory for that implementation).
  4. on a subsequent request, build the key again, and try to get an entry from the cache with that key.
  5. return the cached token instead of forwarding the call.

(there are a couple of additional aspects with www-authenticate headers, token valid periods, etc... but this is the gist of it).

I understand the challenge, in terms of fragmentation of the ecosystem. Getting the funding to build a bunch of authentication providers on our end will be challenging at best. This is why I wanted to rely on the community and partners to bridge the gaps here. But it we don't provide:

  1. guidelines to API consumers on their options.
  2. guidelines to contributors on how to contribute authentication providers.
  3. a way for API consumers to discover those providers.

It's not going to happen. looping in @sebastienlevert for visibility