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:
Livio Amstutz
2020-08-24 10:06:55 +02:00
committed by GitHub
parent 193cfb45f6
commit 4e1e8a714a
18 changed files with 128 additions and 26 deletions

View File

@@ -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")
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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"

View File

@@ -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
},
}
)

View 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
}

View File

@@ -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)
}