{"action":"created","issue":{"url":"https://api.github.com/repos/spring-projects/spring-security/issues/5226","repository_url":"https://api.github.com/repos/spring-projects/spring-security","labels_url":"https://api.github.com/repos/spring-projects/spring-security/issues/5226/labels{/name}","comments_url":"https://api.github.com/repos/spring-projects/spring-security/issues/5226/comments","events_url":"https://api.github.com/repos/spring-projects/spring-security/issues/5226/events","html_url":"https://github.com/spring-projects/spring-security/issues/5226","id":313446556,"number":5226,"title":"Provide Resource Server Configurer","user":{"login":"jzheaux","id":3627351,"avatar_url":"https://avatars0.githubusercontent.com/u/3627351?v=4","gravatar_id":"","url":"https://api.github.com/users/jzheaux","html_url":"https://github.com/jzheaux","followers_url":"https://api.github.com/users/jzheaux/followers","following_url":"https://api.github.com/users/jzheaux/following{/other_user}","gists_url":"https://api.github.com/users/jzheaux/gists{/gist_id}","starred_url":"https://api.github.com/users/jzheaux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jzheaux/subscriptions","organizations_url":"https://api.github.com/users/jzheaux/orgs","repos_url":"https://api.github.com/users/jzheaux/repos","events_url":"https://api.github.com/users/jzheaux/events{/privacy}","received_events_url":"https://api.github.com/users/jzheaux/received_events","type":"User","site_admin":false},"labels":[{"id":322225080,"url":"https://api.github.com/repos/spring-projects/spring-security/labels/New%20Feature","name":"New Feature","color":"eeeeee","default":false},{"id":555556091,"url":"https://api.github.com/repos/spring-projects/spring-security/labels/OAuth2","name":"OAuth2","color":"000000","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/spring-projects/spring-security/milestones/106","html_url":"https://github.com/spring-projects/spring-security/milestone/106","labels_url":"https://api.github.com/repos/spring-projects/spring-security/milestones/106/labels","id":2988875,"number":106,"title":"5.1.0.M2","description":"","creator":{"login":"rwinch","id":362503,"avatar_url":"https://avatars0.githubusercontent.com/u/362503?v=4","gravatar_id":"","url":"https://api.github.com/users/rwinch","html_url":"https://github.com/rwinch","followers_url":"https://api.github.com/users/rwinch/followers","following_url":"https://api.github.com/users/rwinch/following{/other_user}","gists_url":"https://api.github.com/users/rwinch/gists{/gist_id}","starred_url":"https://api.github.com/users/rwinch/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rwinch/subscriptions","organizations_url":"https://api.github.com/users/rwinch/orgs","repos_url":"https://api.github.com/users/rwinch/repos","events_url":"https://api.github.com/users/rwinch/events{/privacy}","received_events_url":"https://api.github.com/users/rwinch/received_events","type":"User","site_admin":false},"open_issues":58,"closed_issues":1,"state":"open","created_at":"2017-12-19T14:42:44Z","updated_at":"2018-04-22T01:25:57Z","due_on":"2018-06-25T07:00:00Z","closed_at":null},"comments":0,"created_at":"2018-04-11T18:55:57Z","updated_at":"2018-04-24T17:46:19Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"### Summary\r\n\r\n`HttpSecurity` should support the configuration of an application to operate as a resource server, e.g.\r\n\r\n```java\r\nhttp\r\n    .oauth2().resourceServer()\r\n```\r\n\r\nRelates to #4887"},"comment":{"url":"https://api.github.com/repos/spring-projects/spring-security/issues/comments/384020615","html_url":"https://github.com/spring-projects/spring-security/issues/5226#issuecomment-384020615","issue_url":"https://api.github.com/repos/spring-projects/spring-security/issues/5226","id":384020615,"user":{"login":"jzheaux","id":3627351,"avatar_url":"https://avatars0.githubusercontent.com/u/3627351?v=4","gravatar_id":"","url":"https://api.github.com/users/jzheaux","html_url":"https://github.com/jzheaux","followers_url":"https://api.github.com/users/jzheaux/followers","following_url":"https://api.github.com/users/jzheaux/following{/other_user}","gists_url":"https://api.github.com/users/jzheaux/gists{/gist_id}","starred_url":"https://api.github.com/users/jzheaux/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jzheaux/subscriptions","organizations_url":"https://api.github.com/users/jzheaux/orgs","repos_url":"https://api.github.com/users/jzheaux/repos","events_url":"https://api.github.com/users/jzheaux/events{/privacy}","received_events_url":"https://api.github.com/users/jzheaux/received_events","type":"User","site_admin":false},"created_at":"2018-04-24T17:46:19Z","updated_at":"2018-04-24T17:46:19Z","author_association":"CONTRIBUTOR","body":"I'm moving the discussion about the structure if the DSL here. I'll begin with a restatement of what I last \"officially\" proposed and then explain some revisions, which are based on team feedback.\r\n\r\n### Initial Proposal\r\n\r\nA typical minimal configuration would look like this under the current proposal:\r\n\r\n```java\r\nhttp\r\n    .oauth2().resourceServer()\r\n        .accessTokens()\r\n            .formats().jwt();\r\n```\r\n\r\nAnd a complete configuration would look like this:\r\n\r\n```java\r\nhttp\r\n    .oauth2().resourceServer()\r\n        .bearerTokenResolver(customBearerTokenResolver())\r\n        .accessTokens()\r\n            .verifiers()\r\n                .signature().keys(\"file:///the-location-of-my-key\")\r\n                .encryption().keys(\"http://a-remote-jwks-uri\")\r\n                .addVerifier(customTokenVerifier()).and()\r\n            .formats()\r\n                .jwt().processor(customJwtProcessor()).and()\r\n                .opaque().processor(customOpaqueTokenProcessor());\r\n```\r\n\r\n### Updated proposal\r\n\r\nA number of changes have been suggested, and rather than try and represent everyone's feedback perfectly, I'll invite them to comment on the following updated idea, which incorporates the points that, at least for me, made sense:\r\n\r\n```java\r\nhttp\r\n    .oauth2().resourceServer()\r\n        .jwt()\r\n            .signature().keys(\"https://jwks.json\");\r\n```\r\nor \r\n```java\r\nhttp\r\n    .oauth2().resourceServer()\r\n        .bearerTokenResolver(customBearerTokenResolver())\r\n        .jwt()\r\n            .processor(customJwtProcessor())\r\n            .verifiers(oneCustomVerifier(), anotherCustomVerifier());\r\n```\r\nThe above would be a highly custom circumstance where the code needs to customize the way the bearer token is resolved from the request, the way the token is processed into a verified JWT, and has custom ways for verifying the resulting JWT. Verifying now needs to be couched underneath the format because the verifier contract is typed by the token format.\r\n\r\n### Do we need `processor()`?\r\n\r\nOne concern that was brought up was whether or not `processor` was strictly necessary. I think we could also do something like the following and address my concern, if a little less readably:\r\n\r\n```java\r\nJwtAccessTokenAuthenticationProvider provider =\r\n    new JwtAccessTokenAuthenticationProvider(customJWTProcessor(), customVerifiers());\r\n\r\nhttp\r\n    .oauth2().resourceServer()\r\n        .jwt(provider);\r\n```\r\n\r\nThe argument for stuff like this has been that it makes so that we can stick with spec language in the DSL while still allowing folks to provide custom implementations that may not read like the spec.\r\n\r\nFor example, we may need an authorities mapper in `JwtAccessTokenAuthenticationProvider`, but authorities mapper is not \"spec language\". So instead of having `.jwt().authoritiesMapper(customAuthoritiesMapper())`, I would instantiate the provider outside of the DSL and provide it in `jwt(JwtAccessTokenAuthenticationProvider)`.\r\n\r\nEven with that, though, I would assert that the way that a token is turned into a Java type *is* what the JWT spec refers to with the term \"processing\". So, I don't see:\r\n\r\n```java\r\nhttp.oauth2().resourceServer().jwt().processor(customJWTProcessor())\r\n```\r\n\r\nas a departure from spec language.\r\n\r\n### Minimal Example\r\n\r\nA more typical example would look like:\r\n\r\n```java\r\nhttp\r\n    .oauth2().resourceServer()\r\n        .jwt()\r\n            .signature().keys(\"https://jwks.json\");\r\n```\r\n\r\nWhere the configurer would know that it is a URL instead of a raw key by parsing the string. Note that `.signature()` and `.processor()` would be mutually exclusive as \"process\" implies a complete take-over of how to translate the token into a Java type.\r\n\r\n### `jwkSetUri()`\r\n\r\nAnother view of this same approach is:\r\n\r\n```java\r\nhttp\r\n    .oauth2().resourceServer()\r\n        .opaque()\r\n            .introspectionEndpoint(url(\"https://introspector\").connectionTimeout(30000))\r\n            .verifiers(customVerifier())\r\n            .and()\r\n        .jwt()\r\n            .signature()\r\n                .algorithm(\"EC521\")\r\n                .keys(url(\"https://jwks.json\").readTimeout(30000));\r\n```\r\n\r\nI'm advocating that the jwks URI not be elevated to the same level as the introspection URI because it seems to me that there are may ways to retrieve the signature verification key, JWK being just one of many, though, I wouldn't mind supporting `jwkSetUri` as well as `signature`, the first implying a stronger Spring Security opinion than the second, sort of in the same way that `processor` would be a still weaker opinion than both `jwkSetUri` and `signature`.\r\n\r\n### `accessTokens()` layer\r\n\r\nI'm still going back and forth with `accessTokens()`, which is an extra layer between `resourceServer()` and `jwt()`, `opaque()`, and `verifiers()`. Is it unnecessary typing for the user? `http.oauth2().resourceServer().jwt()` has the same feel as `http.httpBasic()`. We wouldn't do `http.credentials().httpBasic()`, which is why, for now, I lean towards removing `accessTokens()` (and `formats()` also, for the same reason)."}}
{"actor":{"display_login":"jzheaux"}}