mirror of
https://github.com/openziti/zrok.git
synced 2025-06-26 12:42:18 +02:00
tested with google; need to fix host/claims mismatch reauth (#968)
This commit is contained in:
parent
7cf333724f
commit
20f0f3a0e8
@ -4,6 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gobwas/glob"
|
"github.com/gobwas/glob"
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"github.com/openziti/sdk-golang/ziti"
|
"github.com/openziti/sdk-golang/ziti"
|
||||||
@ -17,12 +24,6 @@ import (
|
|||||||
"github.com/openziti/zrok/util"
|
"github.com/openziti/zrok/util"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httputil"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type HttpFrontend struct {
|
type HttpFrontend struct {
|
||||||
@ -435,7 +436,19 @@ func basicAuthRequired(w http.ResponseWriter, realm string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func oauthLoginRequired(w http.ResponseWriter, r *http.Request, cfg *OauthConfig, provider, target string, authCheckInterval time.Duration) {
|
func oauthLoginRequired(w http.ResponseWriter, r *http.Request, cfg *OauthConfig, provider, target string, authCheckInterval time.Duration) {
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s/%s/login?targethost=%s&checkInterval=%s", cfg.RedirectUrl, provider, url.QueryEscape(target), authCheckInterval.String()), http.StatusFound)
|
targetHost := r.Host
|
||||||
|
if targetHost == "" {
|
||||||
|
logrus.Error("request host is empty")
|
||||||
|
http.Error(w, "Invalid request host", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, fmt.Sprintf("%s/oauth/%s/login?targethost=%s&checkInterval=%s",
|
||||||
|
cfg.RedirectUrl,
|
||||||
|
provider,
|
||||||
|
url.QueryEscape(targetHost),
|
||||||
|
authCheckInterval.String()),
|
||||||
|
http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveService(hostMatch string, host string) string {
|
func resolveService(hostMatch string, host string) string {
|
||||||
|
@ -36,6 +36,8 @@ type IntermediateJWT struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func configureOIDCProvider(cfg *OauthConfig, providerCfg *OauthProviderConfig, tls bool) (*OIDCProvider, error) {
|
func configureOIDCProvider(cfg *OauthConfig, providerCfg *OauthProviderConfig, tls bool) (*OIDCProvider, error) {
|
||||||
|
logrus.Infof("configuring oidc provider: %v", providerCfg.Name)
|
||||||
|
|
||||||
if providerCfg == nil {
|
if providerCfg == nil {
|
||||||
return nil, errors.New("provider configuration is required")
|
return nil, errors.New("provider configuration is required")
|
||||||
}
|
}
|
||||||
@ -43,7 +45,7 @@ func configureOIDCProvider(cfg *OauthConfig, providerCfg *OauthProviderConfig, t
|
|||||||
rpConfig := &oauth2.Config{
|
rpConfig := &oauth2.Config{
|
||||||
ClientID: providerCfg.ClientId,
|
ClientID: providerCfg.ClientId,
|
||||||
ClientSecret: providerCfg.ClientSecret,
|
ClientSecret: providerCfg.ClientSecret,
|
||||||
RedirectURL: fmt.Sprintf("%v/%s/oauth", cfg.RedirectUrl, providerCfg.Name),
|
RedirectURL: fmt.Sprintf("%v/oauth/%s", cfg.RedirectUrl, providerCfg.Name),
|
||||||
Scopes: providerCfg.Scopes,
|
Scopes: providerCfg.Scopes,
|
||||||
Endpoint: providerCfg.GetEndpoint(),
|
Endpoint: providerCfg.GetEndpoint(),
|
||||||
}
|
}
|
||||||
@ -92,7 +94,36 @@ func (p *OIDCProvider) setupHandlers(cfg *OauthConfig, key []byte, tls bool) {
|
|||||||
host, err := url.QueryUnescape(r.URL.Query().Get("targethost"))
|
host, err := url.QueryUnescape(r.URL.Query().Get("targethost"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("unable to unescape target host: %v", err)
|
logrus.Errorf("unable to unescape target host: %v", err)
|
||||||
|
deleteZrokCookies(w, r)
|
||||||
|
http.Error(w, "Invalid target host", http.StatusBadRequest)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up the host value
|
||||||
|
host = strings.TrimSpace(host)
|
||||||
|
if host == "" {
|
||||||
|
logrus.Error("target host is empty")
|
||||||
|
deleteZrokCookies(w, r)
|
||||||
|
http.Error(w, "Empty target host", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any scheme, path, or query parameters
|
||||||
|
if strings.Contains(host, "://") {
|
||||||
|
if parsedURL, err := url.Parse(host); err == nil && parsedURL.Host != "" {
|
||||||
|
host = parsedURL.Host
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If there's still a path component, take only the first part
|
||||||
|
host = strings.Split(host, "/")[0]
|
||||||
|
|
||||||
|
if host == "" {
|
||||||
|
logrus.Error("failed to extract valid host")
|
||||||
|
deleteZrokCookies(w, r)
|
||||||
|
http.Error(w, "Invalid target host", http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
rp.AuthURLHandler(func() string {
|
rp.AuthURLHandler(func() string {
|
||||||
id := uuid.New().String()
|
id := uuid.New().String()
|
||||||
t := jwt.NewWithClaims(jwt.SigningMethodHS256, IntermediateJWT{
|
t := jwt.NewWithClaims(jwt.SigningMethodHS256, IntermediateJWT{
|
||||||
@ -167,12 +198,15 @@ func (p *OIDCProvider) setupHandlers(cfg *OauthConfig, key []byte, tls bool) {
|
|||||||
authCheckInterval = i
|
authCheckInterval = i
|
||||||
}
|
}
|
||||||
|
|
||||||
SetZrokCookie(w, cfg.CookieDomain, email, tokens.AccessToken, p.name, authCheckInterval, key, token.Claims.(*IntermediateJWT).Host)
|
targetHost := token.Claims.(*IntermediateJWT).Host
|
||||||
http.Redirect(w, r, fmt.Sprintf("%s://%s", scheme, token.Claims.(*IntermediateJWT).Host), http.StatusFound)
|
logrus.Infof("setting cookie and redirecting to host: %s", targetHost)
|
||||||
|
|
||||||
|
SetZrokCookie(w, cfg.CookieDomain, email, tokens.AccessToken, p.name, authCheckInterval, key, targetHost)
|
||||||
|
http.Redirect(w, r, fmt.Sprintf("%s://%s", scheme, targetHost), http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Handle(fmt.Sprintf("/%s/login", p.name), authHandlerWithQueryState(p.relyingParty))
|
http.Handle(fmt.Sprintf("/oauth/%s/login", p.name), authHandlerWithQueryState(p.relyingParty))
|
||||||
http.Handle(fmt.Sprintf("/%s/oauth", p.name), rp.CodeExchangeHandler(getEmail, p.relyingParty))
|
http.Handle(fmt.Sprintf("/oauth/%s", p.name), rp.CodeExchangeHandler(getEmail, p.relyingParty))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *OIDCProvider) extractEmail(response []byte) (string, error) {
|
func (p *OIDCProvider) extractEmail(response []byte) (string, error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user