mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 00:47:33 +00:00
fix: cors (#621)
* fix: dont (re)generate client secret with auth type none * fix(cors): allow Origin from request * feat: add origin allow list and fix some core issues * rename migration * fix UserIDsByDomain * check origin on userinfo * update oidc pkg
This commit is contained in:
@@ -2,9 +2,10 @@ package authz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
|
||||
"github.com/caos/logging"
|
||||
"github.com/caos/zitadel/internal/api/grpc"
|
||||
http_util "github.com/caos/zitadel/internal/api/http"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
)
|
||||
|
||||
type key int
|
||||
@@ -46,8 +47,13 @@ func VerifyTokenAndWriteCtxData(ctx context.Context, token, orgID string, t *Tok
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
projectID, err := t.GetProjectIDByClientID(ctx, clientID)
|
||||
logging.LogWithFields("AUTH-GfAoV", "clientID", clientID).OnError(err).Warn("could not read projectid by clientid")
|
||||
projectID, origins, err := t.ProjectIDAndOriginsByClientID(ctx, clientID)
|
||||
if err != nil {
|
||||
return nil, errors.ThrowPermissionDenied(err, "AUTH-GHpw2", "could not read projectid by clientid")
|
||||
}
|
||||
if err := checkOrigin(ctx, origins); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return context.WithValue(ctx, dataKey, CtxData{UserID: userID, OrgID: orgID, ProjectID: projectID, AgentID: agentID}), nil
|
||||
}
|
||||
|
||||
@@ -69,3 +75,14 @@ func GetAllPermissionsFromCtx(ctx context.Context) []string {
|
||||
ctxPermission, _ := ctx.Value(allPermissionsKey).([]string)
|
||||
return ctxPermission
|
||||
}
|
||||
|
||||
func checkOrigin(ctx context.Context, origins []string) error {
|
||||
origin := grpc.GetGatewayHeader(ctx, http_util.Origin)
|
||||
if origin == "" {
|
||||
return nil
|
||||
}
|
||||
if http_util.IsOriginAllowed(origins, origin) {
|
||||
return nil
|
||||
}
|
||||
return errors.ThrowPermissionDenied(nil, "AUTH-DZG21", "Errors.OriginNotAllowed")
|
||||
}
|
||||
|
@@ -23,8 +23,8 @@ func (v *testVerifier) ResolveGrants(ctx context.Context) (*Grant, error) {
|
||||
return v.grant, nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) ProjectIDByClientID(ctx context.Context, clientID string) (string, error) {
|
||||
return "", nil
|
||||
func (v *testVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (string, []string, error) {
|
||||
return "", nil, nil
|
||||
}
|
||||
|
||||
func (v *testVerifier) ExistsOrg(ctx context.Context, orgID string) error {
|
||||
|
@@ -22,7 +22,7 @@ type authZRepo interface {
|
||||
VerifyAccessToken(ctx context.Context, token, clientID string) (userID, agentID string, err error)
|
||||
VerifierClientID(ctx context.Context, name string) (clientID string, err error)
|
||||
ResolveGrants(ctx context.Context) (grant *Grant, err error)
|
||||
ProjectIDByClientID(ctx context.Context, clientID string) (projectID string, err error)
|
||||
ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error)
|
||||
ExistsOrg(ctx context.Context, orgID string) error
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ func (v *TokenVerifier) ResolveGrant(ctx context.Context) (*Grant, error) {
|
||||
return v.authZRepo.ResolveGrants(ctx)
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) GetProjectIDByClientID(ctx context.Context, clientID string) (string, error) {
|
||||
return v.authZRepo.ProjectIDByClientID(ctx, clientID)
|
||||
func (v *TokenVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (string, []string, error) {
|
||||
return v.authZRepo.ProjectIDAndOriginsByClientID(ctx, clientID)
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) ExistsOrg(ctx context.Context, orgID string) error {
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grpc-ecosystem/go-grpc-middleware/util/metautils"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/http"
|
||||
)
|
||||
@@ -12,6 +13,10 @@ func GetHeader(ctx context.Context, headername string) string {
|
||||
return metautils.ExtractIncoming(ctx).Get(headername)
|
||||
}
|
||||
|
||||
func GetGatewayHeader(ctx context.Context, headername string) string {
|
||||
return GetHeader(ctx, runtime.MetadataPrefix+headername)
|
||||
}
|
||||
|
||||
func GetAuthorizationHeader(ctx context.Context) string {
|
||||
return GetHeader(ctx, http.Authorization)
|
||||
}
|
||||
|
@@ -131,7 +131,7 @@ func addInterceptors(handler http.Handler, g Gateway) http.Handler {
|
||||
if interceptor, ok := g.(grpcGatewayCustomInterceptor); ok {
|
||||
handler = interceptor.GatewayHTTPInterceptor(handler)
|
||||
}
|
||||
return http_mw.CORSInterceptorOpts(http_mw.DefaultCORSOptions, handler)
|
||||
return http_mw.CORSInterceptor(handler)
|
||||
}
|
||||
|
||||
func gatewayPort(port string) string {
|
||||
|
@@ -27,8 +27,8 @@ func (v *verifierMock) VerifyAccessToken(ctx context.Context, token, clientID st
|
||||
func (v *verifierMock) ResolveGrants(ctx context.Context) (*authz.Grant, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (v *verifierMock) ProjectIDByClientID(ctx context.Context, clientID string) (string, error) {
|
||||
return "", nil
|
||||
func (v *verifierMock) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (string, []string, error) {
|
||||
return "", nil, nil
|
||||
}
|
||||
func (v *verifierMock) ExistsOrg(ctx context.Context, orgID string) error {
|
||||
return nil
|
||||
|
@@ -13,12 +13,15 @@ const (
|
||||
AcceptLanguage = "accept-language"
|
||||
CacheControl = "cache-control"
|
||||
ContentType = "content-type"
|
||||
ContentLength = "content-length"
|
||||
Expires = "expires"
|
||||
Location = "location"
|
||||
Origin = "origin"
|
||||
Pragma = "pragma"
|
||||
UserAgentHeader = "user-agent"
|
||||
ForwardedFor = "x-forwarded-for"
|
||||
XUserAgent = "x-user-agent"
|
||||
XGrpcWeb = "x-grpc-web"
|
||||
|
||||
ContentSecurityPolicy = "content-security-policy"
|
||||
XXSSProtection = "x-xss-protection"
|
||||
|
@@ -18,6 +18,8 @@ var (
|
||||
http_utils.AcceptLanguage,
|
||||
http_utils.Authorization,
|
||||
http_utils.ZitadelOrgID,
|
||||
http_utils.XUserAgent,
|
||||
http_utils.XGrpcWeb,
|
||||
},
|
||||
AllowedMethods: []string{
|
||||
http.MethodOptions,
|
||||
@@ -30,9 +32,10 @@ var (
|
||||
},
|
||||
ExposedHeaders: []string{
|
||||
http_utils.Location,
|
||||
http_utils.ContentLength,
|
||||
},
|
||||
AllowedOrigins: []string{
|
||||
"http://localhost:*",
|
||||
AllowOriginFunc: func(_ string) bool {
|
||||
return true
|
||||
},
|
||||
}
|
||||
)
|
||||
|
23
internal/api/http/origin.go
Normal file
23
internal/api/http/origin.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func GetOriginFromURLString(s string) (string, error) {
|
||||
parsed, err := url.Parse(s)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s://%s", parsed.Scheme, parsed.Host), nil
|
||||
}
|
||||
|
||||
func IsOriginAllowed(allowList []string, origin string) bool {
|
||||
for _, allowed := range allowList {
|
||||
if allowed == origin {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/caos/oidc/pkg/op"
|
||||
|
||||
"github.com/caos/zitadel/internal/api/authz"
|
||||
"github.com/caos/zitadel/internal/api/http"
|
||||
"github.com/caos/zitadel/internal/errors"
|
||||
proj_model "github.com/caos/zitadel/internal/project/model"
|
||||
user_model "github.com/caos/zitadel/internal/user/model"
|
||||
@@ -41,11 +42,18 @@ func (o *OPStorage) AuthorizeClientIDSecret(ctx context.Context, id string, secr
|
||||
return o.repo.AuthorizeOIDCApplication(ctx, id, secret)
|
||||
}
|
||||
|
||||
func (o *OPStorage) GetUserinfoFromToken(ctx context.Context, tokenID string) (*oidc.Userinfo, error) {
|
||||
func (o *OPStorage) GetUserinfoFromToken(ctx context.Context, tokenID, origin string) (*oidc.Userinfo, error) {
|
||||
token, err := o.repo.TokenByID(ctx, tokenID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app, err := o.repo.ApplicationByClientID(ctx, token.ApplicationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if origin != "" && !http.IsOriginAllowed(app.OriginAllowList, origin) {
|
||||
return nil, errors.ThrowPermissionDenied(nil, "OIDC-da1f3", "origin is not allowed")
|
||||
}
|
||||
return o.GetUserinfoFromScopes(ctx, token.UserID, token.Scopes)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user