-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
fix(oauth2): prevent an authorization code created by one plugin instance to be exchanged for an access token by a different plugin instance #10011
Conversation
03e33cf
to
8af6631
Compare
Related PR: #9312 |
8af6631
to
f4d82a7
Compare
@@ -2360,7 +2374,7 @@ describe("Plugin: oauth2 [#" .. strategy .. "]", function() | |||
assert.same({ error_description = "code_verifier is required for PKCE authorization requests", error = "invalid_request" }, json) | |||
end) | |||
it("success when no code_verifier provided for public app without pkce when conf.pkce is none", function() | |||
local code = provision_code() | |||
local code = provision_code("oauth2_14.com") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the test to use the same oauth2 plugin instance
f4d82a7
to
e531f38
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some grammar and spelling issues to be fixed.
d4708e5
to
c7cd10e
Compare
c844358
to
1a047a0
Compare
This is most certainly a breaking change since it is very much possible that a user could be relying on such buggy behavior. |
kong/plugins/oauth2/daos.lua
Outdated
@@ -79,6 +79,7 @@ local oauth2_authorization_codes = { | |||
{ scope = { type = "string" }, }, | |||
{ challenge = { type = "string", required = false }}, | |||
{ challenge_method = { type = "string", required = false, one_of = { "S256" } }}, | |||
{ plugin_id = { type = "string", required = false } }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we make this a foreign key?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, and sounds good to me.
kong/plugins/oauth2/access.lua
Outdated
@@ -643,6 +644,15 @@ local function issue_token(conf) | |||
end | |||
end | |||
|
|||
if not response_params[ERROR] and conf.global_credentials then | |||
if kong.plugin.get_id() ~= auth_code.plugin_id then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we handle entries added before the migration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that would be a problem. I updated it to become only validate if auth_code.plugin_id
is present to make the old code pass the validation.
Discussed this today with @kikito. He will circle back on this one. |
@hbagdi I agree with @vm-001 that the current behavior is buggy. I cannot imagine a customer relying on the current behavior. As a reminder, here is a depiction of the OAuth2 authorization flow: The user first creates an authorization grant (authentication code) using the service of the OAuth2 identity provider. It then presents the authentication code to the authorization server, which exchanges it for an access token. That token can then be used to authenticate against the resource server. I believe that we can assume that our users use the OAuth2 plugin in the "normal way": A user hits a service that is protected by OAuth2 and that redirects them to the IdP. The IdP issues the authentication code and redirects the user back to the same service, in which Kong plays the authentication server role. Kong exchanges the authentication code for an access token and returns it to the client for further interaction with the resource server. I cannot imagine a situation in which a user would willingly want to be able to have Kong exchange the authentication code issued when trying to access one service by another service. It seems to me that this would only happen if there is an error in the application (i.e. the OAuth2 related responses are not properly interpreted, making the token request go to a different service) or by malicious intent (i.e. an attacker has access to a less-privileged service and uses the bug to exchange an authentication code by that less-privileged service to a token issued by a more-privileged service). I am not confident that the fix in this PR will solve all such problems, but I'm certain that we don't want to leave such gaps open if we know about them. The PR does not currently pass checks because of an incompatibility with Cassandra. This will need to be fixed. I also have the question whether |
b75551b
to
8693bc8
Compare
…ance to be exchanged for an access token by a different plugin instance
8693bc8
to
a86239d
Compare
I think the |
…ance to be exchanged for an access token by a different plugin instance (#10011) * fix(oauth2): prevent an authorization code created by one plugin instance to be exchanged for an access token by a different plugin instance * verify only if plugin_id is present to avoid existing codes being fails * add test case * change plugin_id field type from text to uuid * make plugin_id to be foreign key * fix merge issue * fix cassandra script (cherry picked from commit 8c4e5c6)
…ance to be exchanged for an access token by a different plugin instance (#10011) * fix(oauth2): prevent an authorization code created by one plugin instance to be exchanged for an access token by a different plugin instance * verify only if plugin_id is present to avoid existing codes being fails * add test case * change plugin_id field type from text to uuid * make plugin_id to be foreign key * fix merge issue * fix cassandra script (cherry picked from commit 8c4e5c6)
Summary
Forbid an authorization code can be exchanged to access_token in different plugin instance.
Checklist
Issue reference
FTI-3983