@novasamatech/host-papp 0.8.3 → 0.8.5
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.
- package/dist/sso/auth/impl.d.ts +7 -0
- package/dist/sso/auth/impl.js +6 -1
- package/dist/sso/auth/scale/handshakeV2.d.ts +37 -4
- package/dist/sso/auth/scale/handshakeV2.js +46 -6
- package/dist/sso/auth/v2/state.d.ts +10 -0
- package/dist/sso/auth/v2/state.js +1 -0
- package/dist/sso/sessionManager/userSession.js +6 -0
- package/dist/sso/userSessionRepository.d.ts +13 -0
- package/dist/sso/userSessionRepository.js +6 -0
- package/package.json +5 -5
package/dist/sso/auth/impl.d.ts
CHANGED
|
@@ -17,6 +17,13 @@ export type AuthComponent = ReturnType<typeof createAuth>;
|
|
|
17
17
|
export type OnAuthSuccess = (event: {
|
|
18
18
|
session: StoredUserSession;
|
|
19
19
|
identityChatPrivateKey: Uint8Array;
|
|
20
|
+
/**
|
|
21
|
+
* `papp_encr_pub` from Mobile SSO spec v0.2.2. `null` when the peer
|
|
22
|
+
* shipped a pre-v0.2.2 `HandshakeSuccessV2` body (no `sso_encr_pub_key`
|
|
23
|
+
* field on the wire). The host's SSO session transport stays inactive
|
|
24
|
+
* while null; chat is unaffected since it uses `identityChatPrivateKey`.
|
|
25
|
+
*/
|
|
26
|
+
ssoEncPubKey: Uint8Array | null;
|
|
20
27
|
}) => Promise<void> | void;
|
|
21
28
|
type Params = {
|
|
22
29
|
hostMetadata?: HostMetadata;
|
package/dist/sso/auth/impl.js
CHANGED
|
@@ -152,6 +152,7 @@ export function createAuth({ hostMetadata, deviceIdentity, deviceIdentityStore,
|
|
|
152
152
|
const session = createStoredUserSession(localAccount, remoteAccount, createAccountId(success.rootAccountId ?? new Uint8Array(32)), {
|
|
153
153
|
identityAccountId: createAccountId(success.identityAccountId),
|
|
154
154
|
identityChatPublicKey: success.identityChatPublicKey,
|
|
155
|
+
ssoEncPubKey: success.ssoEncPubKey ?? undefined,
|
|
155
156
|
});
|
|
156
157
|
return userSecretRepository
|
|
157
158
|
.write(session.id, {
|
|
@@ -162,7 +163,11 @@ export function createAuth({ hostMetadata, deviceIdentity, deviceIdentityStore,
|
|
|
162
163
|
})
|
|
163
164
|
.andThen(() => ssoSessionRepository.add(session))
|
|
164
165
|
.andThen(() => onAuthSuccess
|
|
165
|
-
? ResultAsync.fromPromise(Promise.resolve(onAuthSuccess({
|
|
166
|
+
? ResultAsync.fromPromise(Promise.resolve(onAuthSuccess({
|
|
167
|
+
session,
|
|
168
|
+
identityChatPrivateKey: success.identityChatPrivateKey,
|
|
169
|
+
ssoEncPubKey: success.ssoEncPubKey,
|
|
170
|
+
})), toError).map(() => session)
|
|
166
171
|
: okAsync(session));
|
|
167
172
|
}
|
|
168
173
|
}
|
|
@@ -131,11 +131,22 @@ export declare const VersionedHandshakeProposal: import("scale-ts").Codec<{
|
|
|
131
131
|
}, string][];
|
|
132
132
|
};
|
|
133
133
|
}>;
|
|
134
|
-
/**
|
|
134
|
+
/**
|
|
135
|
+
* 32 + 32 + 32 + 65 + 65 = 226 bytes (spec v0.2.2).
|
|
136
|
+
*
|
|
137
|
+
* `ssoEncPubKey` is `papp_encr_pub` per spec § Encrypted response — V2 — the
|
|
138
|
+
* P-256 public key PApp uses for SSO session ECDH. Required to compute
|
|
139
|
+
* `shared_secret_session = ECDH(host_encr_secret, ssoEncPubKey)`. PApp keypair
|
|
140
|
+
* derivation is implementation-defined: Android derives under `//wallet//sso`
|
|
141
|
+
* (`SsoDerivationDomains.SSO_DERIVATION_DOMAIN`); iOS currently reuses
|
|
142
|
+
* `//wallet//chat`. The host treats this field as opaque public material —
|
|
143
|
+
* which keypair PApp picked is invisible here.
|
|
144
|
+
*/
|
|
135
145
|
export declare const HandshakeSuccessV2: import("scale-ts").Codec<{
|
|
136
146
|
identityAccountId: Uint8Array<ArrayBufferLike>;
|
|
137
147
|
rootAccountId: Uint8Array<ArrayBufferLike>;
|
|
138
148
|
identityChatPrivateKey: Uint8Array<ArrayBufferLike>;
|
|
149
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike>;
|
|
139
150
|
deviceEncPubKey: Uint8Array<ArrayBufferLike>;
|
|
140
151
|
}>;
|
|
141
152
|
export type HandshakeSuccessV2Value = {
|
|
@@ -143,8 +154,22 @@ export type HandshakeSuccessV2Value = {
|
|
|
143
154
|
/** Nullable for v0.2 peers (Android `feature/location-for-handshake`). */
|
|
144
155
|
rootAccountId: Uint8Array | null;
|
|
145
156
|
identityChatPrivateKey: Uint8Array;
|
|
157
|
+
/**
|
|
158
|
+
* Nullable for v0.2 / v0.2.1 peers (any PApp build that does not yet ship
|
|
159
|
+
* spec v0.2.2). The host's SSO session transport stays inactive while
|
|
160
|
+
* null — sign/vrf/etc operations fail at the boundary until PApp emits
|
|
161
|
+
* the new field.
|
|
162
|
+
*/
|
|
163
|
+
ssoEncPubKey: Uint8Array | null;
|
|
146
164
|
deviceEncPubKey: Uint8Array;
|
|
147
165
|
};
|
|
166
|
+
/** 32 + 32 + 32 + 65 = 161 bytes (spec v0.2.1) */
|
|
167
|
+
export declare const HandshakeSuccessV2_v021: import("scale-ts").Codec<{
|
|
168
|
+
identityAccountId: Uint8Array<ArrayBufferLike>;
|
|
169
|
+
rootAccountId: Uint8Array<ArrayBufferLike>;
|
|
170
|
+
identityChatPrivateKey: Uint8Array<ArrayBufferLike>;
|
|
171
|
+
deviceEncPubKey: Uint8Array<ArrayBufferLike>;
|
|
172
|
+
}>;
|
|
148
173
|
/** 32 + 32 + 65 = 129 bytes (spec v0.2 — Android `feature/location-for-handshake`) */
|
|
149
174
|
export declare const HandshakeSuccessV2Legacy: import("scale-ts").Codec<{
|
|
150
175
|
identityAccountId: Uint8Array<ArrayBufferLike>;
|
|
@@ -166,9 +191,16 @@ export type DecodedHandshakeResponseV2 = {
|
|
|
166
191
|
};
|
|
167
192
|
/**
|
|
168
193
|
* Length-dispatched decoder for the inner `EncryptedHandshakeResponseV2`
|
|
169
|
-
* plaintext.
|
|
170
|
-
*
|
|
171
|
-
*
|
|
194
|
+
* plaintext. Three Success body shapes are accepted, one per spec rev:
|
|
195
|
+
*
|
|
196
|
+
* 226 bytes (spec v0.2.2) — includes `ssoEncPubKey` (`papp_encr_pub`).
|
|
197
|
+
* 161 bytes (spec v0.2.1) — `ssoEncPubKey` absent; surfaced as `null`.
|
|
198
|
+
* 129 bytes (spec v0.2) — `rootAccountId` AND `ssoEncPubKey` absent.
|
|
199
|
+
*
|
|
200
|
+
* Older peers degrade gracefully: chat continues to work via
|
|
201
|
+
* `identityChatPrivateKey`, but the SSO session transport (which needs
|
|
202
|
+
* `ssoEncPubKey` to derive `shared_secret_session`) stays inactive on
|
|
203
|
+
* the host until the peer upgrades.
|
|
172
204
|
*/
|
|
173
205
|
export declare const decodeEncryptedHandshakeResponseV2: (bytes: Uint8Array) => DecodedHandshakeResponseV2;
|
|
174
206
|
/**
|
|
@@ -229,6 +261,7 @@ export declare const EncryptedHandshakeResponseV2: import("scale-ts").Codec<{
|
|
|
229
261
|
identityAccountId: Uint8Array<ArrayBufferLike>;
|
|
230
262
|
rootAccountId: Uint8Array<ArrayBufferLike>;
|
|
231
263
|
identityChatPrivateKey: Uint8Array<ArrayBufferLike>;
|
|
264
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike>;
|
|
232
265
|
deviceEncPubKey: Uint8Array<ArrayBufferLike>;
|
|
233
266
|
};
|
|
234
267
|
}>;
|
|
@@ -61,8 +61,26 @@ export const VersionedHandshakeProposal = Enum({
|
|
|
61
61
|
V2: HandshakeProposalV2,
|
|
62
62
|
});
|
|
63
63
|
// ── Response (V2) ───────────────────────────────────────────────────────
|
|
64
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* 32 + 32 + 32 + 65 + 65 = 226 bytes (spec v0.2.2).
|
|
66
|
+
*
|
|
67
|
+
* `ssoEncPubKey` is `papp_encr_pub` per spec § Encrypted response — V2 — the
|
|
68
|
+
* P-256 public key PApp uses for SSO session ECDH. Required to compute
|
|
69
|
+
* `shared_secret_session = ECDH(host_encr_secret, ssoEncPubKey)`. PApp keypair
|
|
70
|
+
* derivation is implementation-defined: Android derives under `//wallet//sso`
|
|
71
|
+
* (`SsoDerivationDomains.SSO_DERIVATION_DOMAIN`); iOS currently reuses
|
|
72
|
+
* `//wallet//chat`. The host treats this field as opaque public material —
|
|
73
|
+
* which keypair PApp picked is invisible here.
|
|
74
|
+
*/
|
|
65
75
|
export const HandshakeSuccessV2 = Struct({
|
|
76
|
+
identityAccountId: AccountIdCodec,
|
|
77
|
+
rootAccountId: AccountIdCodec,
|
|
78
|
+
identityChatPrivateKey: PrivateKeyCodec,
|
|
79
|
+
ssoEncPubKey: PublicKeyCodec,
|
|
80
|
+
deviceEncPubKey: PublicKeyCodec,
|
|
81
|
+
});
|
|
82
|
+
/** 32 + 32 + 32 + 65 = 161 bytes (spec v0.2.1) */
|
|
83
|
+
export const HandshakeSuccessV2_v021 = Struct({
|
|
66
84
|
identityAccountId: AccountIdCodec,
|
|
67
85
|
rootAccountId: AccountIdCodec,
|
|
68
86
|
identityChatPrivateKey: PrivateKeyCodec,
|
|
@@ -76,9 +94,16 @@ export const HandshakeSuccessV2Legacy = Struct({
|
|
|
76
94
|
});
|
|
77
95
|
/**
|
|
78
96
|
* Length-dispatched decoder for the inner `EncryptedHandshakeResponseV2`
|
|
79
|
-
* plaintext.
|
|
80
|
-
*
|
|
81
|
-
*
|
|
97
|
+
* plaintext. Three Success body shapes are accepted, one per spec rev:
|
|
98
|
+
*
|
|
99
|
+
* 226 bytes (spec v0.2.2) — includes `ssoEncPubKey` (`papp_encr_pub`).
|
|
100
|
+
* 161 bytes (spec v0.2.1) — `ssoEncPubKey` absent; surfaced as `null`.
|
|
101
|
+
* 129 bytes (spec v0.2) — `rootAccountId` AND `ssoEncPubKey` absent.
|
|
102
|
+
*
|
|
103
|
+
* Older peers degrade gracefully: chat continues to work via
|
|
104
|
+
* `identityChatPrivateKey`, but the SSO session transport (which needs
|
|
105
|
+
* `ssoEncPubKey` to derive `shared_secret_session`) stays inactive on
|
|
106
|
+
* the host until the peer upgrades.
|
|
82
107
|
*/
|
|
83
108
|
export const decodeEncryptedHandshakeResponseV2 = (bytes) => {
|
|
84
109
|
if (bytes.length === 0)
|
|
@@ -92,7 +117,7 @@ export const decodeEncryptedHandshakeResponseV2 = (bytes) => {
|
|
|
92
117
|
return { tag: 'Pending', value: { tag: 'AllowanceAllocation', value: undefined } };
|
|
93
118
|
}
|
|
94
119
|
if (tag === 1) {
|
|
95
|
-
if (body.length ===
|
|
120
|
+
if (body.length === 226) {
|
|
96
121
|
const decoded = HandshakeSuccessV2.dec(body);
|
|
97
122
|
return {
|
|
98
123
|
tag: 'Success',
|
|
@@ -100,6 +125,20 @@ export const decodeEncryptedHandshakeResponseV2 = (bytes) => {
|
|
|
100
125
|
identityAccountId: decoded.identityAccountId,
|
|
101
126
|
rootAccountId: decoded.rootAccountId,
|
|
102
127
|
identityChatPrivateKey: decoded.identityChatPrivateKey,
|
|
128
|
+
ssoEncPubKey: decoded.ssoEncPubKey,
|
|
129
|
+
deviceEncPubKey: decoded.deviceEncPubKey,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (body.length === 161) {
|
|
134
|
+
const decoded = HandshakeSuccessV2_v021.dec(body);
|
|
135
|
+
return {
|
|
136
|
+
tag: 'Success',
|
|
137
|
+
value: {
|
|
138
|
+
identityAccountId: decoded.identityAccountId,
|
|
139
|
+
rootAccountId: decoded.rootAccountId,
|
|
140
|
+
identityChatPrivateKey: decoded.identityChatPrivateKey,
|
|
141
|
+
ssoEncPubKey: null,
|
|
103
142
|
deviceEncPubKey: decoded.deviceEncPubKey,
|
|
104
143
|
},
|
|
105
144
|
};
|
|
@@ -112,11 +151,12 @@ export const decodeEncryptedHandshakeResponseV2 = (bytes) => {
|
|
|
112
151
|
identityAccountId: decoded.identityAccountId,
|
|
113
152
|
rootAccountId: null,
|
|
114
153
|
identityChatPrivateKey: decoded.identityChatPrivateKey,
|
|
154
|
+
ssoEncPubKey: null,
|
|
115
155
|
deviceEncPubKey: decoded.deviceEncPubKey,
|
|
116
156
|
},
|
|
117
157
|
};
|
|
118
158
|
}
|
|
119
|
-
throw new Error(`EncryptedHandshakeResponseV2: Success body length ${body.length} not in {129, 161}`);
|
|
159
|
+
throw new Error(`EncryptedHandshakeResponseV2: Success body length ${body.length} not in {129, 161, 226}`);
|
|
120
160
|
}
|
|
121
161
|
if (tag === 2) {
|
|
122
162
|
return { tag: 'Failed', value: str.dec(body) };
|
|
@@ -54,6 +54,16 @@ export type HandshakeSuccessState = {
|
|
|
54
54
|
* back to the authorising device.
|
|
55
55
|
*/
|
|
56
56
|
deviceEncPubKey: Uint8Array;
|
|
57
|
+
/**
|
|
58
|
+
* `papp_encr_pub` from the Mobile SSO spec (v0.2.2 — 65 bytes, P-256
|
|
59
|
+
* uncompressed). The host's SSO session transport derives
|
|
60
|
+
* `shared_secret_session = ECDH(host_encr_secret, ssoEncPubKey)` from
|
|
61
|
+
* this. Nullable because v0.2 and v0.2.1 peers don't ship it; while
|
|
62
|
+
* null the host's SSO transport stays inactive (sign/vrf/etc continue
|
|
63
|
+
* to fail at the boundary) and chat keeps working through
|
|
64
|
+
* `identityChatPrivateKey`.
|
|
65
|
+
*/
|
|
66
|
+
ssoEncPubKey: Uint8Array | null;
|
|
57
67
|
/**
|
|
58
68
|
* The pairing-topic statement was signed by PApp's device statement
|
|
59
69
|
* account. `HandshakeSuccessV2` doesn't carry it in the encrypted body, so
|
|
@@ -35,6 +35,7 @@ export const fromInnerResponse = (response, peerStatementAccountId = null) => {
|
|
|
35
35
|
identityChatPrivateKey: response.value.identityChatPrivateKey,
|
|
36
36
|
identityChatPublicKey: deriveIdentityChatPublicKey(response.value.identityChatPrivateKey),
|
|
37
37
|
deviceEncPubKey: response.value.deviceEncPubKey,
|
|
38
|
+
ssoEncPubKey: response.value.ssoEncPubKey,
|
|
38
39
|
peerStatementAccountId,
|
|
39
40
|
};
|
|
40
41
|
case 'Failed':
|
|
@@ -79,6 +79,12 @@ export function createUserSession({ userSession, statementStore, encryption, sto
|
|
|
79
79
|
statementStore,
|
|
80
80
|
encryption,
|
|
81
81
|
prover,
|
|
82
|
+
// V1 sessions historically derived SessionId by feeding the peer's raw
|
|
83
|
+
// encryption pubkey into khash; preserve that behaviour here so existing
|
|
84
|
+
// V1 channels stay byte-identical post-refactor. V2 callers (e.g.
|
|
85
|
+
// polkadot-desktop's V2SsoSession) pass the ECDH-derived shared secret
|
|
86
|
+
// explicitly per Mobile SSO spec v0.2.2.
|
|
87
|
+
sessionKey: userSession.remoteAccount.publicKey,
|
|
82
88
|
maxRequestSize: MAX_SSO_REQUEST_SIZE,
|
|
83
89
|
});
|
|
84
90
|
const processedMessages = fieldListView({
|
|
@@ -17,10 +17,12 @@ declare const storedUserSessionCodec: import("scale-ts").Codec<{
|
|
|
17
17
|
rootAccountId: AccountId;
|
|
18
18
|
identityAccountId: AccountId | undefined;
|
|
19
19
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
20
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
20
21
|
}>;
|
|
21
22
|
type StoredUserSessionV2Extras = {
|
|
22
23
|
identityAccountId?: AccountId;
|
|
23
24
|
identityChatPublicKey?: Uint8Array;
|
|
25
|
+
ssoEncPubKey?: Uint8Array;
|
|
24
26
|
};
|
|
25
27
|
export declare function createStoredUserSession(localAccount: LocalSessionAccount, remoteAccount: RemoteSessionAccount, rootAccountId: AccountId, extras?: StoredUserSessionV2Extras): StoredUserSession;
|
|
26
28
|
export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
@@ -38,6 +40,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
38
40
|
rootAccountId: AccountId;
|
|
39
41
|
identityAccountId: AccountId | undefined;
|
|
40
42
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
43
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
41
44
|
}): import("neverthrow").ResultAsync<{
|
|
42
45
|
id: string;
|
|
43
46
|
localAccount: {
|
|
@@ -52,6 +55,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
52
55
|
rootAccountId: AccountId;
|
|
53
56
|
identityAccountId: AccountId | undefined;
|
|
54
57
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
58
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
55
59
|
}, Error>;
|
|
56
60
|
filter(fn: (value: {
|
|
57
61
|
id: string;
|
|
@@ -67,6 +71,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
67
71
|
rootAccountId: AccountId;
|
|
68
72
|
identityAccountId: AccountId | undefined;
|
|
69
73
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
74
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
70
75
|
}) => boolean): import("neverthrow").ResultAsync<{
|
|
71
76
|
id: string;
|
|
72
77
|
localAccount: {
|
|
@@ -81,6 +86,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
81
86
|
rootAccountId: AccountId;
|
|
82
87
|
identityAccountId: AccountId | undefined;
|
|
83
88
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
89
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
84
90
|
}[], Error>;
|
|
85
91
|
mutate(fn: (value: {
|
|
86
92
|
id: string;
|
|
@@ -96,6 +102,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
96
102
|
rootAccountId: AccountId;
|
|
97
103
|
identityAccountId: AccountId | undefined;
|
|
98
104
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
105
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
99
106
|
}[]) => {
|
|
100
107
|
id: string;
|
|
101
108
|
localAccount: {
|
|
@@ -110,6 +117,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
110
117
|
rootAccountId: AccountId;
|
|
111
118
|
identityAccountId: AccountId | undefined;
|
|
112
119
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
120
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
113
121
|
}[]): import("neverthrow").ResultAsync<{
|
|
114
122
|
id: string;
|
|
115
123
|
localAccount: {
|
|
@@ -124,6 +132,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
124
132
|
rootAccountId: AccountId;
|
|
125
133
|
identityAccountId: AccountId | undefined;
|
|
126
134
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
135
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
127
136
|
}[], Error>;
|
|
128
137
|
read(): import("neverthrow").ResultAsync<{
|
|
129
138
|
id: string;
|
|
@@ -139,6 +148,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
139
148
|
rootAccountId: AccountId;
|
|
140
149
|
identityAccountId: AccountId | undefined;
|
|
141
150
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
151
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
142
152
|
}[], Error>;
|
|
143
153
|
write(value: {
|
|
144
154
|
id: string;
|
|
@@ -154,6 +164,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
154
164
|
rootAccountId: AccountId;
|
|
155
165
|
identityAccountId: AccountId | undefined;
|
|
156
166
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
167
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
157
168
|
}[]): import("neverthrow").ResultAsync<null, Error> | import("neverthrow").ResultAsync<{
|
|
158
169
|
id: string;
|
|
159
170
|
localAccount: {
|
|
@@ -168,6 +179,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
168
179
|
rootAccountId: AccountId;
|
|
169
180
|
identityAccountId: AccountId | undefined;
|
|
170
181
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
182
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
171
183
|
}[], Error>;
|
|
172
184
|
clear(): import("neverthrow").ResultAsync<void, Error>;
|
|
173
185
|
subscribe(fn: (value: {
|
|
@@ -184,6 +196,7 @@ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
|
|
|
184
196
|
rootAccountId: AccountId;
|
|
185
197
|
identityAccountId: AccountId | undefined;
|
|
186
198
|
identityChatPublicKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
199
|
+
ssoEncPubKey: Uint8Array<ArrayBufferLike> | undefined;
|
|
187
200
|
}[]) => void): VoidFunction;
|
|
188
201
|
};
|
|
189
202
|
export {};
|
|
@@ -12,6 +12,11 @@ const storedUserSessionCodec = Struct({
|
|
|
12
12
|
rootAccountId: AccountIdCodec,
|
|
13
13
|
identityAccountId: Option(AccountIdCodec),
|
|
14
14
|
identityChatPublicKey: Option(Bytes(65)),
|
|
15
|
+
// `papp_encr_pub` (Mobile SSO spec v0.2.2, 65-byte uncompressed P-256).
|
|
16
|
+
// Persisted so the host can rebuild its SSO session transport
|
|
17
|
+
// (`shared_secret_session = ECDH(host_encr_secret, ssoEncPubKey)`) on a
|
|
18
|
+
// cold start without re-running the handshake. `None` for pre-v0.2.2 peers.
|
|
19
|
+
ssoEncPubKey: Option(Bytes(65)),
|
|
15
20
|
});
|
|
16
21
|
export function createStoredUserSession(localAccount, remoteAccount, rootAccountId, extras = {}) {
|
|
17
22
|
return {
|
|
@@ -21,6 +26,7 @@ export function createStoredUserSession(localAccount, remoteAccount, rootAccount
|
|
|
21
26
|
rootAccountId,
|
|
22
27
|
identityAccountId: extras.identityAccountId,
|
|
23
28
|
identityChatPublicKey: extras.identityChatPublicKey,
|
|
29
|
+
ssoEncPubKey: extras.ssoEncPubKey,
|
|
24
30
|
};
|
|
25
31
|
}
|
|
26
32
|
export const createUserSessionRepository = (storage) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novasamatech/host-papp",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.5",
|
|
5
5
|
"description": "Polkadot app integration",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"@noble/ciphers": "2.2.0",
|
|
35
35
|
"@noble/curves": "2.2.0",
|
|
36
36
|
"@noble/hashes": "2.2.0",
|
|
37
|
-
"@novasamatech/host-api": "0.8.
|
|
38
|
-
"@novasamatech/scale": "0.8.
|
|
39
|
-
"@novasamatech/statement-store": "0.8.
|
|
40
|
-
"@novasamatech/storage-adapter": "0.8.
|
|
37
|
+
"@novasamatech/host-api": "0.8.5",
|
|
38
|
+
"@novasamatech/scale": "0.8.5",
|
|
39
|
+
"@novasamatech/statement-store": "0.8.5",
|
|
40
|
+
"@novasamatech/storage-adapter": "0.8.5",
|
|
41
41
|
"@polkadot-api/utils": "^0.4.0",
|
|
42
42
|
"@polkadot-labs/hdkd-helpers": "^0.0.30",
|
|
43
43
|
"nanoevents": "9.1.0",
|