Skip to content

Add configuration support for Opaque Token authentication #15872

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

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

Add configuration support for Opaque Token authentication #15872

jzheaux opened this issue Feb 7, 2019 · 12 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@jzheaux
Copy link
Contributor

jzheaux 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.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Feb 7, 2019
@jzheaux jzheaux changed the title Add properties for Opaque Token support Add configuration support for Opaque Token authentication Feb 7, 2019
@mbhave
Copy link
Contributor

mbhave 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 type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Feb 7, 2019
@mbhave mbhave added this to the 2.2.x milestone Feb 7, 2019
@jgrandja
Copy link

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

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

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

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

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

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

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

mbhave 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.

@mbhave mbhave added the status: blocked An issue that's blocked on an external project change label Apr 17, 2019
@wilkinsona
Copy link
Member

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

@jzheaux
Copy link
Contributor Author

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

mbhave commented May 31, 2019

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

@mbhave mbhave removed the status: blocked An issue that's blocked on an external project change label May 31, 2019
@mbhave mbhave modified the milestones: 2.2.x, 2.2.0.M4 Jun 10, 2019
@mbhave mbhave closed this as completed in 2560b54 Jun 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants