feat(ocm): implement WAYF page and enhance invitation workflow#13243
feat(ocm): implement WAYF page and enhance invitation workflow#13243MahdiBaghbani wants to merge 1 commit into
Conversation
|
Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would create a changelog item based on your changes. |
08be310 to
95d4f1f
Compare
|
add: Wayf.vue component with provider selection and federation discovery add: useWayf.ts composable for WAYF logic and provider management add: InvitationAcceptanceModal.vue for invitation acceptance add: useInvitationAcceptance.ts composable to share acceptance logic add: wayf.ts types for federation and provider interfaces add: WAYF documentation add: /wayf route with anonymous authentication support add: /accept-invite route for invitation acceptance workflow add: Configure anonymous authContext for public WAYF access refactor: IncomingInvitations to use shared acceptance composable add: multiple token copy options to OutgoingInvitations (plain, base64, WAYF link) enhance: token display with separate copy buttons for each format enhance: Prevent users from accepting self-generated invitations enhance: Filter out current instance from federation provider lists enhance: Validate manual provider entries against self-domain Signed-off-by: Mahdi Baghbani <mahdi-baghbani@azadehafzar.io>
95d4f1f to
521e80b
Compare
DeepDiver1975
left a comment
There was a problem hiding this comment.
Maintainer review (automated, by Claude Code on behalf of @DeepDiver1975). Thanks for porting this WAYF work over — the UX flow is clean and the self-domain prevention is a nice touch. Since this is a federation/invitation flow that crosses a trust boundary, I focused most of the review on security. A few things should be addressed before merge.
Security (please address)
1. Open-redirect / javascript: URI risk in WAYF navigation (useWayf.ts).
navigateToProvider() does window.location.href = finalUrl, where inviteAcceptDialog for an absolute URL is used as-is with no scheme/host validation:
let inviteDialogUrl = provider.inviteAcceptDialog
if (inviteDialogUrl.startsWith('/')) { ... }
// If it's already absolute, use as-is <-- no validation
const finalUrl = buildProviderUrl(inviteDialogUrl, token, providerDomain)
window.location.href = finalUrlprovider.inviteAcceptDialog comes from the /sciencemesh/federations response (server.inviteAcceptDialog). If a federation registry entry can contain a value like javascript:... or data:..., or an arbitrary attacker-controlled host, you get a redirect-to-attacker (and the invite token — a bearer secret — is appended to that URL). Please validate before navigating:
- Require
https:(reject anything that isn'thttp/https); explicitly rejectjavascript:/data:/blob:. - For absolute URLs, consider pinning the host to
provider.fqdnso the dialog URL can't redirect the token to a different host than the provider the user selected.
buildProviderUrlalready constructs vianew URL(), which throws on a malformed base — butjavascript:https://...parses fine, sonew URL()alone is not sufficient protection here.
2. Invite token in URL query string. The WAYF link (?token=...) and the redirect to the foreign provider both carry the raw token in the URL. Tokens in URLs land in browser history, server logs, and the Referer header. This may be inherent to the OCM/WAYF handoff spec, but please confirm it's intended and that the token is single-use / short-lived on the backend.
3. discoverProvider trusts the backend inviteAcceptDialog likewise — same validation point as (1) applies to the discovery response path (manual entry).
Correctness / quality
loadFederations()—new URL(server.url).hostnamecan throw. If anyserver.urlin the federations response is malformed, the.map()throws and the whole list fails to render (caught by the outer try → generic "Failed to load providers"). Consider per-server try/catch so one bad entry doesn't blank the page.useInvitationAcceptance.acceptInvitationhas an unusedresponse(const response = await ...; return true) — drop the variable or return the response.isSelfDomainmatches only on bare hostname.http://example.comandhttps://example.com:443are normalized (scheme + port stripped) — good — but a path/userinfo (example.com/foo,user@example.com) wouldn't normalize. Minor, since manual entry then flows to discovery, but worth tightening.App.vueaccept-invite watch readsroute.query.token/providerDomainbut the modal then callshttpAuthenticated.post('/sciencemesh/accept-invite'). The/accept-inviteroute has no explicitauthContext, so it defaults touser— an anonymous user arriving from a foreign WAYF page will hit auth before the modal is useful. Confirm that's the intended UX (login-then-accept) and that the token/provider survive the auth redirect.
i18n
Looks good — all user-facing strings use $gettext, including pluralization for provider counts. Two existing typos are fixed ("conections"→"connections", "Invition"→"Invitation"), nice.
Tests
web-app-ocm currently ships no unit tests, and this PR (≈1300 LOC of new composables/components) adds none. The pure logic in useWayf.ts (isSelfDomain, filterProviders, buildProviderUrl) and useInvitationAcceptance.ts (isOwnGeneratedToken, token decode in IncomingInvitations.decodeInviteToken) is very testable and is exactly the security-sensitive surface — please add unit tests, especially covering the open-redirect validation once added and the base64/plain token decode edge cases.
Changelog
Present and well-formed (changelog/unreleased/enhancement-ocm-wayf-page.md), correct Enhancement: type and PR URL. No action needed.
Minor
docs/Where Are You From page.mdis a manual test plan rather than user/dev docs — fine to keep, but consider moving the test scenarios into actual specs.- Several
console.errorcalls log full error objects; ensure tokens aren't logged in those error payloads.
Overall: solid feature, but the WAYF redirect target needs scheme/host validation before this should merge, given a bearer token rides along on that redirect. Happy to re-review once the validation + a couple of tests are in.
This review was generated by an automated agent. Note: depends on owncloud/reva#432 and owncloud/ocis#11758 per the PR description.


Although this PR is referenced under cs3org/OCM-STA#1, it is not directly part of the STA funded work. However, since the changes are closely related and beneficial to OCM, I decided to port them here as well for consistency.
This PR depends on this PR owncloud/reva#432 to be merged in Reva.
This PR depends on this PR owncloud/ocis#11758 to be merged in oCIS.
Description
This PR implements the frontend components for WAYF (Where Are You From) functionality in the OCM web application, enabling users to discover and select their cloud provider when accepting federated invitations. The implementation provides a user friendly interface for OCM provider selection and complements the backend WAYF discovery endpoints.
Technical
Things I've added to the web application:
Code Changes
New Components:
src/views/Wayf.vue: Main WAYF page with provider selection UI, search functionality, and federation displaysrc/views/InvitationAcceptanceModal.vue: Modal component for accepting invitations with provider validationNew Composables:
src/composables/useWayf.ts: Core WAYF logic including federation loading, provider discovery, and self-domain validationsrc/composables/useInvitationAcceptance.ts: Shared invitation acceptance logic with self-generated token detectionNew Types:
src/types/wayf.ts: TypeScript interfaces for federation and provider data structuresUpdated Routing (
src/index.ts):/wayfroute withauthContext: 'anonymous'for public access/accept-inviteroute for invitation acceptance workflowModified Views:
src/views/OutgoingInvitations.vue: Added three token copy options (plain, base64, WAYF link) with visual improvementssrc/views/IncomingInvitations.vue: Refactored to use shareduseInvitationAcceptancecomposablesrc/views/ConnectionsPanel.vue: Minor UI adjustmentssrc/views/App.vue: Updated to support new routesStore Updates (
web-pkg/src/composables/piniaStores/inviteTokensList.ts):tokenAtProviderandwayfLinkpropertiesDocumentation:
docs/Where Are You From page.md: WAYF usage guide, API endpoints, and testing scenariosVideos of the changes and general flow of the OCM app
From oCIS to Nextcloud
Ocis-To-Nextcloud.webm
From Nextcloud to oCIS
Nextcloud-to-oCIS.webm