Skip to content

Commit

Permalink
Check alternative origins asset against new IC domain (#1233)
Browse files Browse the repository at this point in the history
* Check alternative origins asset against new IC domain

This removes the dependency to ic0.app from the alternative origins feature.
Additionally it lifts the restriction on the subdomain to be a canister ID.

* Fixup

* Fixup

* Format

* Clean up

* Clean up

---------

Co-authored-by: Nicolas Mattia <[email protected]>
  • Loading branch information
frederikrothenberger and nmattia authored Feb 17, 2023
1 parent 29c420f commit c22e236
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 102 deletions.
4 changes: 2 additions & 2 deletions docker-test-env/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ services:
# internet identity
- identity.internetcomputer.org
# test app, TEST_APP_CANISTER_ID is substituted by the start-selenium-env script
- TEST_APP_CANISTER_ID.ic0.app
- TEST_APP_CANISTER_ID.icp0.io
- nice-name.com
# also handle the *.raw origins, but nginx will just respond with status 400
- TEST_APP_CANISTER_ID.raw.ic0.app
- TEST_APP_CANISTER_ID.raw.icp0.io

# Selenium container with chromedriver and chrome
selenium:
Expand Down
33 changes: 0 additions & 33 deletions docker-test-env/reverse_proxy/certs/wildcard.ic0.app.crt

This file was deleted.

51 changes: 0 additions & 51 deletions docker-test-env/reverse_proxy/certs/wildcard.ic0.app.key

This file was deleted.

33 changes: 33 additions & 0 deletions docker-test-env/reverse_proxy/certs/wildcard.icp0.io.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFqDCCA5ACCQDUOI9nCyaDZjANBgkqhkiG9w0BAQsFADCBlTELMAkGA1UEBhMC
Y2gxDzANBgNVBAgMBlp1cmljaDEPMA0GA1UEBwwGWnVyaWNoMRAwDgYDVQQKDAdE
RklOSVRZMQwwCgYDVQQLDANHSVgxEjAQBgNVBAMMCSouaWNwMC5pbzEwMC4GCSqG
SIb3DQEJARYhZnJlZGVyaWsucm90aGVuYmVyZ2VyQGRmaW5pdHkub3JnMB4XDTIz
MDIxNzA4MjUyMVoXDTI0MDIxNzA4MjUyMVowgZUxCzAJBgNVBAYTAmNoMQ8wDQYD
VQQIDAZadXJpY2gxDzANBgNVBAcMBlp1cmljaDEQMA4GA1UECgwHREZJTklUWTEM
MAoGA1UECwwDR0lYMRIwEAYDVQQDDAkqLmljcDAuaW8xMDAuBgkqhkiG9w0BCQEW
IWZyZWRlcmlrLnJvdGhlbmJlcmdlckBkZmluaXR5Lm9yZzCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBANt+ihl6YLmPPEUYS89B9R5yNn2X28OWoqhllLSu
uwNf148nQgDvtIibZ+ERBSNZXCJ2/wAvCla1RQ/Rgg+vc52YeuBtNv022jtQKXUC
VsRhi4/oy/2m7pkqbLYFk+QwJ27e9pwigmvHCSJK7IKpbmvnIdCPiKCPbFsRz4Sq
LKe2OhQ7mGG5FPS5k63a/GMJCsYZSoSCuJst+9QF2vfGbri736H2A3CJkXWFR9Q4
/ttBDYgjOqTWYvVddIjvd/zRZkCX3Nv4BZbL5MHFslsQx8mRfXAS7VYg7dcV5ana
RV5sTgTeRiTW1cF6YyDw0GgZV1bQkNaqWZ48CKwMv9FjOYLKha51k0x5spWGOlPp
QQBHCDc6KUCjOhjZHZsAn/WpAJPKAgqOU++F0IArD7S8eEWWL6ZwBF+H4bMs/cF4
/xKge70xpwIxq6yBylpgd8YEEliY4EhmCeTTjMTsY/YqNHSzSbO0hkiwIdEyFfeb
iCt3PYXVMJP3XNfZBiQeqVFmOU5RVLbch2Xrmq7Wwvr+wLJyQD1ChEFoZ4UR4Lk7
DQtLVsVrV+jt8GG201WX0eg7cs/bxcfDN3wB93LtsmA0rRt+f1uzoM57UNkDqJLE
dpgNx4ZbHQkz/kT+AZoZoPtcYqk6j6jSzsJQSiAKTJoOIxO56mHG6bSWkGXqodkR
cTbpAgMBAAEwDQYJKoZIhvcNAQELBQADggIBAGJLOdssHKtCTjUluL8KwYAwJInq
xYau0/m3rWWcDdYa+dpLIA8YZgOeIOn0AAzkrMEotOuMZSE5XTddghzfBRg6m4hD
5R4CAsWoPV027N3BhykSVMvsDBLGum6Pokfq9QwsD9js8ZrhXXyfODQcKfQntSfy
2THk1HAOXide6uSsbxfFChhAdPrJqQ7226ozgPZzIH9/k6GqutmM8kU3/wfLzWgu
tjNnY7yv0W62uk0ijIh9PrdVtGbYGVqR7EybHJLclh0Ev7CqQxrdq7q9jpV8KDgE
DtckPtCcAcfGexTXSB30Qm8GYqb/PatrLQgIlJzzSWu91WyhvGKVp6ichs4+qc2w
J/WJgxwQSHivw0TMNz1SkfuzCQeoPkuudVbfd/i+fDtVxXuNGqleN0YMXRwjSzV9
/teGJ72zgDJBRgwG7P5MgJTghBX6E3v9Y/VqzNIPfz4GH78D7fxntnA1IIOE226x
tNTGij+njn9mnMHhMW0b04M3FGToYKC6+PeVW6pWGCYnQPdt4nYVSUohnBTNOpGl
iC/2qR78J6KwAlnJ71uhG/3mX4csQL6rBIgydoOjbCDY+wc2gJlx5Q4xX84A2yzn
FrT2b/5ZqKt0bVpW7E9j7pfrdbXBdTJzbIvLZp75VzIONAAF3f0zBRMcVLFROpzc
RAj5RsRNBmRjoXjY
-----END CERTIFICATE-----
51 changes: 51 additions & 0 deletions docker-test-env/reverse_proxy/certs/wildcard.icp0.io.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
12 changes: 6 additions & 6 deletions docker-test-env/reverse_proxy/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ http {
# This makes all requests to raw return 400
server {
listen 443 ssl;
server_name "~^(.*)\.raw\.ic0\.app$";
server_name "~^(.*)\.raw\.icp0\.io$";

ssl_certificate /etc/nginx/certs/wildcard.ic0.app.crt;
ssl_certificate_key /etc/nginx/certs/wildcard.ic0.app.key;
ssl_certificate /etc/nginx/certs/wildcard.icp0.io.crt;
ssl_certificate_key /etc/nginx/certs/wildcard.icp0.io.key;

location / {
add_header "Access-Control-Allow-Origin" "*" always;
Expand All @@ -65,10 +65,10 @@ http {
# (a mock of) the legacy IC, which we use to e.g. query for alternative origins
server {
listen 443 ssl;
server_name "~^(.*)\.ic0\.app$";
server_name "~^(.*)\.icp0\.io";

ssl_certificate /etc/nginx/certs/wildcard.ic0.app.crt;
ssl_certificate_key /etc/nginx/certs/wildcard.ic0.app.key;
ssl_certificate /etc/nginx/certs/wildcard.icp0.io.crt;
ssl_certificate_key /etc/nginx/certs/wildcard.icp0.io.key;

location / {
proxy_pass http://host.docker.internal:4943;
Expand Down
29 changes: 24 additions & 5 deletions src/frontend/src/flows/authorize/validateDerivationOrigin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { Principal } from "@dfinity/principal";
import { wrapError } from "../../utils/utils";

const ORIGIN_VALIDATION_REGEX = /^https:\/\/([\w-]+)(?:\.raw)?\.ic0\.app$/;
// Regex that's used to ensure an alternative origin is valid. We only allow canisters as alternative origins.
// Note: this allows origins that are served both from the legacy domain (ic0.app) and the official domain (icp0.io).
const ORIGIN_VALIDATION_REGEX =
/^https:\/\/([\w-]+)(?:\.raw)?\.(?:ic0\.app|icp0\.io)$/;

const MAX_ALTERNATIVE_ORIGINS = 10;
type ValidationResult =
| { result: "valid" }
Expand Down Expand Up @@ -46,10 +50,25 @@ export const validateDerivationOrigin = async (
message: "invalid regex match result. No value for capture group 1.",
};
}
// verifies that a valid principal id was matched
// (canister ids must be valid principal ids)
const canisterId = Principal.fromText(matches[1]);
const alternativeOriginsUrl = `https://${canisterId.toText()}.ic0.app/.well-known/ii-alternative-origins`;
const subdomain = matches[1];

// We only allow alternative origins of the form <canister-id>.(ic0.app|icp0.io), but the nns dapp
// has always been on a custom domain (nns.ic0.app). This means instead of failing because the subdomain
// is not a canister id (when the subdomain is 'nns'), we instead swap it for the nns-dapp's canister ID.
const NNS_DAPP_CANISTER_ID = Principal.fromText(
"qoctq-giaaa-aaaaa-aaaea-cai"
);

// verifies that a valid principal id or the nns dapp was matched
// (canister ids must be valid principal ids), throw an error (caught above) otherwise
const canisterId =
subdomain === "nns"
? NNS_DAPP_CANISTER_ID
: Principal.fromText(subdomain);

// Regardless of whether the _origin_ (from which principals are derived) is on ic0.app or icp0.io, we always
// query the list of alternative origins from icp0.io (official domain)
const alternativeOriginsUrl = `https://${canisterId.toText()}.icp0.io/.well-known/ii-alternative-origins`;
const response = await fetch(
// always fetch non-raw
alternativeOriginsUrl,
Expand Down
8 changes: 4 additions & 4 deletions src/frontend/src/test-e2e/alternativeOrigin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ test("Should not issue delegation when derivationOrigin is malformed", async ()
'"https://some-random-disallowed-url.com" is not a valid derivation origin for "https://nice-name.com"'
);
expect(await errorView.getErrorDetail()).toEqual(
"derivationOrigin does not match regex /^https:\\/\\/([\\w-]+)(?:\\.raw)?\\.ic0\\.app$/"
"derivationOrigin does not match regex /^https:\\/\\/([\\w-]+)(?:\\.raw)?\\.(?:ic0\\.app|icp0\\.io)$/"
);
});
}, 300_000);
Expand Down Expand Up @@ -202,7 +202,7 @@ test("Should fetch /.well-known/ii-alternative-origins using the non-raw url", a
"certified"
);
await niceDemoAppView.setDerivationOrigin(
`https://${TEST_APP_CANISTER_ID}.raw.ic0.app`
`https://${TEST_APP_CANISTER_ID}.raw.icp0.io`
);
expect(await niceDemoAppView.getPrincipal()).toBe("2vxsx-fae");
await niceDemoAppView.signin();
Expand All @@ -217,11 +217,11 @@ test("Should fetch /.well-known/ii-alternative-origins using the non-raw url", a

// Selenium has _no_ connectivity to the raw url
await browser.execute(
`console.log(await fetch("https://${TEST_APP_CANISTER_ID}.raw.ic0.app/.well-known/ii-alternative-origins"))`
`console.log(await fetch("https://${TEST_APP_CANISTER_ID}.raw.icp0.io/.well-known/ii-alternative-origins"))`
);
let logs = (await browser.getLogs("browser")) as { message: string }[];
expect(logs[logs.length - 1].message).toEqual(
`https://${TEST_APP_CANISTER_ID}.raw.ic0.app/.well-known/ii-alternative-origins - Failed to load resource: the server responded with a status of 400 (Bad Request)`
`https://${TEST_APP_CANISTER_ID}.raw.icp0.io/.well-known/ii-alternative-origins - Failed to load resource: the server responded with a status of 400 (Bad Request)`
);

// This works anyway --> fetched using non-raw
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/test-e2e/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import test_app_canister_ids from "../../../../demos/test-app/.dfx/local/canister_ids.json";

export const TEST_APP_CANISTER_ID = test_app_canister_ids.test_app.local;
export const TEST_APP_CANONICAL_URL = `https://${TEST_APP_CANISTER_ID}.ic0.app`;
export const TEST_APP_CANONICAL_URL = `https://${TEST_APP_CANISTER_ID}.icp0.io`;
export const TEST_APP_NICE_URL = "https://nice-name.com";
export const REPLICA_URL = "https://icp-api.io";
export const II_URL = "https://identity.internetcomputer.org";
Expand Down

0 comments on commit c22e236

Please sign in to comment.