Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

make redirect uri validation case-insensitve #282

Merged
merged 5 commits into from
Mar 13, 2024

Conversation

fairclothjm
Copy link
Contributor

@fairclothjm fairclothjm commented Mar 12, 2024

Overview

This PR proposes to make the redirecut URI matching validation case-insensitive.

Background

An HVD user recently reported an issue where they could not log into the Vault UI using the OIDC auth method even when the URL was correct.

"Error: Missing auth_url. Please check that allowed_redirect_uris for the role include this mount path."

This was discovered when a customer had named their HVD cluster with capital letters (e.g. ABC-cluster).
When setting allowed_redirect_uris as a part of the OIDC setup process and then attempting to login to the Vault UI, the browser automatically transforms the login URL to all-lowercase, causing the URL to not match the configured allowed_redirect_uris.

Impact

This issue affects users whose clusters IDs have capital letters in them and are trying to login via OIDC in the Vault UI.

Tests

Confirmed that the new tests fail before the change was implemented

=== RUN   TestOIDC_AuthURL
=== RUN   TestOIDC_AuthURL/case_insensitive
=== PAUSE TestOIDC_AuthURL/case_insensitive
=== CONT  TestOIDC_AuthURL/case_insensitive
2024-03-12T15:48:16.578-0500 [WARN]  unauthorized redirect_uri: redirect_uri=https://EXAMPLE.com
    path_oidc_test.go:166: expected auth_url "" to match regex: client_id=abc
--- FAIL: TestOIDC_AuthURL (0.33s)
    --- FAIL: TestOIDC_AuthURL/case_insensitive (0.00s)
=== RUN   TestOIDC_ValidRedirect
    path_oidc_test.go:1582: Fail on https://EXAMPLE.com:5000/[a b https://example.com:5000]. Expected: true
--- FAIL: TestOIDC_ValidRedirect (0.00s)

@fairclothjm fairclothjm requested a review from a team March 12, 2024 21:01
@andaley
Copy link

andaley commented Mar 12, 2024

thanks so much for tackling this so quickly!

Copy link
Contributor

@benashz benashz left a comment

Choose a reason for hiding this comment

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

Looking good. I added a few comments/questions.

path_oidc.go Outdated
@@ -547,7 +547,7 @@ func validRedirect(uri string, allowed []string) bool {

// if uri isn't a loopback, just string search the allowed list
if !strutil.StrListContains([]string{"localhost", "127.0.0.1", "::1"}, inputURI.Hostname()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe that loop back interface has a CIDR of /8 . I think you might want to remove the last octet from 127.0.0.1. In addition, localhost is not guaranteed to map back to a loopback interface address. You may want to add some comments to that effect.

`scope=openid`,
}

for _, test := range expected {
Copy link
Contributor

Choose a reason for hiding this comment

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

test used a variable name is a bit confusing. I wonder if we could rename it to testPat or something like that. Also, is there a specific reason why we couldn't have a single regex pattern for the full URL - like, is order of the params not deterministic?

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 agree about the name test. I will update that!

This was mostly copied from an existing test case. I tried reworking it to use a single regex pattern but it isn't obvious what match is failing and I couldn't get it to work. This way gives us a better error when the match fails.

path_oidc.go Outdated
@@ -537,6 +538,17 @@ func (b *jwtAuthBackend) verifyOIDCRequest(stateID string) *oidcRequest {
return nil
}

func isLoopbackAddress(hostname string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! One minor nit, I would maybe name this function isLocalAddr() or isLocalhost() since it also compares against a hostname.

Copy link
Contributor

@benashz benashz left a comment

Choose a reason for hiding this comment

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

LGTM!

@@ -538,7 +538,7 @@ func (b *jwtAuthBackend) verifyOIDCRequest(stateID string) *oidcRequest {
return nil
}

func isLoopbackAddress(hostname string) bool {
func isLocalAddr(hostname string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@fairclothjm fairclothjm merged commit 668f736 into main Mar 13, 2024
4 checks passed
@fairclothjm fairclothjm deleted the VAULT-24688/case-insensitive-redirect branch March 13, 2024 17:25
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants