-
Notifications
You must be signed in to change notification settings - Fork 492
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
[oidc-discovery-provider] Fix keys url #5690
base: main
Are you sure you want to change the base?
Changes from all commits
bfbdeb3
442a1c8
6b33c7f
29bdd98
63d7981
f35e79b
6f5e7e9
88e33bb
295ccc2
8800dba
219ac45
b88a3ae
9bcf2dd
d18d37d
79865b8
851dc3a
dc97122
d191da0
bc0b68e
6d07e62
8c7972b
e28186a
462a7b2
4675ec8
ef0c4b5
7da1b9f
a448c12
96dee03
1902ac9
e6694f6
38a2d49
710d78b
01709db
3b80a00
a438130
bcf6e92
fcb33ec
35895d1
dc7aa77
e6814c5
9146d52
7a5f5ac
32465f0
e6772f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,24 +24,40 @@ type Handler struct { | |
allowInsecureScheme bool | ||
setKeyUse bool | ||
log logrus.FieldLogger | ||
jwtIssuer string | ||
jwtIssuer *url.URL | ||
jwksURI *url.URL | ||
serverPathPrefix string | ||
|
||
http.Handler | ||
} | ||
|
||
func NewHandler(log logrus.FieldLogger, domainPolicy DomainPolicy, source JWKSSource, allowInsecureScheme bool, setKeyUse bool, jwtIssuer string) *Handler { | ||
func NewHandler(log logrus.FieldLogger, domainPolicy DomainPolicy, source JWKSSource, allowInsecureScheme bool, setKeyUse bool, jwtIssuer *url.URL, jwksURI *url.URL, serverPathPrefix string) *Handler { | ||
if serverPathPrefix == "" { | ||
serverPathPrefix = "/" | ||
} | ||
h := &Handler{ | ||
domainPolicy: domainPolicy, | ||
source: source, | ||
allowInsecureScheme: allowInsecureScheme, | ||
setKeyUse: setKeyUse, | ||
log: log, | ||
jwtIssuer: jwtIssuer, | ||
jwksURI: jwksURI, | ||
serverPathPrefix: serverPathPrefix, | ||
} | ||
|
||
mux := http.NewServeMux() | ||
mux.Handle("/.well-known/openid-configuration", handlers.ProxyHeaders(http.HandlerFunc(h.serveWellKnown))) | ||
mux.Handle("/keys", http.HandlerFunc(h.serveKeys)) | ||
wkPath, err := url.JoinPath(serverPathPrefix, "/.well-known/openid-configuration") | ||
if err != nil { | ||
return nil | ||
} | ||
jwksPath, err := url.JoinPath(serverPathPrefix, "/keys") | ||
if err != nil { | ||
return nil | ||
} | ||
|
||
mux.Handle(wkPath, handlers.ProxyHeaders(http.HandlerFunc(h.serveWellKnown))) | ||
mux.Handle(jwksPath, http.HandlerFunc(h.serveKeys)) | ||
|
||
h.Handler = mux | ||
return h | ||
|
@@ -53,34 +69,55 @@ func (h *Handler) serveWellKnown(w http.ResponseWriter, r *http.Request) { | |
return | ||
} | ||
|
||
var host string | ||
var path string | ||
var urlScheme string | ||
if h.jwtIssuer != "" { | ||
jwtIssuerURL, _ := url.Parse(h.jwtIssuer) | ||
host = jwtIssuerURL.Host | ||
path = jwtIssuerURL.Path | ||
urlScheme = jwtIssuerURL.Scheme | ||
} else { | ||
host = r.Host | ||
urlScheme = "https" | ||
if h.allowInsecureScheme && r.TLS == nil && r.URL.Scheme != "https" { | ||
urlScheme = "http" | ||
} | ||
urlScheme := "https" | ||
if h.allowInsecureScheme && r.TLS == nil && r.URL.Scheme != "https" { | ||
urlScheme = "http" | ||
} | ||
|
||
if err := h.verifyHost(host); err != nil { | ||
http.Error(w, err.Error(), http.StatusBadRequest) | ||
return | ||
issuerURL := h.jwtIssuer | ||
if h.jwtIssuer == nil { | ||
issuerURL = &url.URL{ | ||
Scheme: urlScheme, | ||
Host: r.Host, | ||
} | ||
if h.serverPathPrefix != "/" { | ||
issuerURL.Path = h.serverPathPrefix | ||
} | ||
} | ||
|
||
issuerURL := url.URL{ | ||
Scheme: urlScheme, | ||
Host: host, | ||
Path: path, | ||
var jwksURI *url.URL | ||
switch { | ||
case h.jwksURI != nil: | ||
jwksURI = h.jwksURI | ||
case h.jwtIssuer != nil: | ||
// If jwksIsser is set but not jwksURI, fall back to 1.11.1 behavior until we can remove jwksIssuer leaking into jwksURI in 1.13.0 | ||
keysPath, err := url.JoinPath(h.jwtIssuer.Path, "keys") | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
jwksURI = &url.URL{ | ||
Scheme: h.jwtIssuer.Scheme, | ||
Host: h.jwtIssuer.Host, | ||
Path: keysPath, | ||
} | ||
default: | ||
keysPath, err := url.JoinPath(h.serverPathPrefix, "keys") | ||
if err != nil { | ||
http.Error(w, err.Error(), http.StatusInternalServerError) | ||
return | ||
} | ||
jwksURI = &url.URL{ | ||
Scheme: urlScheme, | ||
Host: r.Host, | ||
Path: keysPath, | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be possible to simplify this a bit. I'm thinking something like:
Minimizes dependencies between the parts of the two URLs and makes it a bit easier to read, at least in my opinion. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure I follow this one. Talking about moving the var definition closer to the block of code setting it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, basically that + keeping the extra vars (mainly host and port) outside of the ifs. I think it makes the code a bit easier to follow since the reader doesn't have to jump through various if conditions to come up with the final value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. |
||
|
||
jwksURI := issuerURL.JoinPath("keys") | ||
if err := h.verifyHost(r.Host); err != nil { | ||
http.Error(w, err.Error(), http.StatusBadRequest) | ||
return | ||
} | ||
|
||
doc := struct { | ||
Issuer string `json:"issuer"` | ||
|
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 include
serverPathPrefix
in the Issuer here?Per the specs:
So technically, if the well-known document includes a path component, the issuer should too.
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.
Depends on if there are any proxies doing rewrites in front...
But, yeah. I think your probably right, as the default, if the serverPathPrefix is set, the default may benefit from having it set too. The user can always override issuer if they are using a proxy in front.