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

fix(openid-connect): the default 'redirect_uri' (#2426) #7690

Merged
merged 9 commits into from
Dec 22, 2023

Conversation

liweitianux
Copy link
Contributor

Description

Previously the redirect_uri was set to ngx.var.request_uri if not
configured. However, it caused the underlying lua-resty-openidc
module to raise this error:

request to the redirect_uri path but there's no session state found

because lua-resty-openidc would think it was the redirection response
from OP when the redirect_uri equals ngx.var.request_uri.

Although the OAuth 2.0 Security Best Current Practice [1] recommends
that the redirect_uri should be explicitly specified to prevent
malicious redirection attacks, it would also be handy for APISIX to
properly determine a default one if redirect_uri not given.

Therefore, append the .apisix/redirect suffix to the current request
URI to determine the default redirect_uri. It makes
lua-resty-openidc happy and it's almost unlikely to conflict with
user's URIs.

Also note that the OP should be properly configured to accept such
auto-determined redirect URIs.

Update the documentation accordingly.

Fix #2426.

[1] https://datatracker.ietf.org/doc/draft-ietf-oauth-security-topics/

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible (If not, please discuss on the APISIX mailing list first)

Previously the `redirect_uri` was set to `ngx.var.request_uri` if not
configured.  However, it caused the underlying `lua-resty-openidc`
module to raise this error:

```
request to the redirect_uri path but there's no session state found
```

because `lua-resty-openidc` would think it was the redirection response
from OP when the `redirect_uri` equals `ngx.var.request_uri`.

Although the OAuth 2.0 Security Best Current Practice [1] recommends
that the `redirect_uri` should be explicitly specified to prevent
malicious redirection attacks, it would also be handy for APISIX to
properly determine a default one if `redirect_uri` not given.

Therefore, append the `.apisix/redirect` suffix to the current request
URI to determine the default `redirect_uri`.  It makes
`lua-resty-openidc` happy and it's almost unlikely to conflict with
user's URIs.

Also note that the OP should be properly configured to accept such
auto-determined redirect URIs.

Update the documentation accordingly.

Fix apache#2426.

[1] https://datatracker.ietf.org/doc/draft-ietf-oauth-security-topics/
@@ -198,3 +198,4 @@ In this example, the Plugin can enforce that the access token, the ID token, and

- `redirect_uri` needs to be captured by the route where the current APISIX is located. For example, the `uri` of the current route is `/api/v1/*`, `redirect_uri` can be filled in as `/api/v1/callback`;
- `scheme` and `host` of `redirect_uri` (`scheme:host`) are the values required to access APISIX from the perspective of the identity provider.
- See also [this GitHub issue](https://github.com/apache/apisix/issues/2426), especially these comments: [@starsz](https://github.com/apache/apisix/issues/2426#issuecomment-1091021687), [@david-woelfle](https://github.com/apache/apisix/issues/2426#issuecomment-1090675455), [@liweitianux (1)](https://github.com/apache/apisix/issues/2426#issuecomment-1206107085), [@liweitianux (2)](https://github.com/apache/apisix/issues/2426#issuecomment-1207423283)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you write the conclusion in a short sentence, instead of multiple reference links?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- See also [this GitHub issue](https://github.com/apache/apisix/issues/2426), especially these comments: [@starsz](https://github.com/apache/apisix/issues/2426#issuecomment-1091021687), [@david-woelfle](https://github.com/apache/apisix/issues/2426#issuecomment-1090675455), [@liweitianux (1)](https://github.com/apache/apisix/issues/2426#issuecomment-1206107085), [@liweitianux (2)](https://github.com/apache/apisix/issues/2426#issuecomment-1207423283)
- `redirect_uri` should not be the same as the URI of the route. This is because when a user initiates a request to visit the protected resource, the request directly hits the redirection URI with no session cookie in the request, which leads to the `no session state found` error.

@spacewander spacewander requested a review from starsz August 16, 2022 06:14
@@ -65,7 +65,7 @@ local schema = {
},
redirect_uri = {
type = "string",
description = "use ngx.var.request_uri if not configured"
description = "auto append '.apisix/redirect' if not configured"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it cannot make sure the new URI will be matched by the same route, it actually adds an implicit condition that the route match type is prefix instead of exact.

Copy link
Contributor Author

@liweitianux liweitianux Aug 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well. If the route is of type exact, then it cannot actually use this openid-connect plugin, because the redirect_uri must be different from the request URI, as required by lua-resty-openidc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liweitianux Could you write some hints about this in the OpenID Connect doc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I'll update the doc later.

Copy link
Contributor

@starsz starsz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @liweitianux .Can you add a test case to cover it ?

Comment on lines +266 to +281
-- NOTE: 'lua-resty-openidc' requires that 'redirect_uri' be
-- different from 'uri'. So default to append the
-- '.apisix/redirect' suffix if not configured.
local suffix = "/.apisix/redirect"
local uri = ctx.var.uri
if core.string.has_suffix(uri, suffix) then
-- This is the redirection response from the OIDC provider.
conf.redirect_uri = uri
else
if string.sub(uri, -1, -1) == "/" then
conf.redirect_uri = string.sub(uri, 1, -2) .. suffix
else
conf.redirect_uri = uri .. suffix
end
end
core.log.debug("auto set redirect_uri: ", conf.redirect_uri)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When there is no conf.redirect_uri, it looks like we generate redirect_uri for each request(except for the real redirect from IdP).

Can we inject a default value for redirect_uri when we add the openid-connect plugin.

For example:

  1. we require that the match condition for a road has to be a prefix match, like /openid/*, then redirect_uri defaults to /openid/.apisix/redirect.

Listen to what others say.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liweitianux any thoughts about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we can set a proper default value for redirect_uri, because a plugin can be configured globally, per-route, and per-service. An exception is that the openid-connect plugin is configured for a specific route, so we can determine a redirect_uri that's covered by the route.

Please correct me if I'm mistaken.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a test case to show that not providing redirect_uri works fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the job this year, and I haven't been working with APISIX for more than one year now. I'm unfamiliar with the test framework, and that was the main reason that this PR was lacking a test case. It would be great if you can rejuvenate this PR. Thanks.

@github-actions
Copy link

This pull request has been marked as stale due to 60 days of inactivity. It will be closed in 4 weeks if no further activity occurs. If you think that's incorrect or this pull request should instead be reviewed, please simply write any comment. Even if closed, you can still revive the PR at any time or discuss it on the [email protected] list. Thank you for your contributions.

@github-actions github-actions bot added the stale label Oct 17, 2022
@github-actions
Copy link

This pull request/issue has been closed due to lack of activity. If you think that is incorrect, or the pull request requires review, you can revive the PR at any time.

@monkeyDluffy6017
Copy link
Contributor

Please resolve the conflicts and make the ci pass

@monkeyDluffy6017 monkeyDluffy6017 changed the title fix(openid-connect): Fix the default 'redirect_uri' (#2426) fix(openid-connect): the default 'redirect_uri' (#2426) Nov 29, 2023
@shreemaan-abhishek shreemaan-abhishek self-assigned this Dec 1, 2023
@luoluoyuyu
Copy link
Contributor

luoluoyuyu commented Dec 3, 2023

Hi @liweitianux @shreemaan-abhishek @monkeyDluffy6017
Can I perfect this PR work?

@shreemaan-abhishek
Copy link
Contributor

@luoluoyuyu sure.

@luoluoyuyu
Copy link
Contributor

luoluoyuyu commented Dec 3, 2023

@shreemaan-abhishek
It seems I don't have permission to add commits. @liweitianux can you open the permission。

@shreemaan-abhishek
Copy link
Contributor

@liweitianux could you invite @luoluoyuyu with access to your repo?

@liweitianux
Copy link
Contributor Author

liweitianux commented Dec 4, 2023

@liweitianux could you invite @luoluoyuyu with access to your repo?

Hi, @luoluoyuyu and @shreemaan-abhishek, I've invited both of you to my repo. Thank you.

local httpc = http.new()
local uri = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello"
local res, err = httpc:request_uri(uri, {method = "GET"})
ngx.say(res.status)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant code

local res, err = httpc:request_uri(uri, {method = "GET"})
ngx.say(res.status)
if res.status == 400 then
ngx.say(res.status)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the response_body was true

@moonming moonming merged commit c7d406d into apache:master Dec 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bug:enable openid-connect plugin without redirect_uri got 500 error