Skip to content

Commit 3c10b4f

Browse files
Merge pull request #1251 from dfinity/marc0olo/improve-examples
Marc0olo/improve examples
2 parents ea33175 + ec52507 commit 3c10b4f

File tree

6 files changed

+152
-23
lines changed

6 files changed

+152
-23
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
[
2+
{
3+
"match": "**/*",
4+
"security_policy" : "hardened",
5+
"headers": {
6+
// Security: The Content Security Policy (CSP) given below aims at working with many apps rather than providing maximal security.
7+
// We recommend tightening the CSP for your specific application. Some recommendations are as follows:
8+
// - Use the CSP Evaluator (https://csp-evaluator.withgoogle.com/) to validate the CSP you define.
9+
// - Follow the “Strict CSP” recommendations (https://csp.withgoogle.com/docs/strict-csp.html). However, note that in the context of the IC,
10+
// nonces cannot be used because the response bodies must be static to work well with HTTP asset certification.
11+
// Thus, we recommend to include script hashes (in combination with strict-dynamic) in the CSP as described
12+
// in https://csp.withgoogle.com/docs/faq.html in section “What if my site is static and I can't add nonces to scripts?”.
13+
// See for example the II CSP (https://github.com/dfinity/internet-identity/blob/main/src/internet_identity/src/http.rs).
14+
// - It is recommended to tighten the connect-src directive. With the current CSP configuration the browser can
15+
// make requests to https://*.icp0.io, hence being able to call any canister via https://icp0.io/api/v2/canister/{canister-ID}.
16+
// This could potentially be used in combination with another vulnerability (e.g. XSS) to exfiltrate private data.
17+
// The developer can configure this policy to only allow requests to their specific canisters,
18+
// e.g: connect-src 'self' https://icp-api.io/api/v2/canister/{my-canister-ID}, where {my-canister-ID} has the following format: aaaaa-aaaaa-aaaaa-aaaaa-aaa
19+
// - It is recommended to configure style-src, style-src-elem and font-src directives with the resources your canister is going to use
20+
// instead of using the wild card (*) option. Normally this will include 'self' but also other third party styles or fonts resources (e.g: https://fonts.googleapis.com or other CDNs)
21+
22+
// Notes about the CSP below:
23+
// - We added img-src data: because data: images are used often.
24+
// - frame-ancestors: none mitigates clickjacking attacks. See https://owasp.org/www-community/attacks/Clickjacking.
25+
"Content-Security-Policy": "default-src 'self';script-src 'self';connect-src 'self' http://localhost:* https://icp0.io https://*.icp0.io https://icp-api.io;img-src 'self' data:;style-src * 'unsafe-inline';style-src-elem * 'unsafe-inline';font-src *;object-src 'none';base-uri 'self';frame-ancestors 'none';form-action 'self';upgrade-insecure-requests;",
26+
27+
// Security: The permissions policy disables all features for security reasons. If your site needs such permissions, activate them.
28+
// To configure permissions go here https://www.permissionspolicy.com/
29+
// This example updated the clipboard-write permission to allow writing to clipboard
30+
"Permissions-Policy": "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(self), gamepad=(), speaker-selection=(), conversion-measurement=(), focus-without-user-activation=(), hid=(), idle-detection=(), interest-cohort=(), serial=(), sync-script=(), trust-token-redemption=(), window-placement=(), vertical-scroll=()",
31+
32+
// Security: Mitigates clickjacking attacks.
33+
// See: https://owasp.org/www-community/attacks/Clickjacking.
34+
"X-Frame-Options": "DENY",
35+
36+
// Security: Avoids forwarding referrer information to other origins.
37+
// See: https://owasp.org/www-project-secure-headers/#referrer-policy.
38+
"Referrer-Policy": "same-origin",
39+
40+
// Security: Tells the user’s browser that it must always use HTTPS with your site.
41+
// See: https://owasp.org/www-project-secure-headers/#http-strict-transport-security
42+
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
43+
44+
// Security: Prevents the browser from interpreting files as a different MIME type to what is specified in the Content-Type header.
45+
// See: https://owasp.org/www-project-secure-headers/#x-content-type-options
46+
"X-Content-Type-Options": "nosniff",
47+
48+
// Security: Enables browser features to mitigate some of the XSS attacks. Note that it has to be in mode=block.
49+
// See: https://owasp.org/www-community/attacks/xss/
50+
"X-XSS-Protection": "1; mode=block"
51+
},
52+
// Uncomment to redirect all requests from .raw.icp0.io to .icp0.io
53+
// "allow_raw_access": false
54+
},
55+
]

hosting/oisy-signer-demo/frontend/src/hooks/useOisyWallet.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ export function useOisyWallet() {
1616
const [accountIdentifier, setAccountIdentifier] = useState(null);
1717
const [defaultAgent, setDefaultAgent] = useState(null);
1818
const [oisySignerAgent, setOisySignerAgent] = useState(null);
19-
const [oisyIcpLedgerAgent, setOisyIcpLedgerAgent] = useState(null);
20-
const [oisyCkUsdcLedgerAgent, setOisyCkUsdcLedgerAgent] = useState(null);
19+
const [oisyIcpActor, setOisyIcpActor] = useState(null);
20+
const [oisyCkUsdcActor, setOisyCkUsdcActor] = useState(null);
2121

2222
const [icpMetadata, setIcpMetadata] = useState();
2323
const [ckUsdcMetadata, setCkUsdcMetadata] = useState();
@@ -29,17 +29,17 @@ export function useOisyWallet() {
2929
const oisySigner = new Signer({ transport: oisyTransport });
3030

3131
useEffect(() => {
32-
if (oisySignerAgent && !oisyIcpLedgerAgent && !oisyCkUsdcLedgerAgent) {
33-
const oisyIcpLedgerAgent = IcrcLedgerCanister.create({
32+
if (oisySignerAgent && !oisyIcpActor && !oisyCkUsdcActor) {
33+
const oisyIcpActor = IcrcLedgerCanister.create({
3434
agent: oisySignerAgent,
3535
canisterId: Principal.fromText(ICP_LEDGER_ID),
3636
});
37-
const oisyckUsdcLedgerAgent = IcrcLedgerCanister.create({
37+
const oisyCkUsdcActor = IcrcLedgerCanister.create({
3838
agent: oisySignerAgent,
3939
canisterId: Principal.fromText(CKUSDC_LEDGER_ID),
4040
});
41-
setOisyIcpLedgerAgent(oisyIcpLedgerAgent);
42-
setOisyCkUsdcLedgerAgent(oisyckUsdcLedgerAgent);
41+
setOisyIcpActor(oisyIcpActor);
42+
setOisyCkUsdcActor(oisyCkUsdcActor);
4343
}
4444
// eslint-disable-next-line react-hooks/exhaustive-deps
4545
}, [oisySignerAgent]);
@@ -90,7 +90,7 @@ export function useOisyWallet() {
9090
const principal = icrcAccount.owner;
9191
const accountIdentifier = AccountIdentifier.fromPrincipal({ principal });
9292

93-
const defaultAgent = await HttpAgent.create({ host: 'https://ic0.app' });
93+
const defaultAgent = await HttpAgent.create({ host: 'https://icp0.io' });
9494
const signerAgent = await SignerAgent.create({
9595
agent: defaultAgent,
9696
signer: oisySigner,
@@ -110,8 +110,8 @@ export function useOisyWallet() {
110110
setAccountIdentifier(null);
111111
setDefaultAgent(null);
112112
setOisySignerAgent(null);
113-
setOisyIcpLedgerAgent(null);
114-
setOisyCkUsdcLedgerAgent(null);
113+
setOisyIcpActor(null);
114+
setOisyCkUsdcActor(null);
115115
setIcpBalance(null);
116116
setCkUsdcBalance(null);
117117
setIcpMetadata(undefined);
@@ -147,7 +147,7 @@ export function useOisyWallet() {
147147
ckUsdcBalance,
148148
icpMetadata,
149149
ckUsdcMetadata,
150-
transferIcp: () => transfer(oisyIcpLedgerAgent, icpMetadata),
151-
transferCkUsdc: () => transfer(oisyCkUsdcLedgerAgent, ckUsdcMetadata),
150+
transferIcp: () => transfer(oisyIcpActor, icpMetadata),
151+
transferCkUsdc: () => transfer(oisyCkUsdcActor, ckUsdcMetadata),
152152
};
153153
}

motoko/nft-creator/frontend/public/.ic-assets.json5

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111

1212
"headers": {
1313
"Content-Security-Policy": "default-src 'self';script-src 'self' 'unsafe-eval' 'unsafe-inline';connect-src 'self' http://localhost:* https://icp0.io https://*.icp0.io https://icp-api.io;img-src 'self' data: https://science.nasa.gov;style-src * 'unsafe-inline';style-src-elem * 'unsafe-inline';font-src *;object-src 'none';base-uri 'self';frame-ancestors 'none';form-action 'self';upgrade-insecure-requests;",
14+
// Security: The permissions policy disables all features for security reasons. If your site needs such permissions, activate them.
15+
// To configure permissions go here https://www.permissionspolicy.com/
16+
// This example updated the clipboard-write permission to allow writing to clipboard
17+
"Permissions-Policy": "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(self), gamepad=(), speaker-selection=(), conversion-measurement=(), focus-without-user-activation=(), hid=(), idle-detection=(), interest-cohort=(), serial=(), sync-script=(), trust-token-redemption=(), window-placement=(), vertical-scroll=()",
1418
},
1519

1620
// Uncomment to disable the warning about using the

motoko/nft-creator/src/declarations/internet_identity/internet_identity.did

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,12 @@ type CaptchaResult = ChallengeResult;
301301

302302
// Extra information about registration status for new devices
303303
type DeviceRegistrationInfo = record {
304-
// If present, the user has tentatively added a new device. This
305-
// new device needs to be verified (see relevant endpoint) before
306-
// 'expiration'.
304+
// If present, the user has registered a new authentication method. This new authentication
305+
// method needs to be confirmed before 'expiration' in order to be added to the identity.
307306
tentative_device : opt DeviceData;
307+
// If present, the user has registered a new session. This new session needs to be confirmed before
308+
// 'expiration' in order for it be authorized to register an authentication method to the identity.
309+
tentative_session : opt principal;
308310
// The timestamp at which the anchor will turn off registration mode
309311
// (and the tentative device will be forgotten, if any, and if not verified)
310312
expiration : Timestamp;
@@ -481,10 +483,13 @@ type OpenIDRegFinishArg = record {
481483

482484
// Extra information about registration status for new authentication methods
483485
type AuthnMethodRegistrationInfo = record {
484-
// If present, the user has registered a new authentication method. This
485-
// new authentication needs to be verified before 'expiration' in order to
486-
// be added to the identity.
486+
487+
// If present, the user has registered a new authentication method. This new authentication
488+
// method needs to be confirmed before 'expiration' in order to be added to the identity.
487489
authn_method : opt AuthnMethodData;
490+
// If present, the user has registered a new session. This new session needs to be confirmed before
491+
// 'expiration' in order for it be authorized to register an authentication method to the identity.
492+
session : opt principal;
488493
// The timestamp at which the identity will turn off registration mode
489494
// (and the authentication method will be forgotten, if any, and if not verified)
490495
expiration : Timestamp;
@@ -495,6 +500,10 @@ type AuthnMethodConfirmationCode = record {
495500
expiration : Timestamp;
496501
};
497502

503+
type AuthnMethodSessionInfo = record {
504+
name : opt text;
505+
};
506+
498507
type RegistrationId = text;
499508

500509
type AuthnMethodRegisterError = variant {
@@ -526,6 +535,13 @@ type AuthnMethodRegistrationModeEnterError = variant {
526535
InternalCanisterError : text;
527536
};
528537

538+
type AuthnMethodRegistrationModeExitError = variant {
539+
Unauthorized : principal;
540+
InternalCanisterError : text;
541+
RegistrationModeOff;
542+
InvalidMetadata : text;
543+
};
544+
529545
type LookupByRegistrationIdError = variant {
530546
InvalidRegistrationId : text;
531547
};
@@ -860,12 +876,19 @@ service : (opt InternetIdentityInit) -> {
860876

861877
// Exits the authentication method registration mode for the identity.
862878
// Requires authentication.
863-
authn_method_registration_mode_exit : (IdentityNumber) -> (variant { Ok; Err });
879+
authn_method_registration_mode_exit : (IdentityNumber, opt AuthnMethodData) -> (variant { Ok; Err : AuthnMethodRegistrationModeExitError });
864880

865881
// Registers a new authentication method to the identity.
866882
// This authentication method needs to be confirmed before it can be used for authentication on this identity.
867883
authn_method_register : (IdentityNumber, AuthnMethodData) -> (variant { Ok : AuthnMethodConfirmationCode; Err : AuthnMethodRegisterError });
868884

885+
// Registers a new session for the identity.
886+
// This session needs to be confirmed before it can be used to register an authentication method on this identity.
887+
authn_method_session_register : (IdentityNumber) -> (variant { Ok : AuthnMethodConfirmationCode; Err : AuthnMethodRegisterError });
888+
889+
// Returns session info when session is confirmed and caller matches session.
890+
authn_method_session_info : (IdentityNumber) -> (opt AuthnMethodSessionInfo) query;
891+
869892
// Confirms a previously registered authentication method.
870893
// On successful confirmation, the authentication method is permanently added to the identity and can
871894
// subsequently be used for authentication for that identity.

motoko/nft-creator/src/declarations/internet_identity/internet_identity.did.d.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ export type AuthnMethodRegisterError = { 'RegistrationModeOff' : null } |
7878
{ 'InvalidMetadata' : string };
7979
export interface AuthnMethodRegistrationInfo {
8080
'expiration' : Timestamp,
81+
'session' : [] | [Principal],
8182
'authn_method' : [] | [AuthnMethodData],
8283
}
8384
export type AuthnMethodRegistrationModeEnterError = {
@@ -86,6 +87,12 @@ export type AuthnMethodRegistrationModeEnterError = {
8687
{ 'InternalCanisterError' : string } |
8788
{ 'AlreadyInProgress' : null } |
8889
{ 'Unauthorized' : Principal };
90+
export type AuthnMethodRegistrationModeExitError = {
91+
'InternalCanisterError' : string
92+
} |
93+
{ 'RegistrationModeOff' : null } |
94+
{ 'Unauthorized' : Principal } |
95+
{ 'InvalidMetadata' : string };
8996
export type AuthnMethodReplaceError = { 'AuthnMethodNotFound' : null } |
9097
{ 'InvalidMetadata' : string };
9198
export interface AuthnMethodSecuritySettings {
@@ -95,6 +102,7 @@ export interface AuthnMethodSecuritySettings {
95102
export type AuthnMethodSecuritySettingsReplaceError = {
96103
'AuthnMethodNotFound' : null
97104
};
105+
export interface AuthnMethodSessionInfo { 'name' : [] | [string] }
98106
export interface BufferedArchiveEntry {
99107
'sequence_number' : bigint,
100108
'entry' : Uint8Array | number[],
@@ -156,6 +164,7 @@ export type DeviceProtection = { 'unprotected' : null } |
156164
export interface DeviceRegistrationInfo {
157165
'tentative_device' : [] | [DeviceData],
158166
'expiration' : Timestamp,
167+
'tentative_session' : [] | [Principal],
159168
}
160169
export interface DeviceWithUsage {
161170
'alias' : string,
@@ -442,9 +451,9 @@ export interface _SERVICE {
442451
{ 'Err' : AuthnMethodRegistrationModeEnterError }
443452
>,
444453
'authn_method_registration_mode_exit' : ActorMethod<
445-
[IdentityNumber],
454+
[IdentityNumber, [] | [AuthnMethodData]],
446455
{ 'Ok' : null } |
447-
{ 'Err' : null }
456+
{ 'Err' : AuthnMethodRegistrationModeExitError }
448457
>,
449458
'authn_method_remove' : ActorMethod<
450459
[IdentityNumber, PublicKey],
@@ -461,6 +470,15 @@ export interface _SERVICE {
461470
{ 'Ok' : null } |
462471
{ 'Err' : AuthnMethodSecuritySettingsReplaceError }
463472
>,
473+
'authn_method_session_info' : ActorMethod<
474+
[IdentityNumber],
475+
[] | [AuthnMethodSessionInfo]
476+
>,
477+
'authn_method_session_register' : ActorMethod<
478+
[IdentityNumber],
479+
{ 'Ok' : AuthnMethodConfirmationCode } |
480+
{ 'Err' : AuthnMethodRegisterError }
481+
>,
464482
'check_captcha' : ActorMethod<
465483
[CheckCaptchaArg],
466484
{ 'Ok' : IdRegNextStepResult } |

motoko/nft-creator/src/declarations/internet_identity/internet_identity.did.js

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,13 +169,20 @@ export const idlFactory = ({ IDL }) => {
169169
'AlreadyInProgress' : IDL.Null,
170170
'Unauthorized' : IDL.Principal,
171171
});
172+
const AuthnMethodRegistrationModeExitError = IDL.Variant({
173+
'InternalCanisterError' : IDL.Text,
174+
'RegistrationModeOff' : IDL.Null,
175+
'Unauthorized' : IDL.Principal,
176+
'InvalidMetadata' : IDL.Text,
177+
});
172178
const AuthnMethodReplaceError = IDL.Variant({
173179
'AuthnMethodNotFound' : IDL.Null,
174180
'InvalidMetadata' : IDL.Text,
175181
});
176182
const AuthnMethodSecuritySettingsReplaceError = IDL.Variant({
177183
'AuthnMethodNotFound' : IDL.Null,
178184
});
185+
const AuthnMethodSessionInfo = IDL.Record({ 'name' : IDL.Opt(IDL.Text) });
179186
const CheckCaptchaArg = IDL.Record({ 'solution' : IDL.Text });
180187
const RegistrationFlowNextStep = IDL.Variant({
181188
'CheckCaptcha' : IDL.Record({ 'captcha_png_base64' : IDL.Text }),
@@ -271,6 +278,7 @@ export const idlFactory = ({ IDL }) => {
271278
const DeviceRegistrationInfo = IDL.Record({
272279
'tentative_device' : IDL.Opt(DeviceData),
273280
'expiration' : Timestamp,
281+
'tentative_session' : IDL.Opt(IDL.Principal),
274282
});
275283
const IdentityAnchorInfo = IDL.Record({
276284
'name' : IDL.Opt(IDL.Text),
@@ -339,6 +347,7 @@ export const idlFactory = ({ IDL }) => {
339347
});
340348
const AuthnMethodRegistrationInfo = IDL.Record({
341349
'expiration' : Timestamp,
350+
'session' : IDL.Opt(IDL.Principal),
342351
'authn_method' : IDL.Opt(AuthnMethodData),
343352
});
344353
const IdentityInfo = IDL.Record({
@@ -527,8 +536,13 @@ export const idlFactory = ({ IDL }) => {
527536
[],
528537
),
529538
'authn_method_registration_mode_exit' : IDL.Func(
530-
[IdentityNumber],
531-
[IDL.Variant({ 'Ok' : IDL.Null, 'Err' : IDL.Null })],
539+
[IdentityNumber, IDL.Opt(AuthnMethodData)],
540+
[
541+
IDL.Variant({
542+
'Ok' : IDL.Null,
543+
'Err' : AuthnMethodRegistrationModeExitError,
544+
}),
545+
],
532546
[],
533547
),
534548
'authn_method_remove' : IDL.Func(
@@ -551,6 +565,21 @@ export const idlFactory = ({ IDL }) => {
551565
],
552566
[],
553567
),
568+
'authn_method_session_info' : IDL.Func(
569+
[IdentityNumber],
570+
[IDL.Opt(AuthnMethodSessionInfo)],
571+
['query'],
572+
),
573+
'authn_method_session_register' : IDL.Func(
574+
[IdentityNumber],
575+
[
576+
IDL.Variant({
577+
'Ok' : AuthnMethodConfirmationCode,
578+
'Err' : AuthnMethodRegisterError,
579+
}),
580+
],
581+
[],
582+
),
554583
'check_captcha' : IDL.Func(
555584
[CheckCaptchaArg],
556585
[

0 commit comments

Comments
 (0)