jwt_authn: implementation of www-authenticate header#16216
jwt_authn: implementation of www-authenticate header#16216snowp merged 24 commits intoenvoyproxy:mainfrom
Conversation
|
Hi @cyran-ryan, welcome and thank you for your contribution. We will try to review your Pull Request as quickly as possible. In the meantime, please take a look at the contribution guidelines if you have not done so already. |
6fcf4d9 to
28f4153
Compare
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
28f4153 to
d298dac
Compare
| absl::StrJoin(absl::StrSplit(error_msg, ' '), "_"), "}"); | ||
| } | ||
|
|
||
| std::string buildUri(const Http::RequestHeaderMap& request_headers, |
There was a problem hiding this comment.
buildOriginalUri(). This could be move to source/common/http/utility. other modules may need this
There was a problem hiding this comment.
Agreed, I'll put up a change with that shortly
| code, ::google::jwt_verify::getStatusString(status), nullptr, absl::nullopt, | ||
| code, ::google::jwt_verify::getStatusString(status), | ||
| [uri = this->original_uri_](Http::ResponseHeaderMap& headers) { | ||
| headers.setCopy(Http::LowerCaseString("www-authenticate"), |
There was a problem hiding this comment.
Is it OK to send the same response for "token missing" case?
There was a problem hiding this comment.
So that's a tough one, it looks like from the OAuth 2.0 RFC (which seems to be the most analogous to this situation) the error field should be included if the token is rejected but not if it's missing. If we think that we just need to follow the 401 Unauthorized RFC, we just need realm to exist.
There was a problem hiding this comment.
By looking at OAuth 2.0 RFC, for invalid token, server SHOULD add error=.
How about:
for missing we just add "realm=", but for invalid token we also add error=. e.g. "realm=URI, error=invalid_token"
There was a problem hiding this comment.
Agreed! Working on that change today
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
|
You need to add some unit-test or integration tests for the change. |
Would it be necessary to write an entirely new test for this? Or is it sufficient to add checks in the 401 response integration tests? |
The latter is fine. As long as it cover both "missing" and "invalid_token" cases. |
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
| } | ||
| absl::string_view path(request_headers.EnvoyOriginalPath() | ||
| ? request_headers.getEnvoyOriginalPathValue() | ||
| : request_headers.getPathValue()); |
There was a problem hiding this comment.
will we have case "envoy-origin-path" exists but not "path"?
There was a problem hiding this comment.
It appears in the router config_impl, that if envoy-origin-path exists, it is set to the path value. So no, there should not be any possibility of envoy-origin-path existing but path not existing.
There was a problem hiding this comment.
That code in the router_config runs after headers make it to the router, so I don't think this will have been set at this point. On the other hand I think the check for Path is unnecessary because getPathValue() should return an empty string in that case. Digging into it some more, original-path is only set in for certain route actions, so there might not be a point in reading it at this point at all?
There was a problem hiding this comment.
Ping on this, I think we can simplify this logic
| namespace JwtAuthn { | ||
|
|
||
| namespace { | ||
| const std::string INVALID_TOKEN_ERROR_STRING = "invalid_token"; |
There was a problem hiding this comment.
prefer not to use std::string in static, can we use string_view, or char[]
There was a problem hiding this comment.
Swapped to string_view
| if (verifier == nullptr) { | ||
| onComplete(Status::Ok); | ||
| } else { | ||
| original_uri_ = Http::Utility::buildOriginalUri(headers, 256); |
There was a problem hiding this comment.
Where is 256 coming from? Should we define it somewhere?
There was a problem hiding this comment.
256 seemed to be a good length limit for URIs in the headers. There are no actual defined limits for how long headers can be, effectively though, many servers will limit the total amount of data headers can use to 8KiB or 16KiB. I'm up for discussion on how long we should allow the generated URI to be. And then yes, I think it's a good idea define the value rather than leaving it as a raw number.
There was a problem hiding this comment.
It is fine to just const define it.
| if (status != Status::JwtMissed) { | ||
| absl::StrAppend(&value, ", error=\"", INVALID_TOKEN_ERROR_STRING, "\""); | ||
| } | ||
| headers.setCopy(Http::LowerCaseString("www-authenticate"), value); |
There was a problem hiding this comment.
maybe define this LowerCaseString as singleton?
There was a problem hiding this comment.
How would you go about that? I've looked at a couple solutions but I run into issues with the fact that the filter can be constructed on multiple threads. We could do something with ThreadLocalStorage I suppose.
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
source/common/http/headers.h
Outdated
| const LowerCaseString Pragma{"pragma"}; | ||
| const LowerCaseString Referer{"referer"}; | ||
| const LowerCaseString Vary{"vary"}; | ||
| const LowerCaseString WwwAuthenticate{"www-authenticate"}; |
There was a problem hiding this comment.
You re-defined it. It is defined in line 215.
There was a problem hiding this comment.
Whoops, I looked at the comment on my phone and didn't notice that. Fixing now
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
|
Retrying Azure Pipelines: |
|
Ok the tests passed but I think the refactor of the tracing library caused the coverage % to drop down. Do you think you could add some dummy call to the functions not covered by tests as per https://storage.googleapis.com/envoy-pr/e4f1d82/coverage/source/common/tracing/index.html ? Should be relatively easy and should make CI go green |
That's understandable seeing as I removed a good chunk of covered code from those files. I'll work on these today. |
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
|
Retrying Azure Pipelines: |
|
Last question, we would like to cherrypick these changes to 1.18, and 1.17. This is for Istio to pull in for their release 1.9 and 1.10. Is this possible? |
|
Current policy limits backports to security and stability fixes I'm afraid. You can try to post an issue about it to discuss, though my knee jerk reaction is that this doesn't qualify. |
* main: listener: match rebalancer to listener IP family type (envoyproxy#16914) jwt_authn: implementation of www-authenticate header (envoyproxy#16216) listener: reset the file event in framework instead of listener filter doing itself (envoyproxy#17227) Small typo fix (envoyproxy#17247) Doc: Clarify request/response attributes are http-only (envoyproxy#17204) bazel/README.md: add aspell comment (envoyproxy#17072) docs: Fix broken URL links in HTTP upgrades doc (envoyproxy#17225) remove the wrong comment on test (envoyproxy#17233) upstream: allow clusters to skip waiting on warmup for initialization (envoyproxy#17179) JwtAuthn: support completing padding on forward jwt payload header (envoyproxy#16752) remove support for v2 UNSUPPORTED_REST_LEGACY (envoyproxy#16968) metrics service: fix wrong argument arrange on MetricsServiceSink (envoyproxy#17127) deps: update cel-cpp to 0.6.1 (envoyproxy#16293) Add ability to filter ConfigDump. (envoyproxy#16774) examples: fix Wasm example. (envoyproxy#17218) upstream: update host's socket factory when metadata is updated. (envoyproxy#16708) Signed-off-by: Garrett Bourg <bourg@squareup.com>
|
/backport |
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info> Co-authored-by: Lizan Zhou <lizan@tetrate.io> Signed-off-by: cyran-ryan <58446431+cyran-ryan@users.noreply.github.com>
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info> Co-authored-by: Lizan Zhou <lizan@tetrate.io> Signed-off-by: cyran-ryan <58446431+cyran-ryan@users.noreply.github.com> Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
… (envoyproxy#17441) Co-authored-by: Lizan Zhou <lizan@tetrate.io> Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info>
jwt_authn: implementation of www-authenticate header (envoyproxy#16216) (envoyproxy#17441)
Signed-off-by: Ryan Sutton <ryan.sutton@volunteers.acasi.info> Co-authored-by: Lizan Zhou <lizan@tetrate.io>
For an explanation of how to fill out the fields, please see the relevant section
in PULL_REQUESTS.md
Commit Message: Adds www-authenticate header to jwt_authn responses
Additional Description: Returns a valid www-authenticate header when deny a request with a 401 Unauthorized response, see RFC 7235 and RFC 6750 for information on the spec and error codes this response returns
Risk Level: Medium
Testing:
Docs Changes:
Release Notes:
Platform Specific Features:
[Optional Runtime guard:]
[Optional Fixes #Issue]
[Optional Deprecated:]
[Optional API Considerations:]