@astrox/auth-client 0.0.24 → 0.0.30
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/lib/cjs/index.d.ts +70 -0
- package/lib/cjs/index.js +225 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/esm/index.d.ts +70 -0
- package/lib/esm/index.js +220 -0
- package/lib/esm/index.js.map +1 -0
- package/lib/tsconfig-cjs.tsbuildinfo +2404 -0
- package/lib/tsconfig.tsbuildinfo +2403 -0
- package/package.json +6 -6
- package/types/buffer-pipe.d.ts +1 -1
@@ -0,0 +1,70 @@
|
|
1
|
+
import { Identity, SignIdentity } from '@astrox/agent';
|
2
|
+
import { DelegationChain } from '@astrox/identity';
|
3
|
+
/**
|
4
|
+
* List of options for creating an {@link AuthClient}.
|
5
|
+
*/
|
6
|
+
export interface AuthClientCreateOptions {
|
7
|
+
/**
|
8
|
+
* An identity to use as the base
|
9
|
+
*/
|
10
|
+
identity?: SignIdentity;
|
11
|
+
/**
|
12
|
+
* Optional storage with get, set, and remove. Uses LocalStorage by default
|
13
|
+
*/
|
14
|
+
storage?: AuthClientStorage;
|
15
|
+
}
|
16
|
+
export interface AuthClientLoginOptions {
|
17
|
+
/**
|
18
|
+
* Identity provider. By default, use the identity service.
|
19
|
+
*/
|
20
|
+
identityProvider?: string | URL;
|
21
|
+
/**
|
22
|
+
* Experiation of the authentication
|
23
|
+
*/
|
24
|
+
maxTimeToLive?: bigint;
|
25
|
+
/**
|
26
|
+
* Callback once login has completed
|
27
|
+
*/
|
28
|
+
onSuccess?: () => void;
|
29
|
+
/**
|
30
|
+
* Callback in case authentication fails
|
31
|
+
*/
|
32
|
+
onError?: (error?: string) => void;
|
33
|
+
}
|
34
|
+
/**
|
35
|
+
* Interface for persisting user authentication data
|
36
|
+
*/
|
37
|
+
export interface AuthClientStorage {
|
38
|
+
get(key: string): Promise<string | null>;
|
39
|
+
set(key: string, value: string): Promise<void>;
|
40
|
+
remove(key: string): Promise<void>;
|
41
|
+
}
|
42
|
+
export declare class LocalStorage implements AuthClientStorage {
|
43
|
+
readonly prefix: string;
|
44
|
+
private readonly _localStorage?;
|
45
|
+
constructor(prefix?: string, _localStorage?: Storage | undefined);
|
46
|
+
get(key: string): Promise<string | null>;
|
47
|
+
set(key: string, value: string): Promise<void>;
|
48
|
+
remove(key: string): Promise<void>;
|
49
|
+
private _getLocalStorage;
|
50
|
+
}
|
51
|
+
export declare class AuthClient {
|
52
|
+
private _identity;
|
53
|
+
private _key;
|
54
|
+
private _chain;
|
55
|
+
private _storage;
|
56
|
+
private _idpWindow?;
|
57
|
+
private _eventHandler?;
|
58
|
+
static create(options?: AuthClientCreateOptions): Promise<AuthClient>;
|
59
|
+
protected constructor(_identity: Identity, _key: SignIdentity | null, _chain: DelegationChain | null, _storage: AuthClientStorage, _idpWindow?: Window | undefined, _eventHandler?: ((event: MessageEvent) => void) | undefined);
|
60
|
+
private _handleSuccess;
|
61
|
+
getIdentity(): Identity;
|
62
|
+
isAuthenticated(): Promise<boolean>;
|
63
|
+
login(options?: AuthClientLoginOptions): Promise<void>;
|
64
|
+
private _getEventHandler;
|
65
|
+
private _handleFailure;
|
66
|
+
private _removeEventListener;
|
67
|
+
logout(options?: {
|
68
|
+
returnTo?: string;
|
69
|
+
}): Promise<void>;
|
70
|
+
}
|
package/lib/cjs/index.js
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.AuthClient = exports.LocalStorage = void 0;
|
4
|
+
const agent_1 = require("@astrox/agent");
|
5
|
+
const authentication_1 = require("@astrox/authentication");
|
6
|
+
const identity_1 = require("@astrox/identity");
|
7
|
+
const KEY_LOCALSTORAGE_KEY = 'identity';
|
8
|
+
const KEY_LOCALSTORAGE_DELEGATION = 'delegation';
|
9
|
+
const IDENTITY_PROVIDER_DEFAULT = 'https://identity.ic0.app';
|
10
|
+
const IDENTITY_PROVIDER_ENDPOINT = '#authorize';
|
11
|
+
async function _deleteStorage(storage) {
|
12
|
+
await storage.remove(KEY_LOCALSTORAGE_KEY);
|
13
|
+
await storage.remove(KEY_LOCALSTORAGE_DELEGATION);
|
14
|
+
}
|
15
|
+
class LocalStorage {
|
16
|
+
constructor(prefix = 'ic-', _localStorage) {
|
17
|
+
this.prefix = prefix;
|
18
|
+
this._localStorage = _localStorage;
|
19
|
+
}
|
20
|
+
get(key) {
|
21
|
+
return Promise.resolve(this._getLocalStorage().getItem(this.prefix + key));
|
22
|
+
}
|
23
|
+
set(key, value) {
|
24
|
+
this._getLocalStorage().setItem(this.prefix + key, value);
|
25
|
+
return Promise.resolve();
|
26
|
+
}
|
27
|
+
remove(key) {
|
28
|
+
this._getLocalStorage().removeItem(this.prefix + key);
|
29
|
+
return Promise.resolve();
|
30
|
+
}
|
31
|
+
_getLocalStorage() {
|
32
|
+
if (this._localStorage) {
|
33
|
+
return this._localStorage;
|
34
|
+
}
|
35
|
+
const ls = typeof window === 'undefined'
|
36
|
+
? typeof global === 'undefined'
|
37
|
+
? typeof self === 'undefined'
|
38
|
+
? undefined
|
39
|
+
: self.localStorage
|
40
|
+
: global.localStorage
|
41
|
+
: window.localStorage;
|
42
|
+
if (!ls) {
|
43
|
+
throw new Error('Could not find local storage.');
|
44
|
+
}
|
45
|
+
return ls;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
exports.LocalStorage = LocalStorage;
|
49
|
+
class AuthClient {
|
50
|
+
constructor(_identity, _key, _chain, _storage,
|
51
|
+
// A handle on the IdP window.
|
52
|
+
_idpWindow,
|
53
|
+
// The event handler for processing events from the IdP.
|
54
|
+
_eventHandler) {
|
55
|
+
this._identity = _identity;
|
56
|
+
this._key = _key;
|
57
|
+
this._chain = _chain;
|
58
|
+
this._storage = _storage;
|
59
|
+
this._idpWindow = _idpWindow;
|
60
|
+
this._eventHandler = _eventHandler;
|
61
|
+
}
|
62
|
+
static async create(options = {}) {
|
63
|
+
var _a;
|
64
|
+
const storage = (_a = options.storage) !== null && _a !== void 0 ? _a : new LocalStorage('ic-');
|
65
|
+
let key = null;
|
66
|
+
if (options.identity) {
|
67
|
+
key = options.identity;
|
68
|
+
}
|
69
|
+
else {
|
70
|
+
const maybeIdentityStorage = await storage.get(KEY_LOCALSTORAGE_KEY);
|
71
|
+
if (maybeIdentityStorage) {
|
72
|
+
try {
|
73
|
+
key = identity_1.Ed25519KeyIdentity.fromJSON(maybeIdentityStorage);
|
74
|
+
}
|
75
|
+
catch (e) {
|
76
|
+
// Ignore this, this means that the localStorage value isn't a valid Ed25519KeyIdentity
|
77
|
+
// serialization.
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
let identity = new agent_1.AnonymousIdentity();
|
82
|
+
let chain = null;
|
83
|
+
if (key) {
|
84
|
+
try {
|
85
|
+
const chainStorage = await storage.get(KEY_LOCALSTORAGE_DELEGATION);
|
86
|
+
if (chainStorage) {
|
87
|
+
chain = identity_1.DelegationChain.fromJSON(chainStorage);
|
88
|
+
// Verify that the delegation isn't expired.
|
89
|
+
if (!authentication_1.isDelegationValid(chain)) {
|
90
|
+
await _deleteStorage(storage);
|
91
|
+
key = null;
|
92
|
+
}
|
93
|
+
else {
|
94
|
+
identity = identity_1.DelegationIdentity.fromDelegation(key, chain);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
catch (e) {
|
99
|
+
console.error(e);
|
100
|
+
// If there was a problem loading the chain, delete the key.
|
101
|
+
await _deleteStorage(storage);
|
102
|
+
key = null;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
return new this(identity, key, chain, storage);
|
106
|
+
}
|
107
|
+
_handleSuccess(message, onSuccess) {
|
108
|
+
var _a;
|
109
|
+
const delegations = message.delegations.map(signedDelegation => {
|
110
|
+
return {
|
111
|
+
delegation: new identity_1.Delegation(signedDelegation.delegation.pubkey, signedDelegation.delegation.expiration, signedDelegation.delegation.targets),
|
112
|
+
signature: signedDelegation.signature.buffer,
|
113
|
+
};
|
114
|
+
});
|
115
|
+
const delegationChain = identity_1.DelegationChain.fromDelegations(delegations, message.userPublicKey.buffer);
|
116
|
+
const key = this._key;
|
117
|
+
if (!key) {
|
118
|
+
return;
|
119
|
+
}
|
120
|
+
this._chain = delegationChain;
|
121
|
+
this._identity = identity_1.DelegationIdentity.fromDelegation(key, this._chain);
|
122
|
+
(_a = this._idpWindow) === null || _a === void 0 ? void 0 : _a.close();
|
123
|
+
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess();
|
124
|
+
this._removeEventListener();
|
125
|
+
}
|
126
|
+
getIdentity() {
|
127
|
+
return this._identity;
|
128
|
+
}
|
129
|
+
async isAuthenticated() {
|
130
|
+
return !this.getIdentity().getPrincipal().isAnonymous() && this._chain !== null;
|
131
|
+
}
|
132
|
+
async login(options) {
|
133
|
+
var _a, _b, _c;
|
134
|
+
let key = this._key;
|
135
|
+
if (!key) {
|
136
|
+
// Create a new key (whether or not one was in storage).
|
137
|
+
key = identity_1.Ed25519KeyIdentity.generate();
|
138
|
+
this._key = key;
|
139
|
+
await this._storage.set(KEY_LOCALSTORAGE_KEY, JSON.stringify(key));
|
140
|
+
}
|
141
|
+
// Create the URL of the IDP. (e.g. https://XXXX/#authorize)
|
142
|
+
const identityProviderUrl = new URL(((_a = options === null || options === void 0 ? void 0 : options.identityProvider) === null || _a === void 0 ? void 0 : _a.toString()) || IDENTITY_PROVIDER_DEFAULT);
|
143
|
+
// Set the correct hash if it isn't already set.
|
144
|
+
identityProviderUrl.hash = IDENTITY_PROVIDER_ENDPOINT;
|
145
|
+
// If `login` has been called previously, then close/remove any previous windows
|
146
|
+
// and event listeners.
|
147
|
+
(_b = this._idpWindow) === null || _b === void 0 ? void 0 : _b.close();
|
148
|
+
this._removeEventListener();
|
149
|
+
// Add an event listener to handle responses.
|
150
|
+
this._eventHandler = this._getEventHandler(identityProviderUrl, options);
|
151
|
+
window.addEventListener('message', this._eventHandler);
|
152
|
+
// Open a new window with the IDP provider.
|
153
|
+
this._idpWindow = (_c = window.open(identityProviderUrl.toString(), 'idpWindow')) !== null && _c !== void 0 ? _c : undefined;
|
154
|
+
}
|
155
|
+
_getEventHandler(identityProviderUrl, options) {
|
156
|
+
return async (event) => {
|
157
|
+
var _a, _b;
|
158
|
+
if (event.origin !== identityProviderUrl.origin) {
|
159
|
+
return;
|
160
|
+
}
|
161
|
+
const message = event.data;
|
162
|
+
switch (message.kind) {
|
163
|
+
case 'authorize-ready': {
|
164
|
+
// IDP is ready. Send a message to request authorization.
|
165
|
+
const request = {
|
166
|
+
kind: 'authorize-client',
|
167
|
+
sessionPublicKey: new Uint8Array((_a = this._key) === null || _a === void 0 ? void 0 : _a.getPublicKey().toDer()),
|
168
|
+
maxTimeToLive: options === null || options === void 0 ? void 0 : options.maxTimeToLive,
|
169
|
+
};
|
170
|
+
(_b = this._idpWindow) === null || _b === void 0 ? void 0 : _b.postMessage(request, identityProviderUrl.origin);
|
171
|
+
break;
|
172
|
+
}
|
173
|
+
case 'authorize-client-success':
|
174
|
+
// Create the delegation chain and store it.
|
175
|
+
try {
|
176
|
+
this._handleSuccess(message, options === null || options === void 0 ? void 0 : options.onSuccess);
|
177
|
+
// Setting the storage is moved out of _handleSuccess to make
|
178
|
+
// it a sync function. Having _handleSuccess as an async function
|
179
|
+
// messes up the jest tests for some reason.
|
180
|
+
if (this._chain) {
|
181
|
+
await this._storage.set(KEY_LOCALSTORAGE_DELEGATION, JSON.stringify(this._chain.toJSON()));
|
182
|
+
}
|
183
|
+
}
|
184
|
+
catch (err) {
|
185
|
+
this._handleFailure(err.message, options === null || options === void 0 ? void 0 : options.onError);
|
186
|
+
}
|
187
|
+
break;
|
188
|
+
case 'authorize-client-failure':
|
189
|
+
this._handleFailure(message.text, options === null || options === void 0 ? void 0 : options.onError);
|
190
|
+
break;
|
191
|
+
default:
|
192
|
+
break;
|
193
|
+
}
|
194
|
+
};
|
195
|
+
}
|
196
|
+
_handleFailure(errorMessage, onError) {
|
197
|
+
var _a;
|
198
|
+
(_a = this._idpWindow) === null || _a === void 0 ? void 0 : _a.close();
|
199
|
+
onError === null || onError === void 0 ? void 0 : onError(errorMessage);
|
200
|
+
this._removeEventListener();
|
201
|
+
}
|
202
|
+
_removeEventListener() {
|
203
|
+
if (this._eventHandler) {
|
204
|
+
window.removeEventListener('message', this._eventHandler);
|
205
|
+
}
|
206
|
+
this._eventHandler = undefined;
|
207
|
+
}
|
208
|
+
async logout(options = {}) {
|
209
|
+
_deleteStorage(this._storage);
|
210
|
+
// Reset this auth client to a non-authenticated state.
|
211
|
+
this._identity = new agent_1.AnonymousIdentity();
|
212
|
+
this._key = null;
|
213
|
+
this._chain = null;
|
214
|
+
if (options.returnTo) {
|
215
|
+
try {
|
216
|
+
window.history.pushState({}, '', options.returnTo);
|
217
|
+
}
|
218
|
+
catch (e) {
|
219
|
+
window.location.href = options.returnTo;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
}
|
223
|
+
}
|
224
|
+
exports.AuthClient = AuthClient;
|
225
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,70 @@
|
|
1
|
+
import { Identity, SignIdentity } from '@astrox/agent';
|
2
|
+
import { DelegationChain } from '@astrox/identity';
|
3
|
+
/**
|
4
|
+
* List of options for creating an {@link AuthClient}.
|
5
|
+
*/
|
6
|
+
export interface AuthClientCreateOptions {
|
7
|
+
/**
|
8
|
+
* An identity to use as the base
|
9
|
+
*/
|
10
|
+
identity?: SignIdentity;
|
11
|
+
/**
|
12
|
+
* Optional storage with get, set, and remove. Uses LocalStorage by default
|
13
|
+
*/
|
14
|
+
storage?: AuthClientStorage;
|
15
|
+
}
|
16
|
+
export interface AuthClientLoginOptions {
|
17
|
+
/**
|
18
|
+
* Identity provider. By default, use the identity service.
|
19
|
+
*/
|
20
|
+
identityProvider?: string | URL;
|
21
|
+
/**
|
22
|
+
* Experiation of the authentication
|
23
|
+
*/
|
24
|
+
maxTimeToLive?: bigint;
|
25
|
+
/**
|
26
|
+
* Callback once login has completed
|
27
|
+
*/
|
28
|
+
onSuccess?: () => void;
|
29
|
+
/**
|
30
|
+
* Callback in case authentication fails
|
31
|
+
*/
|
32
|
+
onError?: (error?: string) => void;
|
33
|
+
}
|
34
|
+
/**
|
35
|
+
* Interface for persisting user authentication data
|
36
|
+
*/
|
37
|
+
export interface AuthClientStorage {
|
38
|
+
get(key: string): Promise<string | null>;
|
39
|
+
set(key: string, value: string): Promise<void>;
|
40
|
+
remove(key: string): Promise<void>;
|
41
|
+
}
|
42
|
+
export declare class LocalStorage implements AuthClientStorage {
|
43
|
+
readonly prefix: string;
|
44
|
+
private readonly _localStorage?;
|
45
|
+
constructor(prefix?: string, _localStorage?: Storage | undefined);
|
46
|
+
get(key: string): Promise<string | null>;
|
47
|
+
set(key: string, value: string): Promise<void>;
|
48
|
+
remove(key: string): Promise<void>;
|
49
|
+
private _getLocalStorage;
|
50
|
+
}
|
51
|
+
export declare class AuthClient {
|
52
|
+
private _identity;
|
53
|
+
private _key;
|
54
|
+
private _chain;
|
55
|
+
private _storage;
|
56
|
+
private _idpWindow?;
|
57
|
+
private _eventHandler?;
|
58
|
+
static create(options?: AuthClientCreateOptions): Promise<AuthClient>;
|
59
|
+
protected constructor(_identity: Identity, _key: SignIdentity | null, _chain: DelegationChain | null, _storage: AuthClientStorage, _idpWindow?: Window | undefined, _eventHandler?: ((event: MessageEvent) => void) | undefined);
|
60
|
+
private _handleSuccess;
|
61
|
+
getIdentity(): Identity;
|
62
|
+
isAuthenticated(): Promise<boolean>;
|
63
|
+
login(options?: AuthClientLoginOptions): Promise<void>;
|
64
|
+
private _getEventHandler;
|
65
|
+
private _handleFailure;
|
66
|
+
private _removeEventListener;
|
67
|
+
logout(options?: {
|
68
|
+
returnTo?: string;
|
69
|
+
}): Promise<void>;
|
70
|
+
}
|
package/lib/esm/index.js
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
import { AnonymousIdentity, } from '@astrox/agent';
|
2
|
+
import { isDelegationValid } from '@astrox/authentication';
|
3
|
+
import { Delegation, DelegationChain, DelegationIdentity, Ed25519KeyIdentity, } from '@astrox/identity';
|
4
|
+
const KEY_LOCALSTORAGE_KEY = 'identity';
|
5
|
+
const KEY_LOCALSTORAGE_DELEGATION = 'delegation';
|
6
|
+
const IDENTITY_PROVIDER_DEFAULT = 'https://identity.ic0.app';
|
7
|
+
const IDENTITY_PROVIDER_ENDPOINT = '#authorize';
|
8
|
+
async function _deleteStorage(storage) {
|
9
|
+
await storage.remove(KEY_LOCALSTORAGE_KEY);
|
10
|
+
await storage.remove(KEY_LOCALSTORAGE_DELEGATION);
|
11
|
+
}
|
12
|
+
export class LocalStorage {
|
13
|
+
constructor(prefix = 'ic-', _localStorage) {
|
14
|
+
this.prefix = prefix;
|
15
|
+
this._localStorage = _localStorage;
|
16
|
+
}
|
17
|
+
get(key) {
|
18
|
+
return Promise.resolve(this._getLocalStorage().getItem(this.prefix + key));
|
19
|
+
}
|
20
|
+
set(key, value) {
|
21
|
+
this._getLocalStorage().setItem(this.prefix + key, value);
|
22
|
+
return Promise.resolve();
|
23
|
+
}
|
24
|
+
remove(key) {
|
25
|
+
this._getLocalStorage().removeItem(this.prefix + key);
|
26
|
+
return Promise.resolve();
|
27
|
+
}
|
28
|
+
_getLocalStorage() {
|
29
|
+
if (this._localStorage) {
|
30
|
+
return this._localStorage;
|
31
|
+
}
|
32
|
+
const ls = typeof window === 'undefined'
|
33
|
+
? typeof global === 'undefined'
|
34
|
+
? typeof self === 'undefined'
|
35
|
+
? undefined
|
36
|
+
: self.localStorage
|
37
|
+
: global.localStorage
|
38
|
+
: window.localStorage;
|
39
|
+
if (!ls) {
|
40
|
+
throw new Error('Could not find local storage.');
|
41
|
+
}
|
42
|
+
return ls;
|
43
|
+
}
|
44
|
+
}
|
45
|
+
export class AuthClient {
|
46
|
+
constructor(_identity, _key, _chain, _storage,
|
47
|
+
// A handle on the IdP window.
|
48
|
+
_idpWindow,
|
49
|
+
// The event handler for processing events from the IdP.
|
50
|
+
_eventHandler) {
|
51
|
+
this._identity = _identity;
|
52
|
+
this._key = _key;
|
53
|
+
this._chain = _chain;
|
54
|
+
this._storage = _storage;
|
55
|
+
this._idpWindow = _idpWindow;
|
56
|
+
this._eventHandler = _eventHandler;
|
57
|
+
}
|
58
|
+
static async create(options = {}) {
|
59
|
+
var _a;
|
60
|
+
const storage = (_a = options.storage) !== null && _a !== void 0 ? _a : new LocalStorage('ic-');
|
61
|
+
let key = null;
|
62
|
+
if (options.identity) {
|
63
|
+
key = options.identity;
|
64
|
+
}
|
65
|
+
else {
|
66
|
+
const maybeIdentityStorage = await storage.get(KEY_LOCALSTORAGE_KEY);
|
67
|
+
if (maybeIdentityStorage) {
|
68
|
+
try {
|
69
|
+
key = Ed25519KeyIdentity.fromJSON(maybeIdentityStorage);
|
70
|
+
}
|
71
|
+
catch (e) {
|
72
|
+
// Ignore this, this means that the localStorage value isn't a valid Ed25519KeyIdentity
|
73
|
+
// serialization.
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
let identity = new AnonymousIdentity();
|
78
|
+
let chain = null;
|
79
|
+
if (key) {
|
80
|
+
try {
|
81
|
+
const chainStorage = await storage.get(KEY_LOCALSTORAGE_DELEGATION);
|
82
|
+
if (chainStorage) {
|
83
|
+
chain = DelegationChain.fromJSON(chainStorage);
|
84
|
+
// Verify that the delegation isn't expired.
|
85
|
+
if (!isDelegationValid(chain)) {
|
86
|
+
await _deleteStorage(storage);
|
87
|
+
key = null;
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
identity = DelegationIdentity.fromDelegation(key, chain);
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
catch (e) {
|
95
|
+
console.error(e);
|
96
|
+
// If there was a problem loading the chain, delete the key.
|
97
|
+
await _deleteStorage(storage);
|
98
|
+
key = null;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
return new this(identity, key, chain, storage);
|
102
|
+
}
|
103
|
+
_handleSuccess(message, onSuccess) {
|
104
|
+
var _a;
|
105
|
+
const delegations = message.delegations.map(signedDelegation => {
|
106
|
+
return {
|
107
|
+
delegation: new Delegation(signedDelegation.delegation.pubkey, signedDelegation.delegation.expiration, signedDelegation.delegation.targets),
|
108
|
+
signature: signedDelegation.signature.buffer,
|
109
|
+
};
|
110
|
+
});
|
111
|
+
const delegationChain = DelegationChain.fromDelegations(delegations, message.userPublicKey.buffer);
|
112
|
+
const key = this._key;
|
113
|
+
if (!key) {
|
114
|
+
return;
|
115
|
+
}
|
116
|
+
this._chain = delegationChain;
|
117
|
+
this._identity = DelegationIdentity.fromDelegation(key, this._chain);
|
118
|
+
(_a = this._idpWindow) === null || _a === void 0 ? void 0 : _a.close();
|
119
|
+
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess();
|
120
|
+
this._removeEventListener();
|
121
|
+
}
|
122
|
+
getIdentity() {
|
123
|
+
return this._identity;
|
124
|
+
}
|
125
|
+
async isAuthenticated() {
|
126
|
+
return !this.getIdentity().getPrincipal().isAnonymous() && this._chain !== null;
|
127
|
+
}
|
128
|
+
async login(options) {
|
129
|
+
var _a, _b, _c;
|
130
|
+
let key = this._key;
|
131
|
+
if (!key) {
|
132
|
+
// Create a new key (whether or not one was in storage).
|
133
|
+
key = Ed25519KeyIdentity.generate();
|
134
|
+
this._key = key;
|
135
|
+
await this._storage.set(KEY_LOCALSTORAGE_KEY, JSON.stringify(key));
|
136
|
+
}
|
137
|
+
// Create the URL of the IDP. (e.g. https://XXXX/#authorize)
|
138
|
+
const identityProviderUrl = new URL(((_a = options === null || options === void 0 ? void 0 : options.identityProvider) === null || _a === void 0 ? void 0 : _a.toString()) || IDENTITY_PROVIDER_DEFAULT);
|
139
|
+
// Set the correct hash if it isn't already set.
|
140
|
+
identityProviderUrl.hash = IDENTITY_PROVIDER_ENDPOINT;
|
141
|
+
// If `login` has been called previously, then close/remove any previous windows
|
142
|
+
// and event listeners.
|
143
|
+
(_b = this._idpWindow) === null || _b === void 0 ? void 0 : _b.close();
|
144
|
+
this._removeEventListener();
|
145
|
+
// Add an event listener to handle responses.
|
146
|
+
this._eventHandler = this._getEventHandler(identityProviderUrl, options);
|
147
|
+
window.addEventListener('message', this._eventHandler);
|
148
|
+
// Open a new window with the IDP provider.
|
149
|
+
this._idpWindow = (_c = window.open(identityProviderUrl.toString(), 'idpWindow')) !== null && _c !== void 0 ? _c : undefined;
|
150
|
+
}
|
151
|
+
_getEventHandler(identityProviderUrl, options) {
|
152
|
+
return async (event) => {
|
153
|
+
var _a, _b;
|
154
|
+
if (event.origin !== identityProviderUrl.origin) {
|
155
|
+
return;
|
156
|
+
}
|
157
|
+
const message = event.data;
|
158
|
+
switch (message.kind) {
|
159
|
+
case 'authorize-ready': {
|
160
|
+
// IDP is ready. Send a message to request authorization.
|
161
|
+
const request = {
|
162
|
+
kind: 'authorize-client',
|
163
|
+
sessionPublicKey: new Uint8Array((_a = this._key) === null || _a === void 0 ? void 0 : _a.getPublicKey().toDer()),
|
164
|
+
maxTimeToLive: options === null || options === void 0 ? void 0 : options.maxTimeToLive,
|
165
|
+
};
|
166
|
+
(_b = this._idpWindow) === null || _b === void 0 ? void 0 : _b.postMessage(request, identityProviderUrl.origin);
|
167
|
+
break;
|
168
|
+
}
|
169
|
+
case 'authorize-client-success':
|
170
|
+
// Create the delegation chain and store it.
|
171
|
+
try {
|
172
|
+
this._handleSuccess(message, options === null || options === void 0 ? void 0 : options.onSuccess);
|
173
|
+
// Setting the storage is moved out of _handleSuccess to make
|
174
|
+
// it a sync function. Having _handleSuccess as an async function
|
175
|
+
// messes up the jest tests for some reason.
|
176
|
+
if (this._chain) {
|
177
|
+
await this._storage.set(KEY_LOCALSTORAGE_DELEGATION, JSON.stringify(this._chain.toJSON()));
|
178
|
+
}
|
179
|
+
}
|
180
|
+
catch (err) {
|
181
|
+
this._handleFailure(err.message, options === null || options === void 0 ? void 0 : options.onError);
|
182
|
+
}
|
183
|
+
break;
|
184
|
+
case 'authorize-client-failure':
|
185
|
+
this._handleFailure(message.text, options === null || options === void 0 ? void 0 : options.onError);
|
186
|
+
break;
|
187
|
+
default:
|
188
|
+
break;
|
189
|
+
}
|
190
|
+
};
|
191
|
+
}
|
192
|
+
_handleFailure(errorMessage, onError) {
|
193
|
+
var _a;
|
194
|
+
(_a = this._idpWindow) === null || _a === void 0 ? void 0 : _a.close();
|
195
|
+
onError === null || onError === void 0 ? void 0 : onError(errorMessage);
|
196
|
+
this._removeEventListener();
|
197
|
+
}
|
198
|
+
_removeEventListener() {
|
199
|
+
if (this._eventHandler) {
|
200
|
+
window.removeEventListener('message', this._eventHandler);
|
201
|
+
}
|
202
|
+
this._eventHandler = undefined;
|
203
|
+
}
|
204
|
+
async logout(options = {}) {
|
205
|
+
_deleteStorage(this._storage);
|
206
|
+
// Reset this auth client to a non-authenticated state.
|
207
|
+
this._identity = new AnonymousIdentity();
|
208
|
+
this._key = null;
|
209
|
+
this._chain = null;
|
210
|
+
if (options.returnTo) {
|
211
|
+
try {
|
212
|
+
window.history.pushState({}, '', options.returnTo);
|
213
|
+
}
|
214
|
+
catch (e) {
|
215
|
+
window.location.href = options.returnTo;
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
}
|
220
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|