Repository navigation
feat(guestlinks)!: auth-guest service #3609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+3,298
−17
Merged
Changes from all commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
19fc7df
feat(guestauth): added guestauth service skeleton
maki5 0448b45
feat(guestauth): added consumer and some basic event handling logic w…
maki5 c5e52f9
feat(guestauth): token service
maki5 06f7d12
feat(guestauth): storage implementation for guest auth tokens
maki5 a60ec8c
feat(guestauth): handler for redeem action and http service
maki5 7af24c0
feat(guestauth): handle events and a bit of cleanup
maki5 ecb546f
feat(guestauth): create jwt token and setup cookies on redeem token call
maki5 ffa70f5
feat(guestauth): upd events handlers tests
maki5 2fc5fb3
feat(guestauth): used renamio for file write
maki5 a1cb335
feat(guestauth): register gusetauth service into opencloud config
maki5 402a0c0
feat(guestauth): register guestauth proxy
maki5 6ea563d
feat(guestauth): added mocks for tests, made services dependencies to…
maki5 45bc705
feat(guestauth): cookie set always to true due to codacy mention
maki5 d359a7d
feat(guestauth): removed uneeded config field
maki5 fdf52e4
feat(guestauth): upd service readme
maki5 2106f60
feat(guestauth): upd version tags for env vars
maki5 b4aa47c
feat(guestauth): renamed Storage interface and dependencies to Manager
maki5 e5c3be7
feat(guestauth): moved SecretHash to a method instead of field in struct
maki5 b920654
feat(guetauth): upd the redeem route
maki5 9088273
feat(guestauth): upd token record expiry proporety value on add
maki5 eac68b9
feat(guestauth): upd redeem response error format
maki5 cf77e47
feat(guestauth): used file lock instead of mutex in file strorage imp…
maki5 f86e339
feat(guestauth): grantee email in GuestTokenCreated event
maki5 cbf3ee8
feat(guestauth): guestauth service rename to auth-guest
maki5 d084709
feat(guestauth): prefix for cookie
maki5 e17a9a3
feat(guestauth): aligned readme
maki5 340851d
feat(guestauth): updated redeem endpoint response and dependencies
maki5 a1a8221
feat(guestauth): global flag to disable the guest links feature
maki5 c5879ca
feat(guestauth): renaming guest ivitations to guest links for consist…
maki5 2c89825
feat(guestauth): upd file manager lock, addtional filetrs for shareEx…
maki5 c1dc12d
feat(guestauth): upd readme with guest links flow diagram
maki5 aeb11b0
Adapt to renamed env var about guest links
aduffeck File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import ( | |
| "time" | ||
|
|
||
| user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" | ||
| collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" | ||
| provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" | ||
| ) | ||
|
|
||
|
|
@@ -20,3 +21,19 @@ func (ResourceMention) Unmarshal(v []byte) (interface{}, error) { | |
| err := json.Unmarshal(v, &e) | ||
| return e, err | ||
| } | ||
|
|
||
| type GuestTokenCreated struct { | ||
| ShareID *collaboration.ShareId | ||
| Sharer *user.UserId | ||
| GranteeEmail string | ||
| ItemID *provider.ResourceId | ||
| ResourceName string | ||
| Token string | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This event should include the grantee's email adress so the notification service doesn't have to look up the share anymore. |
||
| Timestamp time.Time | ||
| } | ||
|
|
||
| func (GuestTokenCreated) Unmarshal(v []byte) (interface{}, error) { | ||
| e := GuestTokenCreated{} | ||
| err := json.Unmarshal(v, &e) | ||
| return e, err | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # maintain v2 separate mocks dir | ||
| dir: "{{.InterfaceDir}}/mocks" | ||
| structname: "{{.InterfaceName}}" | ||
| filename: "{{.InterfaceName | snakecase }}.go" | ||
| pkgname: mocks | ||
|
|
||
| template: testify | ||
| packages: | ||
| github.com/opencloud-eu/opencloud/services/auth-guest/pkg/service/authguest: | ||
| interfaces: | ||
| AuthGuest: {} | ||
| github.com/opencloud-eu/opencloud/services/auth-guest/pkg/service/storage: | ||
| interfaces: | ||
| Manager: {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| SHELL := bash | ||
| NAME := auth-guest | ||
|
|
||
| ifneq (, $(shell command -v go 2> /dev/null)) # suppress `command not found warnings` for non go targets in CI | ||
| include ../../.bingo/Variables.mk | ||
| endif | ||
|
|
||
| include ../../.make/default.mk | ||
| include ../../.make/go.mk | ||
| include ../../.make/release.mk | ||
| include ../../.make/docs.mk | ||
|
|
||
| .PHONY: go-generate | ||
| go-generate: $(MOCKERY) | ||
| $(MOCKERY) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| # auth-guest | ||
|
|
||
| The `auth-guest` service gives guest users access to a share without a full | ||
| OpenCloud account. When a share is created for a user of type | ||
| `USER_TYPE_GUEST`, the service issues a one-time guest link token; redeeming | ||
| that token exchanges it for a signed session cookie that authenticates the | ||
| guest. | ||
|
|
||
| It is disabled by default. Set `OC_ENABLE_GUEST_LINKS=true` to enable the guest | ||
| links feature and start the service. | ||
|
|
||
| ## Overview | ||
|
|
||
| - **Consumes** the share lifecycle events `ShareCreated`, `ShareRemoved` and | ||
| `ShareExpired`. | ||
| - **Publishes** the `GuestTokenCreated` event carrying the guest link token, | ||
| so the link can be delivered to the guest. | ||
| - Exposes an unauthenticated endpoint that redeems the token and sets a | ||
| session cookie. | ||
| - Stores only hashes of the token and deletes the stored record when the share | ||
| is removed or expires. | ||
|
|
||
| ## Guest links flow | ||
|
|
||
| The following sequence diagram describes the guest links flow: | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| autonumber | ||
| actor User as Guest user | ||
| participant Web as Web client | ||
| participant Redeem as Redeem endpoint | ||
| participant Proxy as OpenCloud proxy | ||
| participant Graph as Graph / sharedWithMe | ||
| participant DAV as WebDAV | ||
| participant Reva as Reva | ||
|
|
||
| User->>Web: Open guest link with valid token | ||
| Web->>+Redeem: Redeem Token | ||
| Note right of Redeem: Validate Token | ||
| Redeem->>+Reva: Get Share | ||
| Reva->>-Redeem: Share | ||
| Note right of Redeem: Validate Share, Mark Token used | ||
| Redeem->>-Web: Set Cookie, return shareid | ||
| Note right of Web: HTTP only cookie with signed JWT (JWT lifetime 24h) | ||
| Web->>+Proxy: "/graph/me/drives/sharedWithMe" | ||
| Proxy->>+Reva: validate token extracted from JWT | ||
| Note right of Reva: Sign Reva Token for Guest User | ||
| Reva->>-Proxy: Authenticated | ||
| Proxy->>+Graph: "/graph/me/drives/sharedWithMe" | ||
| Note right of Proxy: Using Reva Token | ||
| Graph->>+Reva: Requests to ShareProvider | ||
| Reva->>-Graph: Shares | ||
| Graph->>-Proxy: driveItems (all shares for the Guest User) | ||
| Proxy->>-Web: driveItems | ||
| Note right of Web: Extracts driveItem for the specific share | ||
| Web->>+Proxy: PROPFIND (resource id extracted from driveItem) | ||
| Note right of Web: Using Cookie | ||
| Proxy->>+Reva: validate token extracted from JWT | ||
| Note right of Reva: Sign Reva Token for Guest User | ||
| Reva->>-Proxy: Authenticated | ||
| Proxy->>+DAV: PROPFIND | ||
| Note right of Proxy: Using Reva Token | ||
| DAV->>+Reva: Requests to StorageProvider | ||
| Reva->>-DAV: StorageProvider Responses | ||
| DAV->>-Proxy: PROPFIND Response | ||
| Proxy->>-Web: PROPFIND Response | ||
| ``` | ||
|
|
||
| ## Token lifecycle | ||
|
|
||
| 1. **Issue** — on the consumed `ShareCreated` event, where the grantee is a | ||
| guest, the service generates a random secret and stores a record keyed by | ||
| the hash of the share id. It then publishes the `GuestTokenCreated` event | ||
| with the token. | ||
| 2. **Redeem** — the guest posts the token to | ||
| `POST /graph/v1beta1/extensions/org.libregraph/guestLinks/redeem`. | ||
| The service validates the token and the share, marks the token as used | ||
| and returns a signed JWT session token in a cookie plus the share's | ||
| `permissionId` in the response body. Tokens are single-use. | ||
| 3. **Cleanup** — on the consumed `ShareRemoved` or `ShareExpired` event, the | ||
| stored record is deleted. | ||
|
|
||
| ## Configuration | ||
|
|
||
| The service is configured via `AUTH_GUEST_*` environment variables or a | ||
| `auth-guest.yaml` file. | ||
|
|
||
| To run only the HTTP part, set `AUTH_GUEST_EVENTS_DISABLED=true`. To run only | ||
| the event consumer, set `AUTH_GUEST_HTTP_DISABLED=true`. | ||
|
|
||
| Relevant options: | ||
|
|
||
| - `AUTH_GUEST_JWT_SECRET` — secret used to sign session tokens. | ||
| - `AUTH_GUEST_JWT_COOKIE_NAME`, `AUTH_GUEST_JWT_TTL` — session cookie name and | ||
| lifetime. | ||
| - `AUTH_GUEST_TOKENS_STORAGE_ROOT` — where guest link token records are stored. | ||
| - `AUTH_GUEST_SERVICE_ACCOUNT_ID`, `AUTH_GUEST_SERVICE_ACCOUNT_SECRET` — service | ||
| account used to query the gateway for share metadata. | ||
| - `AUTH_GUEST_NUM_CONSUMERS` — number of concurrent event consumers. | ||
| - `OC_REVA_GATEWAY` — CS3 gateway used to look up shares. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // Copyright 2026 OpenCloud GmbH <mail@opencloud.eu> | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package command | ||
|
|
||
| import ( | ||
| "github.com/opencloud-eu/opencloud/services/auth-guest/pkg/config" | ||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| // Health is the entrypoint for the health command. | ||
| func Health(cfg *config.Config) *cobra.Command { | ||
| return &cobra.Command{ | ||
| Use: "health", | ||
| Short: "Check health status", | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| // not implemented | ||
| return nil | ||
| }, | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't currently seem to work. The
opts.Config.Commonsstruct is stillnilhere (unless the yaml config file has a section namedshared).AFAICS this is a bug in the top-level config parser ("pkg/config/parser/parse.go") which does not initialize
cfg.CommonsinEnsureDefaults().