-
Notifications
You must be signed in to change notification settings - Fork 136
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement canister chosen alternative origins for principal derivation (
#733) This feature allows applications to move to other origins while keeping the original user principals. See the specification in docs/internet-identity-spec.adoc for more details.
- Loading branch information
1 parent
a65417a
commit 9830ecc
Showing
10 changed files
with
514 additions
and
34 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains 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 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 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 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
76 changes: 76 additions & 0 deletions
76
src/frontend/src/flows/authenticate/validateDerivationOrigin.ts
This file contains 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,76 @@ | ||
import { Principal } from "@dfinity/principal"; | ||
|
||
export type ValidationResult = | ||
| { result: "valid" } | ||
| { result: "invalid"; message: string }; | ||
|
||
export const validateDerivationOrigin = async ( | ||
authRequestOrigin: string, | ||
derivationOrigin?: string | ||
): Promise<ValidationResult> => { | ||
if ( | ||
derivationOrigin === undefined || | ||
derivationOrigin === authRequestOrigin | ||
) { | ||
// this is the default behaviour -> no further validation necessary | ||
return { result: "valid" }; | ||
} | ||
|
||
// check format of derivationOrigin | ||
const matches = /^https:\/\/([\w-]*)(\.raw)?\.ic0\.app$/.exec( | ||
derivationOrigin | ||
); | ||
if (matches === null) { | ||
return { | ||
result: "invalid", | ||
message: | ||
'derivationOrigin does not match regex "^https:\\/\\/([\\w-]*)(\\.raw)?\\.ic0\\.app$"', | ||
}; | ||
} | ||
|
||
try { | ||
const canisterId = Principal.fromText(matches[1]); // verifies that a valid canister id was matched | ||
const alternativeOriginsUrl = `https://${canisterId.toText()}.ic0.app/.well-known/ii-alternative-origins`; | ||
const response = await fetch( | ||
// always fetch non-raw | ||
alternativeOriginsUrl, | ||
// fail on redirects | ||
{ redirect: "error" } | ||
); | ||
|
||
if (response.status !== 200) { | ||
return { | ||
result: "invalid", | ||
message: `resource ${alternativeOriginsUrl} returned invalid status: ${response.status}`, | ||
}; | ||
} | ||
|
||
const alternativeOriginsObj = (await response.json()) as { | ||
alternativeOrigins: string[]; | ||
}; | ||
|
||
// check for expected property | ||
if (!Array.isArray(alternativeOriginsObj?.alternativeOrigins)) { | ||
return { | ||
result: "invalid", | ||
message: `resource ${alternativeOriginsUrl} has invalid format: received ${alternativeOriginsObj}`, | ||
}; | ||
} | ||
|
||
// check allowed alternative origins | ||
if (!alternativeOriginsObj.alternativeOrigins.includes(authRequestOrigin)) { | ||
return { | ||
result: "invalid", | ||
message: `"${authRequestOrigin}" is not listed in the list of allowed alternative origins. Allowed alternative origins: ${alternativeOriginsObj.alternativeOrigins}`, | ||
}; | ||
} | ||
} catch (e) { | ||
return { | ||
result: "invalid", | ||
message: `An error occurred while validation the derivationOrigin "${derivationOrigin}": ${e.message}`, | ||
}; | ||
} | ||
|
||
// all checks passed --> valid | ||
return { result: "valid" }; | ||
}; |
Oops, something went wrong.