Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oidc Access Token Provider #771

Open
andreaTP opened this issue Nov 6, 2023 · 7 comments
Open

Oidc Access Token Provider #771

andreaTP opened this issue Nov 6, 2023 · 7 comments
Labels
java Pull requests that update Java code
Milestone

Comments

@andreaTP
Copy link
Contributor

andreaTP commented Nov 6, 2023

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:

  • Access to an HttpClient (or RequestAdapter but I think there are a few gaps later on) - possibly we should be able to decide to use the same or a different one from the "normal" API calls
  • encode a form body is pretty straightforward with a bare HTTP client, not sure how that looks like with bare Kiota without the generated classes
  • decode a Json response
  • etc...

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
Copy link
Member

baywet commented Nov 6, 2023

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
Copy link
Contributor Author

andreaTP commented Nov 7, 2023

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
Copy link
Contributor Author

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:

  • the AuthenticationProvider needs to be specific for an HTTP Client
  • most mature HTTP Client implementations already offer some way to deal with authentication

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
Copy link
Contributor Author

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
Copy link
Member

baywet commented Nov 23, 2023

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

  • An implementation of AuthenticationProvider.
  • AnonymousProvider + some special configuration of their http client.

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

  • token caching (potentially needs to be distributed depending on which app we're talking about)
  • token challenges (when the service sends you back a 401 with www-authenticate header because your token has been invalidated, doesn't have the right permissions, something else changed like the geolocation of the user...)
  • are not portable between http clients by nature.
  • can't be generated with the client. (generating the auth setup is not something we've given up on, but OpenAPI needs to evolve if we're going to do that)

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:

  • document the different providers we have across languages
  • document the middleware aspect
  • document the fact you can provide your own native client to the request adapter, with a set of configurations.
  • provide some conceptual documentation linking things together and outlining options for authentication.

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
Copy link
Contributor Author

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:

  • Change the current API layer for Auth so that, possibly all, of the use cases can be covered optimally with it
  • Drop the Auth aspect in abstractions as "yet another" partial implementation

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

@baywet
Copy link
Member

baywet commented Nov 23, 2023

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

@github-project-automation github-project-automation bot moved this to Todo in Kiota Jan 19, 2024
@sebastienlevert sebastienlevert added the java Pull requests that update Java code label Jan 19, 2024
@sebastienlevert sebastienlevert added this to the Backlog milestone Jan 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
java Pull requests that update Java code
Projects
Status: Todo 📃
Development

No branches or pull requests

3 participants