mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-30 08:50:49 -06:00
@@ -16566,7 +16566,7 @@ WEBFINGER_OWNCLOUD_SERVER_INSTANCE_URL:
|
||||
deprecationInfo: ""
|
||||
WEBFINGER_RELATIONS:
|
||||
name: WEBFINGER_RELATIONS
|
||||
defaultValue: '[http://openid.net/specs/connect/1.0/issuer http://webfinger.owncloud/rel/server-instance]'
|
||||
defaultValue: '[http://openid.net/specs/connect/1.0/issuer http://webfinger.opencloud/rel/server-instance]'
|
||||
type: '[]string'
|
||||
description: A list of relation URIs or registered relation types to add to webfinger
|
||||
responses. See the Environment Variable Types description for more details.
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
# Webfinger
|
||||
|
||||
The webfinger service provides an RFC7033 WebFinger lookup of ownCloud instances relevant for a given user account via endpoints a the /.well-known/webfinger implementation.
|
||||
|
||||
It is based on https://github.com/owncloud/lookup-webfinger-sciebo but also returns localized `titles` in addition to the `href` property.
|
||||
The webfinger service provides an RFC7033 WebFinger lookup of OpenCloud instances relevant for a given user account via endpoints a the /.well-known/webfinger implementation.
|
||||
|
||||
## OpenID Connect Discovery
|
||||
|
||||
Clients can make an unauthenticated `GET https://drive.ocis.test/.well-known/webfinger?resource=https%3A%2F%2Fdrive.ocis.test` request to discover the OpenID Connect Issuer in the `http://openid.net/specs/connect/1.0/issuer` relation:
|
||||
Clients can make an unauthenticated `GET https://drive.opencloud.test/.well-known/webfinger?resource=https%3A%2F%2Fdrive.opencloud.test` request to discover the OpenID Connect Issuer in the `http://openid.net/specs/connect/1.0/issuer` relation:
|
||||
|
||||
```json
|
||||
{
|
||||
"subject": "https://drive.ocis.test",
|
||||
"subject": "https://drive.opencloud.test",
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
@@ -24,7 +22,7 @@ Here, the `resource` takes the instance domain URI, but an `acct:` URI works as
|
||||
|
||||
## Authenticated Instance Discovery
|
||||
|
||||
When using OpenID connect to authenticate requests, clients can look up the owncloud instances a user has access to.
|
||||
When using OpenID connect to authenticate requests, clients can look up the opencloud instances a user has access to.
|
||||
|
||||
* Authentication is necessary to prevent leaking information about existing users.
|
||||
* Basic auth is not supported.
|
||||
@@ -33,17 +31,17 @@ The default configuration will simply return the `OC_URL` and direct clients to
|
||||
|
||||
```json
|
||||
{
|
||||
"subject": "acct:einstein@drive.ocis.test",
|
||||
"subject": "acct:einstein@drive.opencloud.test",
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
"href": "https://sso.example.org/cas/oidc/"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.owncloud/rel/server-instance",
|
||||
"rel": "http://webfinger.opencloud/rel/server-instance",
|
||||
"href": "https://abc.drive.example.org",
|
||||
"titles": {
|
||||
"en": "oCIS Instance"
|
||||
"en": "OpenCloud Instance"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -59,38 +57,38 @@ webfinger:
|
||||
instances:
|
||||
- claim: email
|
||||
regex: einstein@example\.org
|
||||
href: "https://{{.preferred_username}}.cloud.ocis.test"
|
||||
href: "https://{{.preferred_username}}.cloud.opencloud.test"
|
||||
title:
|
||||
"en": "oCIS Instance for Einstein"
|
||||
"de": "oCIS Instanz für Einstein"
|
||||
"en": "OpenCloud Instance for Einstein"
|
||||
"de": "OpenCloud Instanz für Einstein"
|
||||
break: true
|
||||
- claim: "email"
|
||||
regex: marie@example\.org
|
||||
href: "https://{{.preferred_username}}.cloud.ocis.test"
|
||||
href: "https://{{.preferred_username}}.cloud.opencloud.test"
|
||||
title:
|
||||
"en": "oCIS Instance for Marie"
|
||||
"de": "oCIS Instanz für Marie"
|
||||
"en": "OpenCloud Instance for Marie"
|
||||
"de": "OpenCloud Instanz für Marie"
|
||||
break: false
|
||||
- claim: "email"
|
||||
regex: .+@example\.org
|
||||
href: "https://example-org.cloud.ocis.test"
|
||||
href: "https://example-org.cloud.opencloud.test"
|
||||
title:
|
||||
"en": "oCIS Instance for example.org"
|
||||
"de": "oCIS Instanz für example.org"
|
||||
"en": "OpenCloud Instance for example.org"
|
||||
"de": "OpenCloud Instanz für example.org"
|
||||
break: true
|
||||
- claim: "email"
|
||||
regex: .+@example\.com
|
||||
href: "https://example-com.cloud.ocis.test"
|
||||
href: "https://example-com.cloud.opencloud.test"
|
||||
title:
|
||||
"en": "oCIS Instance for example.com"
|
||||
"de": "oCIS Instanz für example.com"
|
||||
"en": "OpenCloud Instance for example.com"
|
||||
"de": "OpenCloud Instanz für example.com"
|
||||
break: true
|
||||
- claim: "email"
|
||||
regex: .+@.+\..+
|
||||
href: "https://cloud.ocis.test"
|
||||
href: "https://cloud.opencloud.test"
|
||||
title:
|
||||
"en": "oCIS Instance"
|
||||
"de": "oCIS Instanz"
|
||||
"en": "OpenCloud Instance"
|
||||
"de": "OpenCloud Instanz"
|
||||
break: true
|
||||
```
|
||||
|
||||
@@ -105,19 +103,19 @@ Now, an authenticated webfinger request for `acct:me@example.org` (when logged i
|
||||
"href": "https://sso.example.org/cas/oidc/"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.owncloud/rel/server-instance",
|
||||
"href": "https://marie.cloud.ocis.test",
|
||||
"rel": "http://webfinger.opencloud/rel/server-instance",
|
||||
"href": "https://marie.cloud.opencloud.test",
|
||||
"titles": {
|
||||
"en": "oCIS Instance for Marie",
|
||||
"de": "oCIS Instanz für Marie"
|
||||
"en": "OpenCloud Instance for Marie",
|
||||
"de": "OpenCloud Instanz für Marie"
|
||||
}
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.owncloud/rel/server-instance",
|
||||
"rel": "http://webfinger.opencloud/rel/server-instance",
|
||||
"href": "https://xyz.drive.example.org",
|
||||
"titles": {
|
||||
"en": "oCIS Instance for example.org",
|
||||
"de": "oCIS Instanz für example.org"
|
||||
"en": "OpenCloud Instance for example.org",
|
||||
"de": "OpenCloud Instanz für example.org"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# TODO
|
||||
Currently, clients need to make subsequent calls to:
|
||||
* /status.php to check if the instance is in maintenance mode or if the version is supported
|
||||
* /config.json to get the available apps for ocis web to determine which routes require authentication
|
||||
* /themes/owncloud/theme.json for theming info
|
||||
* /config.json to get the available apps for OpenCloud web to determine which routes require authentication
|
||||
* /themes/opencloud/theme.json for theming info
|
||||
* /.well-known/openid-configuration, auth2 token and oidc userinfo endpoints to authenticate the user
|
||||
* /ocs/v1.php/cloud/user to get the username, eg. einstein ... again? it contains the oc10 user id (marie, not the uuid)
|
||||
* /ocs/v1.php/cloud/capabilities to fetch instance capabilites
|
||||
@@ -26,45 +26,45 @@ The /.well-known/webfinger enpdoint allows us to not only get rid of some of the
|
||||
|
||||
```json
|
||||
{
|
||||
"subject": "https://drive.ocis.test",
|
||||
"subject": "https://drive.opencloud.test",
|
||||
"properties": {
|
||||
"http://webfinger.owncloud/prop/maintenance": "false",
|
||||
"http://webfinger.owncloud/prop/version": "10.11.0.6"
|
||||
"http://webfinger.opencloud/prop/maintenance": "false",
|
||||
"http://webfinger.opencloud/prop/version": "10.11.0.6"
|
||||
},
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
"href": "https://idp.ocis.test"
|
||||
"href": "https://idp.opencloud.test"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Introduce Dedicated ocis web Endpoint
|
||||
## Introduce Dedicated OpenCloud web Endpoint
|
||||
|
||||
It also allows us to move some services out of a sharded deployment. We could e.g. introduce a relation for a common ocis web endpoint to not exponse the different instances in the browser bar:
|
||||
It also allows us to move some services out of a sharded deployment. We could e.g. introduce a relation for a common OpenCloud web endpoint to not exponse the different instances in the browser bar:
|
||||
```json
|
||||
{
|
||||
"subject": "acct:einstein@drive.ocis.test",
|
||||
"subject": "acct:einstein@drive.opencloud.test",
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
"href": "https://idp.ocis.test"
|
||||
"href": "https://idp.opencloud.test"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.owncloud/rel/web",
|
||||
"href": "https://drive.ocis.test"
|
||||
"rel": "http://webfinger.opencloud/rel/web",
|
||||
"href": "https://drive.opencloud.test"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.owncloud/rel/server-instance",
|
||||
"href": "https://abc.drive.ocis.test",
|
||||
"rel": "http://webfinger.opencloud/rel/server-instance",
|
||||
"href": "https://abc.drive.opencloud.test",
|
||||
"titles": {
|
||||
"en": "Readable Instance Name"
|
||||
}
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.owncloud/rel/server-instance",
|
||||
"href": "https://xyz.drive.ocis.test",
|
||||
"rel": "http://webfinger.opencloud/rel/server-instance",
|
||||
"href": "https://xyz.drive.opencloud.test",
|
||||
"titles": {
|
||||
"en": "Readable Other Instance Name"
|
||||
}
|
||||
@@ -73,24 +73,24 @@ It also allows us to move some services out of a sharded deployment. We could e.
|
||||
}
|
||||
```
|
||||
|
||||
## Dedicated ocis web Endpoint
|
||||
## Dedicated OpenCloud web Endpoint
|
||||
|
||||
We could also omit the `http://webfinger.owncloud/rel/server-instance` relation and go straight for a graph service with e.g. `rel=http://libregraph.org/rel/graph`:
|
||||
We could also omit the `http://webfinger.opencloud/rel/server-instance` relation and go straight for a graph service with e.g. `rel=http://libregraph.org/rel/graph`:
|
||||
```json
|
||||
{
|
||||
"subject": "acct:einstein@drive.ocis.test",
|
||||
"subject": "acct:einstein@drive.opencloud.test",
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
"href": "https://idp.ocis.test"
|
||||
"href": "https://idp.opencloud.test"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.owncloud/rel/web",
|
||||
"href": "https://drive.ocis.test"
|
||||
"rel": "http://webfinger.opencloud/rel/web",
|
||||
"href": "https://drive.opencloud.test"
|
||||
},
|
||||
{
|
||||
"rel": "http://libregraph.org/rel/graph",
|
||||
"href": "https://abc.drive.ocis.test/graph/v1.0",
|
||||
"href": "https://abc.drive.opencloud.test/graph/v1.0",
|
||||
"titles": {
|
||||
"en": "Readable Instance Name"
|
||||
}
|
||||
@@ -103,10 +103,10 @@ In theory the graph endpoint would allow discovering drives on any domain. But t
|
||||
|
||||
## Subject Properties
|
||||
|
||||
We could also embed subject metadata, however since apps like ocis web also need the groups a user is member of a dedicated call to the libregraph api is probably better. In any case, we could return properties for the subject:
|
||||
We could also embed subject metadata, however since apps like OpenCloud web also need the groups a user is member of a dedicated call to the libregraph api is probably better. In any case, we could return properties for the subject:
|
||||
```json
|
||||
{
|
||||
"subject": "acct:einstein@drive.ocis.test",
|
||||
"subject": "acct:einstein@drive.opencloud.test",
|
||||
"properties": {
|
||||
"http://libregraph.org/prop/user/id": "4c510ada-c86b-4815-8820-42cdf82c3d51",
|
||||
"http://libregraph.org/prop/user/onPremisesSamAccountName": "einstein",
|
||||
@@ -116,18 +116,18 @@ We could also embed subject metadata, however since apps like ocis web also need
|
||||
"links": [
|
||||
{
|
||||
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||
"href": "https://idp.ocis.test"
|
||||
"href": "https://idp.opencloud.test"
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.owncloud/rel/server-instance",
|
||||
"href": "https://abc.drive.ocis.test",
|
||||
"rel": "http://webfinger.opencloud/rel/server-instance",
|
||||
"href": "https://abc.drive.opencloud.test",
|
||||
"titles": {
|
||||
"en": "Readable Instance Name"
|
||||
}
|
||||
},
|
||||
{
|
||||
"rel": "http://webfinger.owncloud/rel/server-instance",
|
||||
"href": "https://xyz.drive.ocis.test",
|
||||
"rel": "http://webfinger.opencloud/rel/server-instance",
|
||||
"href": "https://xyz.drive.opencloud.test",
|
||||
"titles": {
|
||||
"en": "Readable Other Instance Name"
|
||||
}
|
||||
|
||||
@@ -22,11 +22,11 @@ func GetCommands(cfg *config.Config) cli.Commands {
|
||||
}
|
||||
}
|
||||
|
||||
// Execute is the entry point for the ocis webfinger command.
|
||||
// Execute is the entry point for the opencloud webfinger command.
|
||||
func Execute(cfg *config.Config) error {
|
||||
app := clihelper.DefaultApp(&cli.App{
|
||||
Name: "webfinger",
|
||||
Usage: "Serve webfinger API for oCIS",
|
||||
Usage: "Serve webfinger API for OpenCloud",
|
||||
Commands: GetCommands(cfg),
|
||||
})
|
||||
|
||||
|
||||
@@ -130,9 +130,9 @@ func getRelationProviders(cfg *config.Config) (map[string]service.RelationProvid
|
||||
switch relationURI {
|
||||
case relations.OpenIDConnectRel:
|
||||
rels[relationURI] = relations.OpenIDDiscovery(cfg.IDP)
|
||||
case relations.OwnCloudInstanceRel:
|
||||
case relations.OpenCloudInstanceRel:
|
||||
var err error
|
||||
rels[relationURI], err = relations.OwnCloudInstance(cfg.Instances, cfg.OpenCloudURL)
|
||||
rels[relationURI], err = relations.OpenCloudInstance(cfg.Instances, cfg.OpenCloudURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -38,14 +38,14 @@ func DefaultConfig() *config.Config {
|
||||
},
|
||||
|
||||
OpenCloudURL: "https://localhost:9200",
|
||||
Relations: []string{relations.OpenIDConnectRel, relations.OwnCloudInstanceRel},
|
||||
Relations: []string{relations.OpenIDConnectRel, relations.OpenCloudInstanceRel},
|
||||
Instances: []config.Instance{
|
||||
{
|
||||
Claim: "sub",
|
||||
Regex: ".+",
|
||||
Href: "{{.OC_URL}}",
|
||||
Titles: map[string]string{
|
||||
"en": "oCIS Instance",
|
||||
"en": "OpenCloud Instance",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
OwnCloudInstanceRel = "http://webfinger.owncloud/rel/server-instance"
|
||||
OpenCloudInstanceRel = "http://webfinger.opencloud/rel/server-instance"
|
||||
)
|
||||
|
||||
type compiledInstance struct {
|
||||
@@ -23,14 +23,14 @@ type compiledInstance struct {
|
||||
hrefTemplate *template.Template
|
||||
}
|
||||
|
||||
type ownCloudInstance struct {
|
||||
type openCloudInstance struct {
|
||||
instances []compiledInstance
|
||||
openCloudURL string
|
||||
instanceHost string
|
||||
}
|
||||
|
||||
// OwnCloudInstance adds one or more ownCloud instance relations
|
||||
func OwnCloudInstance(instances []config.Instance, openCloudURL string) (service.RelationProvider, error) {
|
||||
// OpenCloudInstance adds one or more OpenCloud instance relations
|
||||
func OpenCloudInstance(instances []config.Instance, openCloudURL string) (service.RelationProvider, error) {
|
||||
compiledInstances := make([]compiledInstance, 0, len(instances))
|
||||
var err error
|
||||
for _, instance := range instances {
|
||||
@@ -50,14 +50,14 @@ func OwnCloudInstance(instances []config.Instance, openCloudURL string) (service
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ownCloudInstance{
|
||||
return &openCloudInstance{
|
||||
instances: compiledInstances,
|
||||
openCloudURL: openCloudURL,
|
||||
instanceHost: u.Host + u.Path,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *ownCloudInstance) Add(ctx context.Context, jrd *webfinger.JSONResourceDescriptor) {
|
||||
func (l *openCloudInstance) Add(ctx context.Context, jrd *webfinger.JSONResourceDescriptor) {
|
||||
if jrd == nil {
|
||||
jrd = &webfinger.JSONResourceDescriptor{}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func (l *ownCloudInstance) Add(ctx context.Context, jrd *webfinger.JSONResourceD
|
||||
var tmplWriter strings.Builder
|
||||
instance.hrefTemplate.Execute(&tmplWriter, claims)
|
||||
jrd.Links = append(jrd.Links, webfinger.Link{
|
||||
Rel: OwnCloudInstanceRel,
|
||||
Rel: OpenCloudInstanceRel,
|
||||
Href: tmplWriter.String(),
|
||||
Titles: instance.Titles,
|
||||
})
|
||||
|
||||
@@ -9,23 +9,23 @@ import (
|
||||
"github.com/opencloud-eu/opencloud/services/webfinger/pkg/webfinger"
|
||||
)
|
||||
|
||||
func TestOwnCloudInstanceErr(t *testing.T) {
|
||||
_, err := OwnCloudInstance([]config.Instance{}, "http://\n\rinvalid")
|
||||
func TestOpenCloudInstanceErr(t *testing.T) {
|
||||
_, err := OpenCloudInstance([]config.Instance{}, "http://\n\rinvalid")
|
||||
if err == nil {
|
||||
t.Errorf("provider did not err on invalid url: %v", err)
|
||||
}
|
||||
_, err = OwnCloudInstance([]config.Instance{{Regex: "("}}, "http://docis.tld")
|
||||
_, err = OpenCloudInstance([]config.Instance{{Regex: "("}}, "http://opencloud.tld")
|
||||
if err == nil {
|
||||
t.Errorf("provider did not err on invalid regex: %v", err)
|
||||
}
|
||||
_, err = OwnCloudInstance([]config.Instance{{Href: "{{invalid}}ee"}}, "http://docis.tld")
|
||||
_, err = OpenCloudInstance([]config.Instance{{Href: "{{invalid}}ee"}}, "http://opencloud.tld")
|
||||
if err == nil {
|
||||
t.Errorf("provider did not err on invalid href template: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOwnCloudInstanceAddLink(t *testing.T) {
|
||||
provider, err := OwnCloudInstance([]config.Instance{{
|
||||
func TestOpenCloudInstanceAddLink(t *testing.T) {
|
||||
provider, err := OpenCloudInstance([]config.Instance{{
|
||||
Claim: "customclaim",
|
||||
Regex: ".+@.+\\..+",
|
||||
Href: "https://{{.otherclaim}}.domain.tld",
|
||||
@@ -33,7 +33,7 @@ func TestOwnCloudInstanceAddLink(t *testing.T) {
|
||||
"foo": "bar",
|
||||
},
|
||||
Break: true,
|
||||
}}, "http://docis.tld")
|
||||
}}, "http://opencloud.tld")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -52,8 +52,8 @@ func TestOwnCloudInstanceAddLink(t *testing.T) {
|
||||
if jrd.Links[0].Href != "https://someone.domain.tld" {
|
||||
t.Errorf("provider returned wrong issuer link href: %v, expected %v", jrd.Links[0].Href, "https://someone.domain.tld")
|
||||
}
|
||||
if jrd.Links[0].Rel != OwnCloudInstanceRel {
|
||||
t.Errorf("provider returned owncloud server instance rel: %v, expected %v", jrd.Links[0].Rel, OwnCloudInstanceRel)
|
||||
if jrd.Links[0].Rel != OpenCloudInstanceRel {
|
||||
t.Errorf("provider returned opencloud server instance rel: %v, expected %v", jrd.Links[0].Rel, OpenCloudInstanceRel)
|
||||
}
|
||||
if len(jrd.Links[0].Titles) != 1 {
|
||||
t.Errorf("provider returned wrong number of titles: %v, expected 1", len(jrd.Links[0].Titles))
|
||||
|
||||
@@ -15,7 +15,7 @@ type Service interface {
|
||||
//
|
||||
// GET /.well-known/webfinger?
|
||||
// resource=acct%3Acarol%40example.com&
|
||||
// rel=http%3A%2F%2Fwebfinger.owncloud%rel%2Fserver-instance
|
||||
// rel=http%3A%2F%2Fwebfinger.opencloud%rel%2Fserver-instance
|
||||
// HTTP/1.1
|
||||
// Host: example.com
|
||||
//
|
||||
@@ -30,14 +30,14 @@ type Service interface {
|
||||
// "links" :
|
||||
// [
|
||||
// {
|
||||
// "rel" : "http://webfinger.owncloud/rel/server-instance",
|
||||
// "rel" : "http://webfinger.opencloud/rel/server-instance",
|
||||
// "href" : "https://instance.example.com",
|
||||
// "titles": {
|
||||
// "en": "Readable Instance Name"
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// "rel" : "http://webfinger.owncloud/rel/server-instance",
|
||||
// "rel" : "http://webfinger.opencloud/rel/server-instance",
|
||||
// "href" : "https://otherinstance.example.com",
|
||||
// "titles": {
|
||||
// "en": "Other Readable Instance Name"
|
||||
|
||||
Reference in New Issue
Block a user