chore: document non-standard glob client (#328)

* op: correct typo

rename checkURIAginstRedirects to checkURIAgainstRedirects

* chore: document standard deviation when using globs

add example on how to toggle the underlying
client implementation based on DevMode.

---------

Co-authored-by: David Sharnoff <dsharnoff@singlestore.com>
This commit is contained in:
Tim Möhlmann 2023-03-28 14:58:57 +03:00 committed by GitHub
parent e1d50faf9b
commit b7d18bfd02
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 16 deletions

View file

@ -32,6 +32,8 @@ type Client struct {
devMode bool devMode bool
idTokenUserinfoClaimsAssertion bool idTokenUserinfoClaimsAssertion bool
clockSkew time.Duration clockSkew time.Duration
postLogoutRedirectURIGlobs []string
redirectURIGlobs []string
} }
// GetID must return the client_id // GetID must return the client_id
@ -44,21 +46,11 @@ func (c *Client) RedirectURIs() []string {
return c.redirectURIs return c.redirectURIs
} }
// RedirectURIGlobs provide wildcarding for additional valid redirects
func (c *Client) RedirectURIGlobs() []string {
return nil
}
// PostLogoutRedirectURIs must return the registered post_logout_redirect_uris for sign-outs // PostLogoutRedirectURIs must return the registered post_logout_redirect_uris for sign-outs
func (c *Client) PostLogoutRedirectURIs() []string { func (c *Client) PostLogoutRedirectURIs() []string {
return []string{} return []string{}
} }
// PostLogoutRedirectURIGlobs provide extra wildcarding for additional valid redirects
func (c *Client) PostLogoutRedirectURIGlobs() []string {
return nil
}
// ApplicationType must return the type of the client (app, native, user agent) // ApplicationType must return the type of the client (app, native, user agent)
func (c *Client) ApplicationType() op.ApplicationType { func (c *Client) ApplicationType() op.ApplicationType {
return c.applicationType return c.applicationType
@ -200,3 +192,26 @@ func WebClient(id, secret string, redirectURIs ...string) *Client {
clockSkew: 0, clockSkew: 0,
} }
} }
type hasRedirectGlobs struct {
*Client
}
// RedirectURIGlobs provide wildcarding for additional valid redirects
func (c hasRedirectGlobs) RedirectURIGlobs() []string {
return c.redirectURIGlobs
}
// PostLogoutRedirectURIGlobs provide extra wildcarding for additional valid redirects
func (c hasRedirectGlobs) PostLogoutRedirectURIGlobs() []string {
return c.postLogoutRedirectURIGlobs
}
// RedirectGlobsClient wraps the client in a op.HasRedirectGlobs
// only if DevMode is enabled.
func RedirectGlobsClient(client *Client) op.Client {
if client.devMode {
return hasRedirectGlobs{client}
}
return client
}

View file

@ -418,7 +418,7 @@ func (s *Storage) GetClientByClientID(ctx context.Context, clientID string) (op.
if !ok { if !ok {
return nil, fmt.Errorf("client not found") return nil, fmt.Errorf("client not found")
} }
return client, nil return RedirectGlobsClient(client), nil
} }
// AuthorizeClientIDSecret implements the op.Storage interface // AuthorizeClientIDSecret implements the op.Storage interface

View file

@ -274,9 +274,9 @@ func ValidateAuthReqScopes(client Client, scopes []string) ([]string, error) {
return scopes, nil return scopes, nil
} }
// checkURIAginstRedirects just checks aginst the valid redirect URIs and ignores // checkURIAgainstRedirects just checks aginst the valid redirect URIs and ignores
// other factors. // other factors.
func checkURIAginstRedirects(client Client, uri string) error { func checkURIAgainstRedirects(client Client, uri string) error {
if str.Contains(client.RedirectURIs(), uri) { if str.Contains(client.RedirectURIs(), uri) {
return nil return nil
} }
@ -303,12 +303,12 @@ func ValidateAuthReqRedirectURI(client Client, uri string, responseType oidc.Res
"Please ensure it is added to the request. If you have any questions, you may contact the administrator of the application.") "Please ensure it is added to the request. If you have any questions, you may contact the administrator of the application.")
} }
if strings.HasPrefix(uri, "https://") { if strings.HasPrefix(uri, "https://") {
return checkURIAginstRedirects(client, uri) return checkURIAgainstRedirects(client, uri)
} }
if client.ApplicationType() == ApplicationTypeNative { if client.ApplicationType() == ApplicationTypeNative {
return validateAuthReqRedirectURINative(client, uri, responseType) return validateAuthReqRedirectURINative(client, uri, responseType)
} }
if err := checkURIAginstRedirects(client, uri); err != nil { if err := checkURIAgainstRedirects(client, uri); err != nil {
return err return err
} }
if strings.HasPrefix(uri, "http://") { if strings.HasPrefix(uri, "http://") {
@ -329,7 +329,7 @@ func ValidateAuthReqRedirectURI(client Client, uri string, responseType oidc.Res
func validateAuthReqRedirectURINative(client Client, uri string, responseType oidc.ResponseType) error { func validateAuthReqRedirectURINative(client Client, uri string, responseType oidc.ResponseType) error {
parsedURL, isLoopback := HTTPLoopbackOrLocalhost(uri) parsedURL, isLoopback := HTTPLoopbackOrLocalhost(uri)
isCustomSchema := !strings.HasPrefix(uri, "http://") isCustomSchema := !strings.HasPrefix(uri, "http://")
if err := checkURIAginstRedirects(client, uri); err == nil { if err := checkURIAgainstRedirects(client, uri); err == nil {
if client.DevMode() { if client.DevMode() {
return nil return nil
} }

View file

@ -56,6 +56,12 @@ type Client interface {
// interpretation. Redirect URIs that match either the non-glob version or the // interpretation. Redirect URIs that match either the non-glob version or the
// glob version will be accepted. Glob URIs are only partially supported for native // glob version will be accepted. Glob URIs are only partially supported for native
// clients: "http://" is not allowed except for loopback or in dev mode. // clients: "http://" is not allowed except for loopback or in dev mode.
//
// Note that globbing / wildcards are not permitted by the OIDC
// standard and implementing this interface can have security implications.
// It is advised to only return a client of this type in rare cases,
// such as DevMode for the client being enabled.
// https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
type HasRedirectGlobs interface { type HasRedirectGlobs interface {
RedirectURIGlobs() []string RedirectURIGlobs() []string
PostLogoutRedirectURIGlobs() []string PostLogoutRedirectURIGlobs() []string