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

Support per-client configuration of token type (opaque/jwt) #3392

Closed
4 of 6 tasks
sgal opened this issue Dec 21, 2022 · 6 comments · Fixed by #3446
Closed
4 of 6 tasks

Support per-client configuration of token type (opaque/jwt) #3392

sgal opened this issue Dec 21, 2022 · 6 comments · Fixed by #3446
Assignees
Labels
feat New feature or request.

Comments

@sgal
Copy link
Contributor

sgal commented Dec 21, 2022

Preflight checklist

Describe your problem

We have a login solution based on Hydra that serves both internal clients (meaning oauth2 clients) and external clients.

For internal clients, we have an existing codebase that is built around JWT tokens that is hard to migrate to opaque. These clients also use internal identifiers as subjects in access tokens.

For external clients, we would like to use the pairwise subjects feature and opaque tokens that come with it.

We also want to have Single Sign On support between internal/external clients.

Currently, Hydra only supports a global configuration of token types, which prevents us from enabling the pairwise subjects feature for external clients, while keeping internal clients unchanged.

Describe your ideal solution

It would be great to be able to configure token type per client, similar to how it is done with token TTL values. With that, our internal clients would stay on JWT tokens and internal identifiers as subjects, and we could also enable external clients with pairwise subjects and opaque tokens.

Workarounds or alternatives

  1. Switch all clients to opaque tokens and implement an opaque -> JWT translation layer for internal clients. This solution forces us to use a separate token issuer for JWT tokens.
  2. Migrate all clients to opaque tokens. This is a massive migration for us, with around 500 services involved and infrastructure not really built around introspection calls.

Version

2.x

Additional Context

No response

@sgal sgal added the feat New feature or request. label Dec 21, 2022
@igorcavalcante
Copy link

It's a very interesting matter, I am working on a oidc solution with a load fo 50M users and spikes of 30k full auth cylces persecond, do claim checks like expiration dates via introspection is something to be avoided.

@aeneasr
Copy link
Member

aeneasr commented Dec 29, 2022

There are two ways to address this from a client perspective:

  1. Have a per-client configuration for the resulting token type
  2. Add a parameter to the consent flow which decides which token type to send

I think the first option is easier to implement than the second option. Currently, we switch the token strategy based on the config here:

switch ats := t.c.AccessTokenStrategy(ctx); ats {
case config.AccessTokenJWTStrategy:
return t.jwt
}
return t.hmac

If the requester

func (t TokenStrategy) GenerateAccessToken(ctx context.Context, requester fosite.Requester) (token string, signature string, err error) {

contains the client, we could potentially use that as an override for the strategy here

func (t TokenStrategy) gs(ctx context.Context) foauth2.CoreStrategy {
switch ats := t.c.AccessTokenStrategy(ctx); ats {
case config.AccessTokenJWTStrategy:
return t.jwt
}
return t.hmac
}

However, I'm not sure how that would impact the subject identifier verification. Currently, validation seems to happen in these places:

p.l.Warn(`The pairwise subject identifier algorithm is not supported by the JWT OAuth 2.0 Access Token Strategy and is thus being disabled. Please remove "pairwise" from oidc.subject_identifiers.supported_types" (e.g. oidc.subject_identifiers.supported_types=public) or set strategies.access_token to "opaque".`)

func (s *DefaultStrategy) ObfuscateSubjectIdentifier(ctx context.Context, cl fosite.Client, subject, forcedIdentifier string) (string, error) {
if c, ok := cl.(*client.Client); ok && c.SubjectType == "pairwise" {
algorithm, ok := s.r.SubjectIdentifierAlgorithm(ctx)[c.SubjectType]
if !ok {
return "", errorsx.WithStack(fosite.ErrInvalidRequest.WithHintf(`Subject Identifier Algorithm '%s' was requested by OAuth 2.0 Client '%s' but is not configured.`, c.SubjectType, c.GetID()))
}
if len(forcedIdentifier) > 0 {
return forcedIdentifier, nil
}
return algorithm.Obfuscate(subject, c)
} else if !ok {
return "", errors.New("Unable to type assert OAuth 2.0 Client to *client.Client")
}
return subject, nil
}

So any change to this logic would require end-to-end tests to ensure that the behavior is correct.

@sgal
Copy link
Contributor Author

sgal commented Dec 29, 2022

I think option 1 would be more scalable for flows that do not use consent, like jwt-bearer. I'm not sure if pairwise support is needed there, seems like an extreme edge case. But token type would be great to have in that grant type.

@aeneasr
Copy link
Member

aeneasr commented Dec 29, 2022

The problem is that we need to validate for these edge cases, because otherwise the behavior is incorrect, which could potentially imply that we'll fail OpenID certification. So while it is an edge case, it has to be considered and properly handled :)

@sgal
Copy link
Contributor Author

sgal commented Dec 29, 2022

I think we're on the same page here. rfc7523 is only oAuth2 and it has no mention of pairwise or any other subject obfuscation, so would it break the OIDC certification if we skip pairwise there?

@aeneasr
Copy link
Member

aeneasr commented Dec 29, 2022

I'm not quite sure if I understand, in this feature request we would issue JWT access tokens for OAuth2 Clients that asks us to do so. That impacts all OAuth2 and OpenID Connect flows, which is we need to make sure that they behave according to spec.

We can also limit this feature to RFC7523 only, but I think we could solve this for the general use case "this client should get JWT access tokens".

@hperl hperl linked a pull request Mar 1, 2023 that will close this issue
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat New feature or request.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants