feat: dynamic issuer (#3481)

* feat: dynamic issuer

* dynamic domain handling

* key rotation durations

* feat: dynamic issuer

* make webauthn displayname dynamic
This commit is contained in:
Livio Amstutz
2022-04-25 10:01:17 +02:00
committed by GitHub
parent 3d5891eb11
commit 75ec73ca4a
41 changed files with 403 additions and 348 deletions

View File

@@ -8,13 +8,13 @@ import (
"net/http"
"os"
"path"
"strings"
"time"
"github.com/caos/logging"
"github.com/caos/oidc/v2/pkg/op"
"github.com/caos/zitadel/internal/api/authz"
http_util "github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/api/http/middleware"
)
@@ -59,7 +59,7 @@ func (i *spaHandler) Open(name string) (http.File, error) {
return i.fileSystem.Open("/index.html")
}
func Start(config Config, domain, url, issuer string, instanceHandler func(http.Handler) http.Handler) (http.Handler, error) {
func Start(config Config, externalSecure bool, issuer op.IssuerFromRequest, instanceHandler func(http.Handler) http.Handler) (http.Handler, error) {
fSys, err := fs.Sub(static, "static")
if err != nil {
return nil, err
@@ -70,7 +70,7 @@ func Start(config Config, domain, url, issuer string, instanceHandler func(http.
config.LongCache.MaxAge,
config.LongCache.SharedMaxAge,
)
security := middleware.SecurityHeaders(csp(domain), nil)
security := middleware.SecurityHeaders(csp(), nil)
handler := &http.ServeMux{}
handler.Handle("/", cache(security(http.FileServer(&spaHandler{http.FS(fSys)}))))
@@ -80,7 +80,8 @@ func Start(config Config, domain, url, issuer string, instanceHandler func(http.
http.Error(w, "empty instanceID", http.StatusInternalServerError)
return
}
environmentJSON, err := createEnvironmentJSON(url, issuer, instance.ConsoleClientID())
url := http_util.BuildOrigin(r.Host, externalSecure)
environmentJSON, err := createEnvironmentJSON(url, issuer(r), instance.ConsoleClientID())
if err != nil {
http.Error(w, fmt.Sprintf("unable to marshal env for console: %v", err), http.StatusInternalServerError)
return
@@ -91,15 +92,12 @@ func Start(config Config, domain, url, issuer string, instanceHandler func(http.
return handler, nil
}
func csp(zitadelDomain string) *middleware.CSP {
if !strings.HasPrefix(zitadelDomain, "*.") {
zitadelDomain = "*." + zitadelDomain
}
func csp() *middleware.CSP {
csp := middleware.DefaultSCP
csp.StyleSrc = csp.StyleSrc.AddInline()
csp.ScriptSrc = csp.ScriptSrc.AddEval()
csp.ConnectSrc = csp.ConnectSrc.AddHost(zitadelDomain)
csp.ImgSrc = csp.ImgSrc.AddHost(zitadelDomain).AddScheme("blob")
csp.ConnectSrc = csp.ConnectSrc.AddOwnHost()
csp.ImgSrc = csp.ImgSrc.AddOwnHost().AddScheme("blob")
return &csp
}

View File

@@ -3,10 +3,10 @@ package login
import (
"context"
"github.com/caos/oidc/pkg/oidc"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/oidc/v2/pkg/oidc"
"github.com/caos/zitadel/internal/actions"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/domain"
iam_model "github.com/caos/zitadel/internal/iam/model"
)

View File

@@ -7,8 +7,8 @@ import (
"strings"
"time"
"github.com/caos/oidc/pkg/client/rp"
"github.com/caos/oidc/pkg/oidc"
"github.com/caos/oidc/v2/pkg/client/rp"
"github.com/caos/oidc/v2/pkg/oidc"
"golang.org/x/oauth2"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"

View File

@@ -4,8 +4,8 @@ import (
"net/http"
"strings"
"github.com/caos/oidc/pkg/client/rp"
"github.com/caos/oidc/pkg/oidc"
"github.com/caos/oidc/v2/pkg/client/rp"
"github.com/caos/oidc/v2/pkg/oidc"
"golang.org/x/text/language"
http_mw "github.com/caos/zitadel/internal/api/http/middleware"

View File

@@ -9,8 +9,8 @@ import (
"time"
"github.com/caos/logging"
"github.com/caos/oidc/pkg/client/rp"
"github.com/caos/oidc/pkg/oidc"
"github.com/caos/oidc/v2/pkg/client/rp"
"github.com/caos/oidc/v2/pkg/oidc"
http_util "github.com/caos/zitadel/internal/api/http"
"github.com/caos/zitadel/internal/domain"

View File

@@ -25,18 +25,17 @@ import (
)
type Login struct {
endpoint string
router http.Handler
renderer *Renderer
parser *form.Parser
command *command.Commands
query *query.Queries
staticStorage static.Storage
//staticCache cache.Cache //TODO: enable when storage is implemented again
endpoint string
router http.Handler
renderer *Renderer
parser *form.Parser
command *command.Commands
query *query.Queries
staticStorage static.Storage
authRepo auth_repository.Repository
baseURL string
consolePath string
oidcAuthCallbackURL func(string) string
oidcAuthCallbackURL func(context.Context, string) string
idpConfigAlg crypto.EncryptionAlgorithm
userCodeAlg crypto.EncryptionAlgorithm
iamDomain string
@@ -46,7 +45,6 @@ type Config struct {
LanguageCookieName string
CSRFCookieName string
Cache middleware.CacheConfig
//StaticCache cache_config.CacheConfig //TODO: enable when storage is implemented again
}
const (
@@ -64,9 +62,10 @@ func CreateLogin(config Config,
consolePath,
domain,
baseURL string,
oidcAuthCallbackURL func(string) string,
oidcAuthCallbackURL func(context.Context, string) string,
externalSecure bool,
userAgentCookie,
issuerInterceptor,
instanceHandler mux.MiddlewareFunc,
userCodeAlg crypto.EncryptionAlgorithm,
idpConfigAlg crypto.EncryptionAlgorithm,
@@ -85,12 +84,6 @@ func CreateLogin(config Config,
idpConfigAlg: idpConfigAlg,
userCodeAlg: userCodeAlg,
}
//TODO: enable when storage is implemented again
//login.staticCache, err = config.StaticCache.Config.NewCache()
//if err != nil {
// return nil, fmt.Errorf("unable to create storage cache: %w", err)
//}
statikFS, err := fs.NewWithNamespace("login")
if err != nil {
return nil, fmt.Errorf("unable to create filesystem: %w", err)
@@ -105,7 +98,8 @@ func CreateLogin(config Config,
return nil, fmt.Errorf("unable to create cacheInterceptor: %w", err)
}
security := middleware.SecurityHeaders(csp(), login.cspErrorHandler)
login.router = CreateRouter(login, statikFS, instanceHandler, csrfInterceptor, cacheInterceptor, security, userAgentCookie, middleware.TelemetryHandler(EndpointResources))
login.router = CreateRouter(login, statikFS, instanceHandler, csrfInterceptor, cacheInterceptor, security, userAgentCookie, middleware.TelemetryHandler(EndpointResources), issuerInterceptor)
login.renderer = CreateRenderer(HandlerPrefix, statikFS, staticStorage, config.LanguageCookieName, systemDefaults.DefaultLanguage)
login.parser = form.NewParser()
return login, nil

View File

@@ -43,11 +43,11 @@ func (l *Login) renderSuccessAndCallback(w http.ResponseWriter, r *http.Request,
userData: l.getUserData(r, authReq, "Login Successful", errID, errMessage),
}
if authReq != nil {
data.RedirectURI = l.oidcAuthCallbackURL("") //the id will be set via the html (maybe change this with the login refactoring)
data.RedirectURI = l.oidcAuthCallbackURL(r.Context(), "") //the id will be set via the html (maybe change this with the login refactoring)
}
l.renderer.RenderTemplate(w, r, l.getTranslator(authReq), l.renderer.Templates[tmplLoginSuccess], data, nil)
}
func (l *Login) redirectToCallback(w http.ResponseWriter, r *http.Request, authReq *domain.AuthRequest) {
http.Redirect(w, r, l.oidcAuthCallbackURL(authReq.ID), http.StatusFound)
http.Redirect(w, r, l.oidcAuthCallbackURL(r.Context(), authReq.ID), http.StatusFound)
}