Skip to content

Commit

Permalink
identity/oidc: loopback redirect dynamic port (#13871)
Browse files Browse the repository at this point in the history
* Add check for OIDC provider to permit a non-exact redirect URI from OIDC client if it is the IPv4 or IPv6 loopback address.

* Update changelog/13871.txt

Co-authored-by: Austin Gebauer <[email protected]>

* Update redirectURI check to match that for the OIDC auth method.

Co-authored-by: Austin Gebauer <[email protected]>
  • Loading branch information
paladin-devops and austingebauer authored Feb 7, 2022
1 parent 9f51f35 commit 8b09873
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 1 deletion.
3 changes: 3 additions & 0 deletions changelog/13871.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
identity/oidc: Adds support for port-agnostic validation of loopback IP redirect URIs.
```
3 changes: 2 additions & 1 deletion vault/identity_store_oidc_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1513,7 +1513,8 @@ func (i *IdentityStore) pathOIDCAuthorize(ctx context.Context, req *logical.Requ
if redirectURI == "" {
return authResponse("", state, ErrAuthInvalidRequest, "redirect_uri parameter is required")
}
if !strutil.StrListContains(client.RedirectURIs, redirectURI) {

if !validRedirect(redirectURI, client.RedirectURIs) {
return authResponse("", state, ErrAuthInvalidRedirectURI, "redirect_uri is not allowed for the client")
}

Expand Down
38 changes: 38 additions & 0 deletions vault/identity_store_oidc_provider_util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package vault

import (
"net/url"

"github.com/hashicorp/go-secure-stdlib/strutil"
)

// validRedirect checks whether uri is in allowed using special handling for loopback uris.
// Ref: https://tools.ietf.org/html/rfc8252#section-7.3
func validRedirect(uri string, allowed []string) bool {
inputURI, err := url.Parse(uri)
if err != nil {
return false
}

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

// otherwise, search for a match in a port-agnostic manner, per the OAuth RFC.
inputURI.Host = inputURI.Hostname()

for _, a := range allowed {
allowedURI, err := url.Parse(a)
if err != nil {
return false
}
allowedURI.Host = allowedURI.Hostname()

if inputURI.String() == allowedURI.String() {
return true
}
}

return false
}

0 comments on commit 8b09873

Please sign in to comment.