diff --git a/changelog/unreleased/claims-policy-selector.md b/changelog/unreleased/claims-policy-selector.md new file mode 100644 index 000000000..25eb2ccf3 --- /dev/null +++ b/changelog/unreleased/claims-policy-selector.md @@ -0,0 +1,5 @@ +Enhancement: Proxy: Add claims policy selector + +Using the proxy config file, it is now possible to let let the IdP determine the routing policy by sending an `ocis.routing.policy` claim. Its value will be used to determine the set of routes for the logged in user. + +https://github.com/owncloud/ocis/pull/2248 diff --git a/ocis-pkg/oidc/claims.go b/ocis-pkg/oidc/claims.go index a35d4322e..815281fc9 100644 --- a/ocis-pkg/oidc/claims.go +++ b/ocis-pkg/oidc/claims.go @@ -1,15 +1,16 @@ package oidc const ( - Iss = "iss" - Sub = "sub" - Email = "email" - Name = "name" + Iss = "iss" + Sub = "sub" + Email = "email" + Name = "name" PreferredUsername = "preferred_username" - UIDNumber = "uidnumber" - GIDNumber = "gidnumber" - Groups = "groups" - OwncloudUUID = "ownclouduuid" + UIDNumber = "uidnumber" + GIDNumber = "gidnumber" + Groups = "groups" + OwncloudUUID = "ownclouduuid" + OcisRoutingPolicy = "ocis.routing.policy" ) // The ProviderMetadata describes an idp. @@ -192,4 +193,7 @@ type StandardClaims struct { // OcisID is a unique, persistent, non reassignable user id OcisID string `json:"ownclouduuid,omitempty"` + + // OcisRoutingPolicy is used to specify the routing policy to use for the ocis proxy + OcisRoutingPolicy string `json:"ocis.routing.policy,omitempty"` } diff --git a/proxy/pkg/config/config.go b/proxy/pkg/config/config.go index a0b20b2d0..4077f9992 100644 --- a/proxy/pkg/config/config.go +++ b/proxy/pkg/config/config.go @@ -141,6 +141,7 @@ type OIDC struct { type PolicySelector struct { Static *StaticSelectorConf Migration *MigrationSelectorConf + Claims *ClaimsSelectorConf } // StaticSelectorConf is the config for the static-policy-selector @@ -166,6 +167,12 @@ type MigrationSelectorConf struct { UnauthenticatedPolicy string `mapstructure:"unauthenticated_policy"` } +// ClaimsSelectorConf is the config for the claims-selector +type ClaimsSelectorConf struct { + DefaultPolicy string `mapstructure:"default_policy"` + UnauthenticatedPolicy string `mapstructure:"unauthenticated_policy"` +} + // New initializes a new configuration func New() *Config { return &Config{ diff --git a/proxy/pkg/middleware/account_resolver.go b/proxy/pkg/middleware/account_resolver.go index a216829a4..d89ced260 100644 --- a/proxy/pkg/middleware/account_resolver.go +++ b/proxy/pkg/middleware/account_resolver.go @@ -83,6 +83,8 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) { } m.logger.Debug().Interface("claims", claims).Msg("Autoprovisioning user") u, err = m.userProvider.CreateUserFromClaims(req.Context(), claims) + // TODO instead of creating an account create a personal storage via the CS3 admin api? + // see https://cs3org.github.io/cs3apis/#cs3.admin.user.v1beta1.CreateUserRequest } if errors.Is(err, backend.ErrAccountDisabled) { diff --git a/proxy/pkg/proxy/policy/selector.go b/proxy/pkg/proxy/policy/selector.go index 10e259d19..11abfe6f5 100644 --- a/proxy/pkg/proxy/policy/selector.go +++ b/proxy/pkg/proxy/policy/selector.go @@ -67,6 +67,10 @@ func LoadSelector(cfg *config.PolicySelector) (Selector, error) { accounts.NewAccountsService("com.owncloud.accounts", grpc.NewClient())), nil } + if cfg.Claims != nil { + return NewClaimsSelector(cfg.Claims), nil + } + return nil, ErrUnexpectedConfigError } @@ -117,3 +121,18 @@ func NewMigrationSelector(cfg *config.MigrationSelectorConf, ss accounts.Account } } + +// NewClaimsSelector selects the policy based on the "ocis.routing.policy" claim +func NewClaimsSelector(cfg *config.ClaimsSelectorConf) Selector { + return func(ctx context.Context, r *http.Request) (s string, err error) { + if claims := oidc.FromContext(r.Context()); claims != nil { + if p, ok := claims[oidc.OcisRoutingPolicy].(string); ok && p != "" { + // TODO check we know the routing policy? + return p, nil + } + return cfg.DefaultPolicy, nil + } + + return cfg.UnauthenticatedPolicy, nil + } +}