@oxy.so/core 1.12.1 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/crypto/webIdentityCarrier.js +1 -1
  3. package/dist/cjs/i18n/locales/ar-SA.json +33 -88
  4. package/dist/cjs/i18n/locales/ca-ES.json +35 -90
  5. package/dist/cjs/i18n/locales/de-DE.json +33 -88
  6. package/dist/cjs/i18n/locales/en-US.json +45 -141
  7. package/dist/cjs/i18n/locales/es-ES.json +44 -140
  8. package/dist/cjs/i18n/locales/fr-FR.json +33 -88
  9. package/dist/cjs/i18n/locales/it-IT.json +33 -88
  10. package/dist/cjs/i18n/locales/ja-JP.json +33 -88
  11. package/dist/cjs/i18n/locales/ko-KR.json +33 -88
  12. package/dist/cjs/i18n/locales/locales/ar-SA.json +33 -88
  13. package/dist/cjs/i18n/locales/locales/ca-ES.json +35 -90
  14. package/dist/cjs/i18n/locales/locales/de-DE.json +33 -88
  15. package/dist/cjs/i18n/locales/locales/en-US.json +45 -141
  16. package/dist/cjs/i18n/locales/locales/es-ES.json +44 -140
  17. package/dist/cjs/i18n/locales/locales/fr-FR.json +33 -88
  18. package/dist/cjs/i18n/locales/locales/it-IT.json +33 -88
  19. package/dist/cjs/i18n/locales/locales/ja-JP.json +33 -88
  20. package/dist/cjs/i18n/locales/locales/ko-KR.json +33 -88
  21. package/dist/cjs/i18n/locales/locales/pt-PT.json +33 -88
  22. package/dist/cjs/i18n/locales/locales/zh-CN.json +34 -89
  23. package/dist/cjs/i18n/locales/pt-PT.json +33 -88
  24. package/dist/cjs/i18n/locales/zh-CN.json +34 -89
  25. package/dist/cjs/index.js +10 -7
  26. package/dist/cjs/mixins/OxyServices.utility.js +140 -0
  27. package/dist/cjs/server/securityHeaders.js +19 -1
  28. package/dist/cjs/session/accountDialogController.js +37 -142
  29. package/dist/cjs/utils/authWebUrl.js +7 -6
  30. package/dist/cjs/utils/oauthPkce.js +5 -1
  31. package/dist/esm/.tsbuildinfo +1 -1
  32. package/dist/esm/crypto/webIdentityCarrier.js +1 -1
  33. package/dist/esm/i18n/locales/ar-SA.json +33 -88
  34. package/dist/esm/i18n/locales/ca-ES.json +35 -90
  35. package/dist/esm/i18n/locales/de-DE.json +33 -88
  36. package/dist/esm/i18n/locales/en-US.json +45 -141
  37. package/dist/esm/i18n/locales/es-ES.json +44 -140
  38. package/dist/esm/i18n/locales/fr-FR.json +33 -88
  39. package/dist/esm/i18n/locales/it-IT.json +33 -88
  40. package/dist/esm/i18n/locales/ja-JP.json +33 -88
  41. package/dist/esm/i18n/locales/ko-KR.json +33 -88
  42. package/dist/esm/i18n/locales/locales/ar-SA.json +33 -88
  43. package/dist/esm/i18n/locales/locales/ca-ES.json +35 -90
  44. package/dist/esm/i18n/locales/locales/de-DE.json +33 -88
  45. package/dist/esm/i18n/locales/locales/en-US.json +45 -141
  46. package/dist/esm/i18n/locales/locales/es-ES.json +44 -140
  47. package/dist/esm/i18n/locales/locales/fr-FR.json +33 -88
  48. package/dist/esm/i18n/locales/locales/it-IT.json +33 -88
  49. package/dist/esm/i18n/locales/locales/ja-JP.json +33 -88
  50. package/dist/esm/i18n/locales/locales/ko-KR.json +33 -88
  51. package/dist/esm/i18n/locales/locales/pt-PT.json +33 -88
  52. package/dist/esm/i18n/locales/locales/zh-CN.json +34 -89
  53. package/dist/esm/i18n/locales/pt-PT.json +33 -88
  54. package/dist/esm/i18n/locales/zh-CN.json +34 -89
  55. package/dist/esm/index.js +2 -1
  56. package/dist/esm/mixins/OxyServices.utility.js +138 -0
  57. package/dist/esm/server/securityHeaders.js +19 -1
  58. package/dist/esm/session/accountDialogController.js +37 -142
  59. package/dist/esm/utils/authWebUrl.js +6 -5
  60. package/dist/esm/utils/oauthPkce.js +5 -1
  61. package/dist/types/.tsbuildinfo +1 -1
  62. package/dist/types/crypto/webIdentityCarrier.d.ts +1 -1
  63. package/dist/types/index.d.ts +5 -3
  64. package/dist/types/mixins/OxyServices.utility.d.ts +84 -1
  65. package/dist/types/server/requesterAssertion.d.ts +2 -2
  66. package/dist/types/server/securityHeaders.d.ts +9 -12
  67. package/dist/types/session/accountDialogController.d.ts +29 -98
  68. package/dist/types/utils/authWebUrl.d.ts +6 -5
  69. package/dist/types/utils/oauthPkce.d.ts +10 -0
  70. package/package.json +2 -2
  71. package/src/crypto/webIdentityCarrier.ts +1 -1
  72. package/src/i18n/locales/ar-SA.json +33 -88
  73. package/src/i18n/locales/ca-ES.json +35 -90
  74. package/src/i18n/locales/de-DE.json +33 -88
  75. package/src/i18n/locales/en-US.json +45 -141
  76. package/src/i18n/locales/es-ES.json +44 -140
  77. package/src/i18n/locales/fr-FR.json +33 -88
  78. package/src/i18n/locales/it-IT.json +33 -88
  79. package/src/i18n/locales/ja-JP.json +33 -88
  80. package/src/i18n/locales/ko-KR.json +33 -88
  81. package/src/i18n/locales/pt-PT.json +33 -88
  82. package/src/i18n/locales/zh-CN.json +34 -89
  83. package/src/index.ts +9 -3
  84. package/src/mixins/OxyServices.utility.ts +208 -0
  85. package/src/mixins/__tests__/accountEvents.test.ts +158 -0
  86. package/src/server/__tests__/securityHeaders.test.ts +17 -0
  87. package/src/server/securityHeaders.ts +29 -1
  88. package/src/session/__tests__/accountDialogController.test.ts +42 -184
  89. package/src/session/accountDialogController.ts +50 -185
  90. package/src/utils/__tests__/oauthPkce.test.ts +7 -0
  91. package/src/utils/authWebUrl.ts +6 -5
  92. package/src/utils/oauthPkce.ts +16 -1
@@ -1,53 +1,48 @@
1
1
  {
2
2
  "signin": {
3
3
  "title": "登录",
4
- "subtitle": "登录以继续",
5
- "addAccountTitle": "添加另一个账户",
4
+ "subtitle": "使用你的 Oxy 账号",
5
+ "addAccountTitle": "添加其他账号",
6
6
  "addAccountSubtitle": "使用另一个账户登录",
7
7
  "username": {
8
8
  "label": "用户名",
9
- "placeholder": "输入您的用户名",
10
- "helper": "3-30个字符,仅字母和数字",
11
- "required": "请输入您的用户名。",
12
- "minLength": "用户名必须至少包含3个字符。"
13
- },
14
- "password": {
15
- "label": "密码",
16
- "placeholder": "输入您的密码",
17
- "required": "请输入您的密码。",
18
- "hint": "输入您的密码以登录"
9
+ "placeholder": "yourname",
10
+ "required": "请输入您的用户名。"
19
11
  },
20
12
  "actions": {
21
13
  "continue": "继续",
22
- "back": "返回",
23
- "signIn": "登录",
24
- "verify": "验证",
25
- "openAccountSwitcher": "切换到另一个账户",
26
- "openAccountSwitcherSubtitle": "{{count}}个其他账户可用",
27
- "openAccountSwitcherSubtitle_singular": "1个其他账户可用",
28
- "openAccountSwitcherSubtitle_zero": "查看您保存的账户",
29
- "manageAccounts": "管理保存的账户",
30
- "manageAccountsSubtitle": "查看会话、删除或登出",
31
- "loadingOtherAccounts": "加载其他账户中…",
32
- "switchAccountFailed": "无法切换账户。请重试。"
33
- },
34
- "forgotPrompt": "忘记密码?",
35
- "security": {
36
- "dataSecure": "您的数据已加密且安全"
14
+ "back": "返回"
37
15
  },
38
- "currentlySignedInAs": "当前登录为",
39
- "alreadySignedInWith": "已登录",
40
- "alreadySignedIn": "已登录",
41
- "alreadySignedInMessage": "此账户已登录。继续使用此账户?",
42
- "continueWithAccount": "继续",
43
- "currentAccount": "当前",
44
- "or": "或",
45
- "viewAllAccounts": "查看更多{{count}}个",
46
16
  "createAccountLink": "初次使用 Oxy?创建账户",
47
17
  "status": {
48
- "accountSwitched": "正在使用{{name}}",
49
18
  "signingIn": "正在登录…"
50
- }
19
+ },
20
+ "subtitleToApp": "以继续前往 {{app}}",
21
+ "orContinueWith": "或使用以下方式继续",
22
+ "qr": {
23
+ "caption": "使用 Commons 扫码登录",
24
+ "renew": "显示新的二维码"
25
+ },
26
+ "methods": {
27
+ "passkey": "使用通行密钥登录"
28
+ },
29
+ "errors": {
30
+ "rateLimited": "尝试次数过多。请在 {{seconds}} 秒后重试。",
31
+ "passkeyCancelled": "通行密钥提示已关闭。准备好后请重试。",
32
+ "passkeyFailed": "无法完成通行密钥验证。请重试。"
33
+ },
34
+ "chooser": {
35
+ "subtitleToApp": "以继续前往 {{app}}"
36
+ },
37
+ "terms": {
38
+ "before": "继续即表示你同意我们的",
39
+ "termsLink": "服务条款",
40
+ "and": "和",
41
+ "privacyLink": "隐私政策"
42
+ },
43
+ "noAccount": "还没有账号?",
44
+ "createAccount": "创建账号",
45
+ "recoverLink": "丢失了通行密钥?恢复你的账号"
51
46
  },
52
47
  "signup": {
53
48
  "title": "创建您的账户",
@@ -55,56 +50,9 @@
55
50
  "createInCommons": "在 Commons 中创建您的身份",
56
51
  "createAccount": "创建账户",
57
52
  "backToSignInLink": "已有账户?登录",
58
- "welcome": {
59
- "title": "欢迎使用Oxy!",
60
- "subtitle": "只需几步即可创建您的账户",
61
- "haveAccount": "已有账户?",
62
- "signInCta": "登录"
63
- },
64
- "identity": {
65
- "title": "您是谁?",
66
- "subtitle": "选择您的用户名并输入您的电子邮件"
67
- },
68
- "username": {
69
- "helper": "3-30个字符,仅字母和数字",
70
- "required": "请输入用户名",
71
- "minLength": "用户名必须至少包含3个字符"
72
- },
73
- "email": {
74
- "required": "请输入电子邮件地址",
75
- "invalid": "请输入有效的电子邮件地址",
76
- "helper": "我们绝不会分享您的电子邮件"
77
- },
78
- "security": {
79
- "title": "保护您的账户",
80
- "subtitle": "创建强密码以保护您的账户"
81
- },
82
- "password": {
83
- "helper": "至少8个字符",
84
- "required": "请输入密码",
85
- "minLength": "密码必须至少包含8个字符",
86
- "confirmRequired": "请确认您的密码",
87
- "mismatch": "密码不匹配",
88
- "confirmHint": "重新输入您的密码以确认"
89
- },
90
- "summary": {
91
- "title": "快完成了!",
92
- "subtitle": "查看您的信息并创建账户",
93
- "sectionTitle": "账户信息",
94
- "fields": {
95
- "username": "用户名",
96
- "email": "电子邮件",
97
- "password": "密码"
98
- },
99
- "notSet": "未设置",
100
- "securityTip": "为了更强的安全性,创建账户后,请在账户设置中启用生物识别身份验证。",
101
- "legalReminder": "创建账户即表示您同意我们的服务条款和隐私政策。"
102
- }
53
+ "webSubtitle": "无需密码。你的设备会创建通行密钥,你的账号会获得一个只有你保管的恢复短语。"
103
54
  },
104
55
  "accountSwitcher": {
105
- "sections": {
106
- "yourAccounts": "你的账户"
107
- },
108
56
  "loading": "正在加载账户...",
109
57
  "qrHeadline": "使用您的 Oxy 身份登录",
110
58
  "signInWithOxy": "使用 Oxy 登录",
@@ -136,10 +84,7 @@
136
84
  "claimFailed": "登录已获批准,但未能完成。请重试。",
137
85
  "generic": "登录失败,请重试。"
138
86
  },
139
- "linkOpenFailed": "无法打开链接,请重试。",
140
- "continueWithPasskey": "继续",
141
- "passkeyHint": "使用指纹、面容或设备 PIN 码。",
142
- "otherDeviceCommons": "账号在其他设备上?用 Commons 扫码"
87
+ "linkOpenFailed": "无法打开链接,请重试。"
143
88
  },
144
89
  "common": {
145
90
  "actions": {
@@ -1,53 +1,48 @@
1
1
  {
2
2
  "signin": {
3
3
  "title": "Iniciar sessão",
4
- "subtitle": "Inicie sessão para continuar",
4
+ "subtitle": "Usa a tua conta Oxy",
5
5
  "addAccountTitle": "Adicionar outra conta",
6
6
  "addAccountSubtitle": "Iniciar sessão com outra conta",
7
7
  "username": {
8
8
  "label": "Nome de utilizador",
9
- "placeholder": "Introduza o seu nome de utilizador",
10
- "helper": "3-30 caracteres, apenas letras e números",
11
- "required": "Por favor, introduza o seu nome de utilizador.",
12
- "minLength": "O nome de utilizador deve ter pelo menos 3 caracteres."
13
- },
14
- "password": {
15
- "label": "Palavra-passe",
16
- "placeholder": "Introduza a sua palavra-passe",
17
- "required": "Por favor, introduza a sua palavra-passe.",
18
- "hint": "Introduza a sua palavra-passe para iniciar sessão"
9
+ "placeholder": "oteunome",
10
+ "required": "Por favor, introduza o seu nome de utilizador."
19
11
  },
20
12
  "actions": {
21
13
  "continue": "Continuar",
22
- "back": "Voltar",
23
- "signIn": "Iniciar sessão",
24
- "verify": "Verificar",
25
- "openAccountSwitcher": "Mudar para outra conta",
26
- "openAccountSwitcherSubtitle": "{{count}} outras contas disponíveis",
27
- "openAccountSwitcherSubtitle_singular": "1 outra conta disponível",
28
- "openAccountSwitcherSubtitle_zero": "Revise as suas contas guardadas",
29
- "manageAccounts": "Gerir contas guardadas",
30
- "manageAccountsSubtitle": "Rever sessões, remover ou terminar sessão",
31
- "loadingOtherAccounts": "A carregar outras contas…",
32
- "switchAccountFailed": "Não foi possível mudar de conta. Por favor, tente novamente."
14
+ "back": "Voltar"
33
15
  },
34
- "forgotPrompt": "Esqueceu-se da palavra-passe?",
35
- "security": {
36
- "dataSecure": "Os seus dados estão encriptados e seguros"
37
- },
38
- "currentlySignedInAs": "Atualmente com sessão iniciada como",
39
- "alreadySignedInWith": "Já tem sessão iniciada com",
40
- "alreadySignedIn": "Já tem sessão iniciada",
41
- "alreadySignedInMessage": "Esta conta já tem sessão iniciada. Continuar com esta conta?",
42
- "continueWithAccount": "Continuar",
43
- "currentAccount": "Atual",
44
- "or": "ou",
45
- "viewAllAccounts": "Ver mais {{count}}",
46
16
  "createAccountLink": "Novo no Oxy? Crie uma conta",
47
17
  "status": {
48
- "accountSwitched": "Agora a usar {{name}}",
49
18
  "signingIn": "A iniciar sessão…"
50
- }
19
+ },
20
+ "subtitleToApp": "para continuar para {{app}}",
21
+ "orContinueWith": "ou continua com",
22
+ "qr": {
23
+ "caption": "Lê com o Commons para entrar",
24
+ "renew": "Mostrar um código novo"
25
+ },
26
+ "methods": {
27
+ "passkey": "Entrar com uma chave de acesso"
28
+ },
29
+ "errors": {
30
+ "rateLimited": "Demasiadas tentativas. Tenta novamente dentro de {{seconds}} s.",
31
+ "passkeyCancelled": "Fechaste o pedido da chave de acesso. Tenta novamente quando quiseres.",
32
+ "passkeyFailed": "Não foi possível concluir a chave de acesso. Tenta novamente."
33
+ },
34
+ "chooser": {
35
+ "subtitleToApp": "para continuar para {{app}}"
36
+ },
37
+ "terms": {
38
+ "before": "Ao continuar, aceitas os nossos",
39
+ "termsLink": "Termos de serviço",
40
+ "and": "e a",
41
+ "privacyLink": "Política de privacidade"
42
+ },
43
+ "noAccount": "Não tens conta?",
44
+ "createAccount": "Criar conta",
45
+ "recoverLink": "Perdeste a chave de acesso? Recupera a tua conta"
51
46
  },
52
47
  "signup": {
53
48
  "title": "Crie a sua conta",
@@ -55,56 +50,9 @@
55
50
  "createInCommons": "Crie a sua identidade no Commons",
56
51
  "createAccount": "Criar conta",
57
52
  "backToSignInLink": "Já tem uma conta? Inicie sessão",
58
- "welcome": {
59
- "title": "Bem-vindo ao Oxy!",
60
- "subtitle": "Crie a sua conta em poucos passos",
61
- "haveAccount": "Já tem uma conta?",
62
- "signInCta": "Iniciar sessão"
63
- },
64
- "identity": {
65
- "title": "Quem é?",
66
- "subtitle": "Escolha o seu nome de utilizador e introduza o seu email"
67
- },
68
- "username": {
69
- "helper": "3-30 caracteres, apenas letras e números",
70
- "required": "Por favor, introduza um nome de utilizador",
71
- "minLength": "O nome de utilizador deve ter pelo menos 3 caracteres"
72
- },
73
- "email": {
74
- "required": "Por favor, introduza um endereço de email",
75
- "invalid": "Por favor, introduza um endereço de email válido",
76
- "helper": "Nunca partilharemos o seu email"
77
- },
78
- "security": {
79
- "title": "Proteja a sua conta",
80
- "subtitle": "Crie uma palavra-passe forte para proteger a sua conta"
81
- },
82
- "password": {
83
- "helper": "Pelo menos 8 caracteres",
84
- "required": "Por favor, introduza uma palavra-passe",
85
- "minLength": "A palavra-passe deve ter pelo menos 8 caracteres",
86
- "confirmRequired": "Por favor, confirme a sua palavra-passe",
87
- "mismatch": "As palavras-passe não coincidem",
88
- "confirmHint": "Reintroduza a sua palavra-passe para confirmar"
89
- },
90
- "summary": {
91
- "title": "Quase lá!",
92
- "subtitle": "Revise as suas informações e crie a sua conta",
93
- "sectionTitle": "Informações da conta",
94
- "fields": {
95
- "username": "Nome de utilizador",
96
- "email": "Email",
97
- "password": "Palavra-passe"
98
- },
99
- "notSet": "Não definido",
100
- "securityTip": "Para maior segurança, ative a autenticação biométrica nas Definições da conta após criar a sua conta.",
101
- "legalReminder": "Ao criar uma conta, concorda com os nossos Termos de Serviço e Política de Privacidade."
102
- }
53
+ "webSubtitle": "Sem palavra-passe. O teu dispositivo cria uma chave de acesso e a tua conta recebe uma frase de recuperação que só tu guardas."
103
54
  },
104
55
  "accountSwitcher": {
105
- "sections": {
106
- "yourAccounts": "As suas contas"
107
- },
108
56
  "loading": "A carregar contas...",
109
57
  "qrHeadline": "Inicie sessão com a sua identidade Oxy",
110
58
  "signInWithOxy": "Iniciar sessão com Oxy",
@@ -136,10 +84,7 @@
136
84
  "claimFailed": "O início de sessão foi aprovado, mas não conseguimos concluí-lo. Tente novamente.",
137
85
  "generic": "Não foi possível iniciar sessão. Tente novamente."
138
86
  },
139
- "linkOpenFailed": "Não foi possível abrir a ligação. Tente novamente.",
140
- "continueWithPasskey": "Continuar",
141
- "passkeyHint": "Use a impressão digital, o rosto ou o PIN do dispositivo.",
142
- "otherDeviceCommons": "Conta noutro dispositivo? Digitalize com o Commons"
87
+ "linkOpenFailed": "Não foi possível abrir a ligação. Tente novamente."
143
88
  },
144
89
  "common": {
145
90
  "actions": {
@@ -1,53 +1,48 @@
1
1
  {
2
2
  "signin": {
3
3
  "title": "登录",
4
- "subtitle": "登录以继续",
5
- "addAccountTitle": "添加另一个账户",
4
+ "subtitle": "使用你的 Oxy 账号",
5
+ "addAccountTitle": "添加其他账号",
6
6
  "addAccountSubtitle": "使用另一个账户登录",
7
7
  "username": {
8
8
  "label": "用户名",
9
- "placeholder": "输入您的用户名",
10
- "helper": "3-30个字符,仅字母和数字",
11
- "required": "请输入您的用户名。",
12
- "minLength": "用户名必须至少包含3个字符。"
13
- },
14
- "password": {
15
- "label": "密码",
16
- "placeholder": "输入您的密码",
17
- "required": "请输入您的密码。",
18
- "hint": "输入您的密码以登录"
9
+ "placeholder": "yourname",
10
+ "required": "请输入您的用户名。"
19
11
  },
20
12
  "actions": {
21
13
  "continue": "继续",
22
- "back": "返回",
23
- "signIn": "登录",
24
- "verify": "验证",
25
- "openAccountSwitcher": "切换到另一个账户",
26
- "openAccountSwitcherSubtitle": "{{count}}个其他账户可用",
27
- "openAccountSwitcherSubtitle_singular": "1个其他账户可用",
28
- "openAccountSwitcherSubtitle_zero": "查看您保存的账户",
29
- "manageAccounts": "管理保存的账户",
30
- "manageAccountsSubtitle": "查看会话、删除或登出",
31
- "loadingOtherAccounts": "加载其他账户中…",
32
- "switchAccountFailed": "无法切换账户。请重试。"
33
- },
34
- "forgotPrompt": "忘记密码?",
35
- "security": {
36
- "dataSecure": "您的数据已加密且安全"
14
+ "back": "返回"
37
15
  },
38
- "currentlySignedInAs": "当前登录为",
39
- "alreadySignedInWith": "已登录",
40
- "alreadySignedIn": "已登录",
41
- "alreadySignedInMessage": "此账户已登录。继续使用此账户?",
42
- "continueWithAccount": "继续",
43
- "currentAccount": "当前",
44
- "or": "或",
45
- "viewAllAccounts": "查看更多{{count}}个",
46
16
  "createAccountLink": "初次使用 Oxy?创建账户",
47
17
  "status": {
48
- "accountSwitched": "正在使用{{name}}",
49
18
  "signingIn": "正在登录…"
50
- }
19
+ },
20
+ "subtitleToApp": "以继续前往 {{app}}",
21
+ "orContinueWith": "或使用以下方式继续",
22
+ "qr": {
23
+ "caption": "使用 Commons 扫码登录",
24
+ "renew": "显示新的二维码"
25
+ },
26
+ "methods": {
27
+ "passkey": "使用通行密钥登录"
28
+ },
29
+ "errors": {
30
+ "rateLimited": "尝试次数过多。请在 {{seconds}} 秒后重试。",
31
+ "passkeyCancelled": "通行密钥提示已关闭。准备好后请重试。",
32
+ "passkeyFailed": "无法完成通行密钥验证。请重试。"
33
+ },
34
+ "chooser": {
35
+ "subtitleToApp": "以继续前往 {{app}}"
36
+ },
37
+ "terms": {
38
+ "before": "继续即表示你同意我们的",
39
+ "termsLink": "服务条款",
40
+ "and": "和",
41
+ "privacyLink": "隐私政策"
42
+ },
43
+ "noAccount": "还没有账号?",
44
+ "createAccount": "创建账号",
45
+ "recoverLink": "丢失了通行密钥?恢复你的账号"
51
46
  },
52
47
  "signup": {
53
48
  "title": "创建您的账户",
@@ -55,56 +50,9 @@
55
50
  "createInCommons": "在 Commons 中创建您的身份",
56
51
  "createAccount": "创建账户",
57
52
  "backToSignInLink": "已有账户?登录",
58
- "welcome": {
59
- "title": "欢迎使用Oxy!",
60
- "subtitle": "只需几步即可创建您的账户",
61
- "haveAccount": "已有账户?",
62
- "signInCta": "登录"
63
- },
64
- "identity": {
65
- "title": "您是谁?",
66
- "subtitle": "选择您的用户名并输入您的电子邮件"
67
- },
68
- "username": {
69
- "helper": "3-30个字符,仅字母和数字",
70
- "required": "请输入用户名",
71
- "minLength": "用户名必须至少包含3个字符"
72
- },
73
- "email": {
74
- "required": "请输入电子邮件地址",
75
- "invalid": "请输入有效的电子邮件地址",
76
- "helper": "我们绝不会分享您的电子邮件"
77
- },
78
- "security": {
79
- "title": "保护您的账户",
80
- "subtitle": "创建强密码以保护您的账户"
81
- },
82
- "password": {
83
- "helper": "至少8个字符",
84
- "required": "请输入密码",
85
- "minLength": "密码必须至少包含8个字符",
86
- "confirmRequired": "请确认您的密码",
87
- "mismatch": "密码不匹配",
88
- "confirmHint": "重新输入您的密码以确认"
89
- },
90
- "summary": {
91
- "title": "快完成了!",
92
- "subtitle": "查看您的信息并创建账户",
93
- "sectionTitle": "账户信息",
94
- "fields": {
95
- "username": "用户名",
96
- "email": "电子邮件",
97
- "password": "密码"
98
- },
99
- "notSet": "未设置",
100
- "securityTip": "为了更强的安全性,创建账户后,请在账户设置中启用生物识别身份验证。",
101
- "legalReminder": "创建账户即表示您同意我们的服务条款和隐私政策。"
102
- }
53
+ "webSubtitle": "无需密码。你的设备会创建通行密钥,你的账号会获得一个只有你保管的恢复短语。"
103
54
  },
104
55
  "accountSwitcher": {
105
- "sections": {
106
- "yourAccounts": "你的账户"
107
- },
108
56
  "loading": "正在加载账户...",
109
57
  "qrHeadline": "使用您的 Oxy 身份登录",
110
58
  "signInWithOxy": "使用 Oxy 登录",
@@ -136,10 +84,7 @@
136
84
  "claimFailed": "登录已获批准,但未能完成。请重试。",
137
85
  "generic": "登录失败,请重试。"
138
86
  },
139
- "linkOpenFailed": "无法打开链接,请重试。",
140
- "continueWithPasskey": "继续",
141
- "passkeyHint": "使用指纹、面容或设备 PIN 码。",
142
- "otherDeviceCommons": "账号在其他设备上?用 Commons 扫码"
87
+ "linkOpenFailed": "无法打开链接,请重试。"
143
88
  },
144
89
  "common": {
145
90
  "actions": {
package/dist/esm/index.js CHANGED
@@ -34,6 +34,7 @@ export { getCommonsApprovalBlockingReason, parseCommonsApprovalExpiresAt, } from
34
34
  // Automatic "Sign in with Oxy" delivery selection — ONE pure decision that maps
35
35
  // the caller's facts onto exactly one primary route (open Commons / await push / QR).
36
36
  export { selectCommonsDelivery, pushTargetsFromDelivery, commonsDeliveryPlatform } from './utils/commonsDelivery.js';
37
+ export { OxyAccountEventError, OXY_ACCOUNT_DELETED_EVENT_URI } from './mixins/OxyServices.utility.js';
37
38
  export { OxyAppDataIdentifierError } from './mixins/OxyServices.appData.js';
38
39
  // ---------------------------------------------------------------------------
39
40
  // User identity and handles
@@ -157,7 +158,7 @@ export { buildAccountsArray, createQuickAccount, getAccountDisplayName, getAccou
157
158
  // `*.oxy.so`).
158
159
  // ---------------------------------------------------------------------------
159
160
  export { registrableApex } from './utils/registrableApex.js';
160
- export { CENTRAL_IDP_APEX, IDENTITY_WEB_ORIGIN } from './utils/authWebUrl.js';
161
+ export { AUTH_WEB_ORIGIN, CENTRAL_IDP_APEX } from './utils/authWebUrl.js';
161
162
  // WebAuthn relying-party origin guard (client side). Mirrors the server's
162
163
  // `isOxyApexOrigin` so consumers can decide whether to offer passkey UI on the
163
164
  // current page (first-party Oxy origin / loopback only).
@@ -7,6 +7,15 @@ import { jwtDecode } from 'jwt-decode';
7
7
  import { loadNodeCrypto } from '@oxy.so/protocol';
8
8
  import { logger } from '../logger/index.js';
9
9
  import { OXY_SERVICE_ENVIRONMENTS } from '../utils/oxyServiceEnvironment.js';
10
+ /** The SET `events` member Oxy uses for an account deletion. */
11
+ export const OXY_ACCOUNT_DELETED_EVENT_URI = 'https://oxy.so/events/account.deleted';
12
+ /** Why an account event token was refused. `message` never contains the token. */
13
+ export class OxyAccountEventError extends Error {
14
+ constructor(message) {
15
+ super(message);
16
+ this.name = 'OxyAccountEventError';
17
+ }
18
+ }
10
19
  /**
11
20
  * Expected JWT audience for tokens issued by the Oxy auth service.
12
21
  */
@@ -133,6 +142,135 @@ export function OxyServicesUtilityMixin(Base) {
133
142
  return null;
134
143
  }
135
144
  }
145
+ /**
146
+ * Verify an account event token from Oxy — the body of an account-event
147
+ * webhook, or an entry's `token` from `listAccountEvents` — and return the
148
+ * event. Throws {@link OxyAccountEventError} unless the token is an
149
+ * EdDSA-signed `secevent+jwt` from Oxy's published key set, issued by
150
+ * `oxy-auth`, addressed to this application, carrying exactly one known
151
+ * event. A service token (`typ: JWT`) is refused here, as this token is
152
+ * refused as a service token.
153
+ *
154
+ * Node only (it needs `node:crypto`). The caller must still be idempotent on
155
+ * `eventId`: Oxy delivers at least once, by push and by pull.
156
+ */
157
+ async verifyAccountEvent(token, options = {}) {
158
+ if (typeof token !== 'string' || token.length === 0 || token.length > 16 * 1024) {
159
+ throw new OxyAccountEventError('Account event token is missing or oversized');
160
+ }
161
+ const parts = token.split('.');
162
+ if (parts.length !== 3 || parts.some((part) => part.length === 0)) {
163
+ throw new OxyAccountEventError('Account event token is not a compact JWS');
164
+ }
165
+ const [headerB64, payloadB64, signatureB64] = parts;
166
+ let header;
167
+ let payload;
168
+ try {
169
+ header = parseJsonSegment(headerB64);
170
+ payload = parseJsonSegment(payloadB64);
171
+ }
172
+ catch {
173
+ throw new OxyAccountEventError('Account event token is malformed');
174
+ }
175
+ if (Object.keys(header).length !== 3
176
+ || header.alg !== 'EdDSA'
177
+ || header.typ !== 'secevent+jwt'
178
+ || typeof header.kid !== 'string'
179
+ || !/^[A-Za-z0-9._-]{1,128}$/.test(header.kid)) {
180
+ throw new OxyAccountEventError('Account event token header is not supported');
181
+ }
182
+ const nodeCrypto = await loadNodeCrypto();
183
+ let jwk;
184
+ try {
185
+ jwk = await resolveServiceTokenPublicKey(header.kid, options.jwksUrl ?? new URL('/.well-known/jwks.json', this.getBaseURL()).toString(), this._serviceTokenJwksCache);
186
+ }
187
+ catch (error) {
188
+ throw new OxyAccountEventError(error instanceof Error ? error.message.replace('Service token', 'Account event') : 'Signing key is unavailable');
189
+ }
190
+ const signature = Buffer.from(signatureB64, 'base64url');
191
+ if (signature.toString('base64url') !== signatureB64 || signature.length !== 64) {
192
+ throw new OxyAccountEventError('Account event token signature is malformed');
193
+ }
194
+ let verified = false;
195
+ try {
196
+ const publicKey = nodeCrypto.createPublicKey({ key: jwk, format: 'jwk' });
197
+ verified = nodeCrypto.verify(null, Buffer.from(`${headerB64}.${payloadB64}`), publicKey, signature);
198
+ }
199
+ catch {
200
+ verified = false;
201
+ }
202
+ if (!verified)
203
+ throw new OxyAccountEventError('Account event token signature is invalid');
204
+ if (payload.iss !== OXY_JWT_ISSUER) {
205
+ throw new OxyAccountEventError('Account event token issuer is not Oxy');
206
+ }
207
+ const audience = options.audience ?? await this._configuredServiceAppId();
208
+ if (typeof payload.aud !== 'string' || payload.aud !== audience) {
209
+ throw new OxyAccountEventError('Account event token is addressed to another application');
210
+ }
211
+ if (typeof payload.jti !== 'string' || payload.jti.length === 0 || payload.jti.length > 128) {
212
+ throw new OxyAccountEventError('Account event token has no event id');
213
+ }
214
+ if (typeof payload.iat !== 'number' || !Number.isFinite(payload.iat)) {
215
+ throw new OxyAccountEventError('Account event token has no issue time');
216
+ }
217
+ const events = payload.events;
218
+ if (typeof events !== 'object' || events === null || Array.isArray(events)) {
219
+ throw new OxyAccountEventError('Account event token carries no events');
220
+ }
221
+ const entries = Object.entries(events);
222
+ const deleted = events[OXY_ACCOUNT_DELETED_EVENT_URI];
223
+ if (entries.length !== 1 || typeof deleted !== 'object' || deleted === null || Array.isArray(deleted)) {
224
+ throw new OxyAccountEventError('Account event token carries an unknown event');
225
+ }
226
+ const body = deleted;
227
+ if (typeof body.userId !== 'string' || body.userId.length === 0 || body.userId.length > 128) {
228
+ throw new OxyAccountEventError('Account event names no account');
229
+ }
230
+ if (typeof body.occurredAt !== 'string' || Number.isNaN(Date.parse(body.occurredAt))) {
231
+ throw new OxyAccountEventError('Account event has no occurrence time');
232
+ }
233
+ if (body.username !== undefined && body.username !== null && typeof body.username !== 'string') {
234
+ throw new OxyAccountEventError('Account event username is malformed');
235
+ }
236
+ return {
237
+ eventId: payload.jti,
238
+ type: 'account.deleted',
239
+ userId: body.userId,
240
+ username: typeof body.username === 'string' ? body.username : null,
241
+ occurredAt: body.occurredAt,
242
+ retained: body.retained === true,
243
+ applicationId: payload.aud,
244
+ issuedAt: payload.iat,
245
+ };
246
+ }
247
+ /**
248
+ * One page of account events addressed to this application, oldest first,
249
+ * from Oxy's pull feed — the reconciliation path behind the webhook. Needs
250
+ * the service credential (`configureServiceAuth`). Verify each entry's
251
+ * `token` with {@link verifyAccountEvent} before acting on it.
252
+ */
253
+ async listAccountEvents(options = {}) {
254
+ const serviceToken = await this.getServiceToken();
255
+ const query = {};
256
+ if (options.after)
257
+ query.after = options.after;
258
+ if (options.limit !== undefined)
259
+ query.limit = String(options.limit);
260
+ return this.makeRequest('GET', '/account-events', query, {
261
+ cache: false,
262
+ headers: { Authorization: `Bearer ${serviceToken}` },
263
+ });
264
+ }
265
+ /** @internal The `appId` claim of this client's own service token. */
266
+ async _configuredServiceAppId() {
267
+ const serviceToken = await this.getServiceToken();
268
+ const appId = jwtDecode(serviceToken).appId;
269
+ if (typeof appId !== 'string' || appId.length === 0) {
270
+ throw new OxyAccountEventError('No audience given and the service credential names no application');
271
+ }
272
+ return appId;
273
+ }
136
274
  /**
137
275
  * Express.js authentication middleware
138
276
  *