Skip to content
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

Add specification for canister chosen alternative domains #724

Merged
merged 4 commits into from
Jul 8, 2022

Conversation

frederikrothenberger
Copy link
Member

This PR adds the specification for the upcoming feature that allows canisters to specify alternative origins for their frontends.
These origins will then receive the same principals as the existing canister frontend urls https://<canister_id>.ic0.app or
https://<canister_id>.raw.ic0.app.

@frederikrothenberger frederikrothenberger marked this pull request as draft July 1, 2022 14:56
This PR adds the specification for the upcoming feature that allows canisters to specify alternative origins for their frontends.
These origins will then receive the same principals as the existing canister frontend urls https://<canister_id>.ic0.app or
https://<canister_id>.raw.ic0.app.
@frederikrothenberger frederikrothenberger marked this pull request as ready for review July 1, 2022 14:58

*Note:* `https://<canister_id>.ic0.app` and `https://<canister_id>.raw.ic0.app` do _not_ issue the same principals by default. However, this feature can also be used to map `https://<canister_id>.raw.ic0.app` to `https://<canister_id>.ic0.app` principals or vice versa.

In order for Internet Identity to accept the `derivationOrigin` the corresponding canister must list the frontend origin in the https://internetcomputer.org/docs/current/references/ic-interface-spec/#state-tree-canister-information[_public_ canister metadata] with name `ii_alternative_origins`. The value of this metadata must be candid encoded `(Vec<Text>)`, where each element is an allowed alternative frontend URL.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that feature comes again.

Abstractly, we need a trusted way for the II frontend to learn from derivationOrigin which alternative origins are allowed.

I would strongly advise against using a IC-specific meachanism to implement this mapping. We deliberately designed the Internet Identity protocol so that it is completely oblivious as to where a certain client frontend is hosted, whether on the Internet Identity. Instead, we relied only on Web and HTTP related technology. Right now, I can host a webpage on https://foo.nomeata.de, and allow users to log in using II, and if I later move that page onto the Internet Computer (once it supports custom URLs, which I fail to understand why it still doesn’t), I can take my users with me.

I think throwing that property out would be an unnecessary layer violation that bars certain applications.

So what would be an alternative? If all we have is an URL, we have to use HTTP? I’d go for a https://en.wikipedia.org/wiki/Well-known_URI at the derivationOrigin. For non-raw canister URLs that will secure thanks to the service workers. And raw urls really shouldn’t be used, just like http:// URLs shouldn’t…

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does an app developer verify ownership of any of their alternative-frontend-origins? Seems like they could be dishonest about which origins they own if they're allowed to add any in their metadata without verification.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that is not a problem: If nomeata.de lists dostro.com as their alternative-frontend-origins, then that just means that nomeata.de announces it trusts dostro.com. This on its own does affect dostro.com’s security at all!

Only when the frontend served from dostro.com also sets the derivationOrigin to nomeata.de something will happen. So there is opt-in from both sides.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed the double opt-in bit :) thank you for the clarification!

Copy link
Member Author

@frederikrothenberger frederikrothenberger Jul 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nomeata: Thanks for the input! I agree that it would be good to keep II independent of canister infrastructure. I was initially worried about using HTTP requests because currently headers and status codes are not covered by certification. Thus any malicious replica or boundary node could redirect to a malicious endpoint not covered by certification. But the fetch API allows to suppress redirects, which would make it secure against this attack.

So the following caveats would apply:

  • The URL must not issue a redirect. This breaks with standard semantics of HTTP requests, but other precedents exist: e.g. service workers also cannot be installed from an URL that returns a redirect.
  • Internet Identity would have to make cross-origin requests. This means that in order for Internet Identity to be able to read the response content, there needs to be a CORS header in place (i.e. Access-Control-Allow-Origin: https://idenity.ic0.app) on the HTTP response. This in itself is not a problem, but the tooling to do this is not there yet (i.e. the asset canister does not support custom headers yet). But I think support for this is planned, @krpeacock?
  • Canisters that have used a .raw domain so far will be stuck in a worse place until we enforce certification on .raw, because any malicious replica or boundary node could issue a valid mapping for the given .raw well-known URL. Such applications do exist (e.g. DSCVR).
  • Apparently, asset certification is hard to do in Motoko at the moment. This seems like a tooling issue, but I'm not sure. @roman-kashitsyn : Could you elaborate on this point?

@Dfinity-Bjoern: What do you think? Given the points above, should we move to using a well-known HTTPs URL?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's preferable to use the HTTP interface if we can make it work. Without the possibility of suppressing redirects, this would have been insecure until we fixed the asset serving protocol. But with suppressing redirects (thanks @frederikrothenberger for pointing that out), the reduced security only applies to raw and we may be willing to accept that – pending a review with the security team.

How long would it take to have the asset canister serve CORS headers?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched spec to use HTTP requests. Pending security review and confirmation by the SDK team that the CORS headers can be implemented within a reasonable timeframe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update regarding CORS headers: The SDK team should be able to provide this within the required timeframe.

@frederikrothenberger frederikrothenberger marked this pull request as draft July 1, 2022 16:46
@nomeata
Copy link
Contributor

nomeata commented Jul 1, 2022

There is another reason why I would suggest not to use the custom WASM sections for this:

Custom WASM sections are a hard an mostly immutable part of the Canister module, i.e. that part that is the same across all instances of a service. But the names of possible alternative domains is certainly metadata that tends to vary between different instances of the same service. It would be odd if an admin of a service would have to recompile or otherwise patch the binary just to configure who that particular instance works.

Imagine a future world where there are plenty of off-the-shelve apps you can just fetch in pre-compiled form and deploy. You’d expect you can configure them dynamically, or at least via the init parameter, but not by changing the binary.

This is also very important for open services where users expect to be able to make sense of the wasm hash reported by the Internet Computer: All deployments of the same code better report the same wasm hash. This would be broken if the users would have to change the wasm.

We don’t really have a market place of apps yet, but note that there is at least one DFINITY provided app where developers regularly download a pre-compiled wasm and use: The Internet Identity dev-build! So this team in particular sees value in creating canister modules that are reusable for many instances.

More generally, I am under the impression that we often forget about the distinction between an app developer (writes codes, creates a wasm), and the app admin (creates canisters, uploads code, configures etc.). Often in small project they are the they same, but in general, these roles can be different people, and it is a design smell if admin-concerns affect the wasm. It is not a surprise that this isn’t always high on people’s mind – they are both on the “other” side of the Interface Spec – but we can at least try :-)

@frederikrothenberger frederikrothenberger marked this pull request as ready for review July 5, 2022 12:14
Copy link
Member

@Dfinity-Bjoern Dfinity-Bjoern left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks @frederikrothenberger !

@frederikrothenberger frederikrothenberger merged commit 48efaf0 into main Jul 8, 2022
@frederikrothenberger frederikrothenberger deleted the frederik/canister-domains-spec branch July 8, 2022 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants