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

Add configuration support for Opaque Token authentication #15872

Closed
jzheaux opened this issue Feb 7, 2019 · 12 comments

Comments

Projects
None yet
5 participants
@jzheaux
Copy link
Contributor

commented Feb 7, 2019

In Spring Security 5.2.0.M2, users can configure the OAuth 2.0 Resource Server to validate opaque tokens through Introspection:

http
    .oauth2ResourceServer()
        .opaqueToken();

It would be nice if this could be property-driven, e.g.:

spring:
  security:
    oauth2:
      resourceserver:
        opaque-token:
          introspection-uri: https://endpoint
          client-id: client_id
          client-secret: client_secret

Then, Spring Boot could register an instance of OAuth2TokenIntrospectionClient:

@Bean 
public OAuth2TokenIntrospectionClient introspectionClient() {
    return new NimbusOAuth2TokenIntrospectionClient(uri, clientId, clientSecret);
}

Note that this configuration is only valid if OAuth2IntrospectionAuthenticationToken is on the classpath.

@jzheaux jzheaux changed the title Add properties for Opaque Token support Add configuration support for Opaque Token authentication Feb 7, 2019

@mbhave

This comment has been minimized.

Copy link
Contributor

commented Feb 7, 2019

@jzheaux Would it possible to validate JWTs using the introspection endpoint or is it just for opaque tokens?

@mbhave mbhave added this to the 2.2.x milestone Feb 7, 2019

@jgrandja

This comment has been minimized.

Copy link

commented Feb 8, 2019

@mbhave

Would it possible to validate JWTs using the introspection endpoint

Yes, the spec does mention this so some providers may support accepting JWT's on Introspect Endpoint

@jzheaux

This comment has been minimized.

Copy link
Contributor Author

commented Feb 8, 2019

@mbhave

or is it just for opaque tokens?

In this case, a JWT is an opaque token. The resource server, when using opaque tokens, is not concerned with its underlying format. It obtains the contents of the token only through the introspection response.

@mbhave

This comment has been minimized.

Copy link
Contributor

commented Feb 8, 2019

@jgrandja I know the spec mentions this, my question was more about does Spring Security support it.

In this case, a JWT is an opaque token.

@jzheaux I wonder if that terminology might be confusing to users. We have a oauth2ResourceServer().jwt() and .oauth2ResourceServer().opaqueToken() where the opaque token could be a JWT.

@jzheaux

This comment has been minimized.

Copy link
Contributor Author

commented Feb 8, 2019

@mbhave That might not have been the clearest way for me to put it, let me try again here.

An opaque token is simply a token whose format the resource server doesn't care about. Sure, it could be a JWT, but it could also be internal and proprietary.

To state oauth2ResourceServer().jwt() means that the user expects the tokens to be JWTs and thus intends to verify and inspect them himself (that is, locally). This implication is clear from both the JWT spec and the Introspection spec. The resulting instance in Spring Security is always a Jwt.

And oauth2ResourceServer().opaqueToken() means that the user expects tokens whose contents he won't inspect or verify himself. This is implied by the word "opaque", and is a word commonly associated with this verification strategy. The resulting instance in Spring Security is always an OAuth2AccessToken.

Regarding the spec, it only mentions JWTs in the introduction as a means to explain the rationale for the spec. It does not indicate JWTs as an expected use case for introspection. In fact, the spec calls out that JWT is a means of inspection independent of any remote endpoint:

Since OAuth 2.0 does not define a protocol for the resource server to learn
meta-information about a token that it has received from an
authorization server, several different approaches have been
developed to bridge this gap. These include using structured token
formats such as JWT
[RFC7519] or proprietary inter-service
communication mechanisms (such as shared databases and protected
enterprise service buses) that convey token information.

Thus, the case for using opaqueToken() (remote verification) with JWTs (local verification) is possible but unlikely: Why would I accept a JWT, which can be inspected locally, only to inspect it remotely?

Does that help? If not, could you help me see more clearly where the spots are for potential confusion?

@mbhave

This comment has been minimized.

Copy link
Contributor

commented Feb 8, 2019

Thanks @jzheaux. I do understand opaqueToken is expected to be used when the user wants to use the introspection endpoint rather than validating the token themselves and it could be JWT or proprietary.

Taking the example that you've linked to, there is a distinction between the two kinds of tokens. For JWTs, it states that

They are self-contained in that it is not necessary for the recipient to call a server to validate the token.

My feeling is that for users who choose to use the introspection endpoint for JWTs, it might be confusing that there is a jwt namespace and an opaqueToken namespace but for JWT introspection, they'd use the properties under opaqueToken and not jwt.

Why would I accept a JWT, which can be inspected locally, only to inspect it remotely?

Possibly because if you inspect the token yourself, you most likely cache the keys and there's a chance of the keys being out of sync with the authorization-server. So you'd rather always validate it with the authorization-server.

I think the main point I want to make is I don't see an opaque token as something whose format the resource server doesn't care about but more as something that is not a self-contained token. Having the opaqueToken property also apply to JWTs seems a bit odd to me but if I'm the only one that feels that way, we can go ahead with what you've proposed.

@jzheaux

This comment has been minimized.

Copy link
Contributor Author

commented Feb 8, 2019

I think the main point I want to make is I don't see an opaque token as something whose format the resource server doesn't care about but more as something that is not a self-contained token.

This distinction is why I would suppose that the 95% case is that the user would pick jwt() if it is a JWT, and opaqueToken() if it is opaque. It would be a little odd to want to use introspection to verify JWTs since they are self-contained. This seems the simplest way to guide the user down the right configuration path.

My feeling is that for users who choose to use the introspection endpoint for JWTs, it might be confusing that there is a jwt namespace and an opaqueToken namespace but for JWT introspection, they'd use the properties under opaqueToken and not jwt.

I suppose if a user wanted to explicitly state that they are using JWTs and wanted to stick with the JWT format (e.g. get a Jwt instance from Spring Security), but still wanted to verify them remotely, that's possible via:

@Bean
public JwtDecoder jwtDecoder() {
    return new MyRemoteIntrospectingJwtDecoder();
}

which would be like the hypothetical security.oauth2.resourceserver.jwt.introspection-uri.

Spring Security does not yet support something like this--getting a Jwt back from an Introspection endpoint--so there wouldn't be a configuration of HttpSecurity that Boot could form to support it, but may be an option if it turns out to be a common use case.

@mbhave

This comment has been minimized.

Copy link
Contributor

commented Mar 11, 2019

The corresponding changes in Spring Security will be available in 5.2.0.M2 which is scheduled for April 15th at the time of writing. Boot 2.0.0.M2 is scheduled for April 9th so we'll have to wait for M3 to do this one.

@mbhave mbhave self-assigned this Apr 12, 2019

@mbhave

This comment has been minimized.

Copy link
Contributor

commented Apr 17, 2019

@jzheaux mentioned that they're looking at finding a new home for client id and secret. I'll mark this one as blocked till then.

@wilkinsona

This comment has been minimized.

Copy link
Member

commented May 24, 2019

@jzheaux Is there an issue we can keep an eye on for client id and secret finding a new home?

@jzheaux

This comment has been minimized.

Copy link
Contributor Author

commented May 31, 2019

Sorry, @wilkinsona, I failed to state that I'd updated the ticket with our updated recommendation.

The recommendation originally was:

introspection-uri: ...
introspection-client-id: ...
introspection-client-secret: ...

which @mbhave correctly pointed out feels pretty redundant. I think a better setup is:

introspection-uri: ...
client-id: ...
client-secret: ...

Is this a workable solution?

@mbhave

This comment has been minimized.

Copy link
Contributor

commented May 31, 2019

That makes sense to me. I've unblocked the issue.

@mbhave mbhave removed the status: blocked label May 31, 2019

@mbhave mbhave modified the milestones: 2.2.x, 2.2.0.M4 Jun 10, 2019

@mbhave mbhave closed this in 2560b54 Jun 10, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.