@oauth2-cli/qui-cli 0.7.16 → 1.0.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.
- package/CHANGELOG.md +21 -19
- package/README.md +33 -4
- package/dist/Client.d.ts +13 -0
- package/dist/Client.js +34 -8
- package/dist/OAuth2.d.ts +40 -0
- package/dist/OAuth2.js +41 -0
- package/dist/OAuth2Plugin.d.ts +96 -14
- package/dist/OAuth2Plugin.js +116 -42
- package/dist/Token/EnvironmentStorage.d.ts +14 -0
- package/dist/Token/EnvironmentStorage.js +14 -0
- package/dist/{Unregistered.d.ts → extendable.d.ts} +1 -1
- package/dist/{Unregistered.js → extendable.js} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/extendable/Client.d.ts +24 -0
- package/extendable/Client.js +71 -0
- package/extendable/OAuth2Plugin.d.ts +154 -0
- package/extendable/OAuth2Plugin.js +288 -0
- package/extendable/Token/EnvironmentStorage.d.ts +21 -0
- package/extendable/Token/EnvironmentStorage.js +27 -0
- package/extendable/Token/index.d.ts +2 -0
- package/extendable/Token/index.js +2 -0
- package/extendable/extendable.d.ts +4 -0
- package/extendable/extendable.js +4 -0
- package/extendable/index.d.ts +1 -0
- package/extendable/index.js +1 -0
- package/extendable/package.json +5 -0
- package/package.extendable.json +5 -0
- package/package.json +11 -6
- package/tsconfig.extendable.json +10 -0
package/dist/OAuth2Plugin.js
CHANGED
|
@@ -3,12 +3,13 @@ import { Env } from '@qui-cli/env';
|
|
|
3
3
|
import { Log } from '@qui-cli/log';
|
|
4
4
|
import * as Plugin from '@qui-cli/plugin';
|
|
5
5
|
import * as OAuth2CLI from 'oauth2-cli';
|
|
6
|
-
import
|
|
6
|
+
import { URL } from 'requestish';
|
|
7
7
|
export class OAuth2Plugin {
|
|
8
8
|
name;
|
|
9
9
|
static names = [];
|
|
10
10
|
static registeredPorts = {};
|
|
11
11
|
overrideName;
|
|
12
|
+
reason;
|
|
12
13
|
/**
|
|
13
14
|
* @param name Human-readable name for client in messages. Must also be a
|
|
14
15
|
* unique qui-cli plugin name.
|
|
@@ -19,15 +20,21 @@ export class OAuth2Plugin {
|
|
|
19
20
|
throw new Error(`A @qui-cli/plugin named ${Colors.value(name)} has already been instantiated.`);
|
|
20
21
|
}
|
|
21
22
|
}
|
|
23
|
+
/** Configured client credentials */
|
|
22
24
|
credentials;
|
|
25
|
+
/** Configured client base_url */
|
|
23
26
|
base_url;
|
|
27
|
+
/** Configured usage information */
|
|
24
28
|
man = {
|
|
25
29
|
heading: 'OAuth 2.0 / Open ID Connect client options'
|
|
26
30
|
};
|
|
31
|
+
/** Configured reference URLs for credentials */
|
|
27
32
|
url = undefined;
|
|
33
|
+
/** Configured hint values for credentials */
|
|
28
34
|
hint = {
|
|
29
35
|
redirect_uri: Colors.quotedValue(`"http://localhost:3000/redirect"`)
|
|
30
36
|
};
|
|
37
|
+
/** Configured environment variable names for credentials */
|
|
31
38
|
env = {
|
|
32
39
|
issuer: 'ISSUER',
|
|
33
40
|
client_id: 'CLIENT_ID',
|
|
@@ -38,13 +45,76 @@ export class OAuth2Plugin {
|
|
|
38
45
|
base_url: 'BASE_URL',
|
|
39
46
|
scope: 'SCOPE'
|
|
40
47
|
};
|
|
48
|
+
/** Configured credentials to suppress in usage and init */
|
|
41
49
|
suppress = {
|
|
42
50
|
scope: true
|
|
43
51
|
};
|
|
52
|
+
/** Configured request components for client to inject */
|
|
44
53
|
inject = undefined;
|
|
45
|
-
|
|
54
|
+
/** Configured {@link OAuth2CLI.Localhost.Options} to pass to client */
|
|
55
|
+
localhost;
|
|
56
|
+
/** Configured client refresh token storage strategy */
|
|
46
57
|
storage = undefined;
|
|
47
58
|
_client = undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Configured oauth2-cli client
|
|
61
|
+
*
|
|
62
|
+
* Do _not_ access until intitialization is complete -- the client will be
|
|
63
|
+
* configured upon first access based on available configuration known at that
|
|
64
|
+
* time
|
|
65
|
+
*/
|
|
66
|
+
get client() {
|
|
67
|
+
if (!this._client) {
|
|
68
|
+
if (!this.credentials?.client_id) {
|
|
69
|
+
throw new Error(`A ${Colors.varName(this.env.client_id)} ${Colors.keyword('must')} ` +
|
|
70
|
+
`be configured for ${this.overrideName || this.name}.`);
|
|
71
|
+
}
|
|
72
|
+
if (!this.credentials?.client_secret) {
|
|
73
|
+
throw new Error(`A ${Colors.varName(this.env.client_secret)} ${Colors.keyword('must')} ` +
|
|
74
|
+
`be configured for ${this.overrideName || this.name}.`);
|
|
75
|
+
}
|
|
76
|
+
if (!this.credentials?.redirect_uri) {
|
|
77
|
+
throw new Error(`A ${Colors.varName(this.env.redirect_uri)} ${Colors.keyword('must')} ` +
|
|
78
|
+
`be configured for ${this.overrideName || this.name}.`);
|
|
79
|
+
}
|
|
80
|
+
if (!this.credentials?.issuer) {
|
|
81
|
+
if (!this.credentials?.authorization_endpoint) {
|
|
82
|
+
throw new Error(`Either an ${Colors.varName(this.env.issuer)} or ` +
|
|
83
|
+
`${Colors.varName(this.env.authorization_endpoint)} ` +
|
|
84
|
+
`${Colors.keyword('must')} be configured for ` +
|
|
85
|
+
`${this.overrideName || this.name}.`);
|
|
86
|
+
}
|
|
87
|
+
if (!this.credentials?.token_endpoint) {
|
|
88
|
+
throw new Error(`Either an ${Colors.varName(this.env.issuer)} or ` +
|
|
89
|
+
`${Colors.varName(this.env.token_endpoint)} ` +
|
|
90
|
+
`${Colors.keyword('must')} be configured for ` +
|
|
91
|
+
`${this.overrideName || this.name}.`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
this._client = this.instantiateClient({
|
|
95
|
+
name: this.overrideName || this.name,
|
|
96
|
+
reason: this.reason,
|
|
97
|
+
credentials: this.credentials,
|
|
98
|
+
base_url: this.base_url,
|
|
99
|
+
inject: this.inject,
|
|
100
|
+
localhost: this.localhost,
|
|
101
|
+
storage: this.storage
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
return this._client;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Configure plugin for use
|
|
108
|
+
*
|
|
109
|
+
* May be called repeatedly, overlaying different options as they become
|
|
110
|
+
* available
|
|
111
|
+
*
|
|
112
|
+
* Invoked automatically by
|
|
113
|
+
* {@link https://github.com/battis/qui-cli#readme qui-cli} during
|
|
114
|
+
* initialization
|
|
115
|
+
*
|
|
116
|
+
* @see {@link Configuration}
|
|
117
|
+
*/
|
|
48
118
|
configure(proposal = {}) {
|
|
49
119
|
function hydrate(p, c) {
|
|
50
120
|
if (p) {
|
|
@@ -60,6 +130,7 @@ export class OAuth2Plugin {
|
|
|
60
130
|
return c;
|
|
61
131
|
}
|
|
62
132
|
this.overrideName = Plugin.hydrate(proposal.name, this.overrideName);
|
|
133
|
+
this.reason = Plugin.hydrate(proposal.reason, this.reason);
|
|
63
134
|
this.credentials = hydrate(proposal.credentials, this.credentials);
|
|
64
135
|
this.base_url = Plugin.hydrate(proposal.base_url, this.base_url);
|
|
65
136
|
this.storage = Plugin.hydrate(proposal.storage, this.storage);
|
|
@@ -69,8 +140,9 @@ export class OAuth2Plugin {
|
|
|
69
140
|
this.hint = hydrate(proposal.hint, this.hint);
|
|
70
141
|
this.env = hydrate(proposal.env, this.env);
|
|
71
142
|
this.suppress = hydrate(proposal.suppress, this.suppress);
|
|
143
|
+
this.localhost = hydrate(proposal.localhost, this.localhost);
|
|
72
144
|
if (this.credentials?.redirect_uri) {
|
|
73
|
-
const url =
|
|
145
|
+
const url = URL.from(this.credentials.redirect_uri);
|
|
74
146
|
if (url.hostname !== 'localhost' &&
|
|
75
147
|
!/^\/https?\/localhost(:\d+)?\//.test(url.pathname)) {
|
|
76
148
|
Log.warning(`The ${Colors.varName(this.env.redirect_uri)} value ${Colors.url(this.credentials.redirect_uri)} for ${this.overrideName || this.name} may not work: it ` +
|
|
@@ -93,6 +165,15 @@ export class OAuth2Plugin {
|
|
|
93
165
|
}
|
|
94
166
|
}
|
|
95
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Provide usage options to
|
|
170
|
+
* {@link https://github.com/battis/qui-cli#readme qui-cli} for display to user
|
|
171
|
+
* on command line
|
|
172
|
+
*
|
|
173
|
+
* Invoked automatically by
|
|
174
|
+
* {@link https://github.com/battis/qui-cli#readme qui-cli} during
|
|
175
|
+
* initialization
|
|
176
|
+
*/
|
|
96
177
|
options() {
|
|
97
178
|
const descriptions = {
|
|
98
179
|
issuer: `The OpenID ${Colors.keyword('issuer')} URL is set from the ` +
|
|
@@ -140,6 +221,13 @@ export class OAuth2Plugin {
|
|
|
140
221
|
]
|
|
141
222
|
};
|
|
142
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Intialize plugin configuration from command line options and environment
|
|
226
|
+
*
|
|
227
|
+
* Invoked automatically by
|
|
228
|
+
* {@link https://github.com/battis/qui-cli#readme qui-cli} during
|
|
229
|
+
* initialization
|
|
230
|
+
*/
|
|
143
231
|
async init(_) {
|
|
144
232
|
const credentials = {};
|
|
145
233
|
const base_url = this.base_url ||
|
|
@@ -157,57 +245,43 @@ export class OAuth2Plugin {
|
|
|
157
245
|
}
|
|
158
246
|
this.configure({ credentials, base_url });
|
|
159
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Instantiate the `oauth2-cli` client
|
|
250
|
+
*
|
|
251
|
+
* Available hook for custom configurations in plugin development
|
|
252
|
+
*/
|
|
160
253
|
instantiateClient(options) {
|
|
161
254
|
return new OAuth2CLI.Client(options);
|
|
162
255
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
if (!this.credentials?.client_secret) {
|
|
170
|
-
throw new Error(`A ${Colors.varName(this.env.client_secret)} ${Colors.keyword('must')} ` +
|
|
171
|
-
`be configured for ${this.overrideName || this.name}.`);
|
|
172
|
-
}
|
|
173
|
-
if (!this.credentials?.redirect_uri) {
|
|
174
|
-
throw new Error(`A ${Colors.varName(this.env.redirect_uri)} ${Colors.keyword('must')} ` +
|
|
175
|
-
`be configured for ${this.overrideName || this.name}.`);
|
|
176
|
-
}
|
|
177
|
-
if (!this.credentials?.issuer) {
|
|
178
|
-
if (!this.credentials?.authorization_endpoint) {
|
|
179
|
-
throw new Error(`Either an ${Colors.varName(this.env.issuer)} or ` +
|
|
180
|
-
`${Colors.varName(this.env.authorization_endpoint)} ` +
|
|
181
|
-
`${Colors.keyword('must')} be configured for ` +
|
|
182
|
-
`${this.overrideName || this.name}.`);
|
|
183
|
-
}
|
|
184
|
-
if (!this.credentials?.token_endpoint) {
|
|
185
|
-
throw new Error(`Either an ${Colors.varName(this.env.issuer)} or ` +
|
|
186
|
-
`${Colors.varName(this.env.token_endpoint)} ` +
|
|
187
|
-
`${Colors.keyword('must')} be configured for ` +
|
|
188
|
-
`${this.overrideName || this.name}.`);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
this._client = this.instantiateClient({
|
|
192
|
-
name: this.overrideName || this.name,
|
|
193
|
-
credentials: this.credentials,
|
|
194
|
-
base_url: this.base_url,
|
|
195
|
-
inject: this.inject,
|
|
196
|
-
views: this.views,
|
|
197
|
-
storage: this.storage
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
return this._client;
|
|
201
|
-
}
|
|
256
|
+
/**
|
|
257
|
+
* Convenience method
|
|
258
|
+
*
|
|
259
|
+
* @see {@link OAuth2CLI.Client.request}
|
|
260
|
+
*/
|
|
202
261
|
request(...args) {
|
|
203
262
|
return this.client.request(...args);
|
|
204
263
|
}
|
|
264
|
+
/**
|
|
265
|
+
* Convenience method
|
|
266
|
+
*
|
|
267
|
+
* @see {@link OAuth2CLI.Client.requestJSON}
|
|
268
|
+
*/
|
|
205
269
|
requestJSON(...args) {
|
|
206
270
|
return this.client.requestJSON(...args);
|
|
207
271
|
}
|
|
272
|
+
/**
|
|
273
|
+
* Convenience method
|
|
274
|
+
*
|
|
275
|
+
* @see {@link OAuth2CLI.Client.fetch}
|
|
276
|
+
*/
|
|
208
277
|
fetch(...args) {
|
|
209
278
|
return this.client.fetch(...args);
|
|
210
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* Convenience method
|
|
282
|
+
*
|
|
283
|
+
* @see {@link OAuth2CLI.Client.fetchJSON}
|
|
284
|
+
*/
|
|
211
285
|
fetchJSON(...args) {
|
|
212
286
|
return this.client.fetchJSON(...args);
|
|
213
287
|
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { Token } from 'oauth2-cli';
|
|
2
|
+
/**
|
|
3
|
+
* Persist a refresh token in the local environment
|
|
4
|
+
*
|
|
5
|
+
* Care should be taken when using this persistence strategy to:
|
|
6
|
+
*
|
|
7
|
+
* 1. Ideally encrypt or otherwise secure the environment value (see
|
|
8
|
+
* {@link https://github.com/battis/oauth2-cli/tree/main/examples/qui-cli/04%201password-integration#readme 1password-integration}
|
|
9
|
+
* example for one approach)
|
|
10
|
+
* 2. Do not commit `.env` files to a public repo
|
|
11
|
+
*/
|
|
2
12
|
export declare class EnvironmentStorage implements Token.Storage {
|
|
3
13
|
private tokenEnvVar;
|
|
14
|
+
/**
|
|
15
|
+
* @param tokenEnvVar Name of the environment variable containing the refresh
|
|
16
|
+
* token, defaults to `REFRESH_TOKEN`
|
|
17
|
+
*/
|
|
4
18
|
constructor(tokenEnvVar?: string);
|
|
5
19
|
load(): Promise<string | undefined>;
|
|
6
20
|
save(refresh_token: string): Promise<void>;
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { Env } from '@qui-cli/env';
|
|
2
|
+
/**
|
|
3
|
+
* Persist a refresh token in the local environment
|
|
4
|
+
*
|
|
5
|
+
* Care should be taken when using this persistence strategy to:
|
|
6
|
+
*
|
|
7
|
+
* 1. Ideally encrypt or otherwise secure the environment value (see
|
|
8
|
+
* {@link https://github.com/battis/oauth2-cli/tree/main/examples/qui-cli/04%201password-integration#readme 1password-integration}
|
|
9
|
+
* example for one approach)
|
|
10
|
+
* 2. Do not commit `.env` files to a public repo
|
|
11
|
+
*/
|
|
2
12
|
export class EnvironmentStorage {
|
|
3
13
|
tokenEnvVar;
|
|
14
|
+
/**
|
|
15
|
+
* @param tokenEnvVar Name of the environment variable containing the refresh
|
|
16
|
+
* token, defaults to `REFRESH_TOKEN`
|
|
17
|
+
*/
|
|
4
18
|
constructor(tokenEnvVar = 'REFRESH_TOKEN') {
|
|
5
19
|
this.tokenEnvVar = tokenEnvVar;
|
|
6
20
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { Credentials, Injection, Localhost, Options } from 'oauth2-cli';
|
|
2
2
|
export * from './Client.js';
|
|
3
3
|
export * from './OAuth2Plugin.js';
|
|
4
4
|
export * as Token from './Token/index.js';
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { JSONValue } from '@battis/typescript-tricks';
|
|
2
|
+
import { Request } from 'express';
|
|
3
|
+
import * as OAuth2CLI from 'oauth2-cli';
|
|
4
|
+
import type * as OpenIDClient from 'openid-client';
|
|
5
|
+
import * as requestish from 'requestish';
|
|
6
|
+
/**
|
|
7
|
+
* Wrap {@link https://www.npmjs.com/package/openid-client openid-client} in a
|
|
8
|
+
* class instance specific to a particular OAuth/OpenID server credential-set,
|
|
9
|
+
* abstracting away most flows into {@link getToken}
|
|
10
|
+
*
|
|
11
|
+
* Emits {@link Client.TokenEvent} whenever a new access token is received
|
|
12
|
+
*
|
|
13
|
+
* Provides optional debug logging output using
|
|
14
|
+
* {@link https://www.npmjs.com/package/@qui-cli/env @qui-cli/env}
|
|
15
|
+
*/
|
|
16
|
+
export declare class Client<C extends OAuth2CLI.Credentials = OAuth2CLI.Credentials> extends OAuth2CLI.Client<C> {
|
|
17
|
+
getConfiguration(): Promise<OpenIDClient.Configuration>;
|
|
18
|
+
authorize(): Promise<OAuth2CLI.Token.Response>;
|
|
19
|
+
handleAuthorizationCodeRedirect(request: Request, session: OAuth2CLI.Localhost.Server): Promise<OAuth2CLI.Token.Response>;
|
|
20
|
+
protected refreshTokenGrant(token: OAuth2CLI.Token.Response): Promise<OAuth2CLI.Token.Response | undefined>;
|
|
21
|
+
protected save(response: OAuth2CLI.Token.Response): Promise<OAuth2CLI.Token.Response>;
|
|
22
|
+
request(url: requestish.URL.ish, method?: string, body?: OpenIDClient.FetchBody, headers?: requestish.Headers.ish, dPoPOptions?: OpenIDClient.DPoPOptions): Promise<Response>;
|
|
23
|
+
requestJSON<J extends JSONValue = JSONValue>(url: requestish.URL.ish, method?: string, body?: OpenIDClient.FetchBody, headers?: requestish.Headers.ish, dPoPOptions?: OpenIDClient.DPoPOptions): Promise<J>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Log } from '@qui-cli/log';
|
|
2
|
+
import * as OAuth2CLI from 'oauth2-cli';
|
|
3
|
+
/**
|
|
4
|
+
* Wrap {@link https://www.npmjs.com/package/openid-client openid-client} in a
|
|
5
|
+
* class instance specific to a particular OAuth/OpenID server credential-set,
|
|
6
|
+
* abstracting away most flows into {@link getToken}
|
|
7
|
+
*
|
|
8
|
+
* Emits {@link Client.TokenEvent} whenever a new access token is received
|
|
9
|
+
*
|
|
10
|
+
* Provides optional debug logging output using
|
|
11
|
+
* {@link https://www.npmjs.com/package/@qui-cli/env @qui-cli/env}
|
|
12
|
+
*/
|
|
13
|
+
export class Client extends OAuth2CLI.Client {
|
|
14
|
+
async getConfiguration() {
|
|
15
|
+
const creating = !this.config;
|
|
16
|
+
const config = await super.getConfiguration();
|
|
17
|
+
if (creating) {
|
|
18
|
+
Log.debug(`${this.name} OAuth 2.0 configuration created`, {
|
|
19
|
+
credentials: this.credentials,
|
|
20
|
+
config: {
|
|
21
|
+
serverMetadata: config.serverMetadata(),
|
|
22
|
+
clientMetadata: config.clientMetadata()
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return config;
|
|
27
|
+
}
|
|
28
|
+
async authorize() {
|
|
29
|
+
Log.debug(`Authorizing ${this.name} new access token`);
|
|
30
|
+
const response = await super.authorize();
|
|
31
|
+
Log.debug(`Authorized ${this.name} new access token`, { response });
|
|
32
|
+
return response;
|
|
33
|
+
}
|
|
34
|
+
async handleAuthorizationCodeRedirect(request, session) {
|
|
35
|
+
Log.debug(`Handling ${this.name} authorization code redirect`, { request });
|
|
36
|
+
const response = await super.handleAuthorizationCodeRedirect(request, session);
|
|
37
|
+
Log.debug(`Received ${this.name} authorization code response`, {
|
|
38
|
+
response
|
|
39
|
+
});
|
|
40
|
+
return response;
|
|
41
|
+
}
|
|
42
|
+
async refreshTokenGrant(token) {
|
|
43
|
+
Log.debug(`Refreshing expired ${this.name} access token`, {
|
|
44
|
+
token
|
|
45
|
+
});
|
|
46
|
+
const refreshed = await super.refreshTokenGrant(token);
|
|
47
|
+
Log.debug(`Received refreshed ${this.name} access token`, {
|
|
48
|
+
token: refreshed
|
|
49
|
+
});
|
|
50
|
+
return refreshed;
|
|
51
|
+
}
|
|
52
|
+
async save(response) {
|
|
53
|
+
Log.debug(`Persisting ${this.name} refresh token, if present and storage configured`, {
|
|
54
|
+
response
|
|
55
|
+
});
|
|
56
|
+
return await super.save(response);
|
|
57
|
+
}
|
|
58
|
+
async request(url, method, body, headers, dPoPOptions) {
|
|
59
|
+
Log.debug(`Sending request to ${this.name}`, {
|
|
60
|
+
request: { method, url, headers, body, dPoPOptions }
|
|
61
|
+
});
|
|
62
|
+
const response = await super.request(url, method, body, headers, dPoPOptions);
|
|
63
|
+
Log.debug(`Received response from ${this.name}`, { response });
|
|
64
|
+
return response;
|
|
65
|
+
}
|
|
66
|
+
async requestJSON(url, method, body, headers, dPoPOptions) {
|
|
67
|
+
const json = await super.requestJSON(url, method, body, headers, dPoPOptions);
|
|
68
|
+
Log.debug(`Parsed JSON from ${this.name} response`, { json });
|
|
69
|
+
return json;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { URLString } from '@battis/descriptive-types';
|
|
2
|
+
import { JSONValue } from '@battis/typescript-tricks';
|
|
3
|
+
import * as Plugin from '@qui-cli/plugin';
|
|
4
|
+
import * as OAuth2CLI from 'oauth2-cli';
|
|
5
|
+
import { URL } from 'requestish';
|
|
6
|
+
import { Client } from './Client.js';
|
|
7
|
+
/** Key for value to be read from the local environment */
|
|
8
|
+
type EnvironmentKey = 'issuer' | 'client_id' | 'client_secret' | 'redirect_uri' | 'authorization_endpoint' | 'token_endpoint' | 'scope' | 'base_url';
|
|
9
|
+
/** Names of environment variables */
|
|
10
|
+
type EnvironmentVars = Record<EnvironmentKey, string>;
|
|
11
|
+
/** Reference URLs for environment variables */
|
|
12
|
+
type SupportUrls = Record<EnvironmentKey, URLString>;
|
|
13
|
+
/** Hint values for environment variables */
|
|
14
|
+
type Hints = Record<EnvironmentKey, string>;
|
|
15
|
+
/** Environment variables to ignore and supporess in usage documentation */
|
|
16
|
+
type EnvVarSuppression = Record<EnvironmentKey, boolean>;
|
|
17
|
+
/** Custom usage information to present to user */
|
|
18
|
+
type Usage = {
|
|
19
|
+
heading: string;
|
|
20
|
+
text?: string[];
|
|
21
|
+
};
|
|
22
|
+
/** Plugin configuration */
|
|
23
|
+
export type Configuration<C extends OAuth2CLI.Credentials = OAuth2CLI.Credentials> = Plugin.Configuration & {
|
|
24
|
+
/** Human-readable name for client in messages (e.g. the name of the API) */
|
|
25
|
+
name?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Human-readable for authorizing access in messages (e.g. the name of the
|
|
28
|
+
* app)
|
|
29
|
+
*/
|
|
30
|
+
reason?: string;
|
|
31
|
+
/** OAuth 2.0/OpenID Connect credential set */
|
|
32
|
+
credentials?: Partial<C>;
|
|
33
|
+
/** Base URL for all non-absolute requests */
|
|
34
|
+
base_url?: URL.ish;
|
|
35
|
+
/** Request components to inject into server requests */
|
|
36
|
+
inject?: OAuth2CLI.Injection;
|
|
37
|
+
/** Refresh token storage service */
|
|
38
|
+
storage?: OAuth2CLI.Token.Storage;
|
|
39
|
+
/** CLI usage section header and text */
|
|
40
|
+
man?: Usage;
|
|
41
|
+
/** Reference URLs for particular credential values */
|
|
42
|
+
url?: Partial<SupportUrls>;
|
|
43
|
+
/** Hint values for particular credential values */
|
|
44
|
+
hint?: Partial<Hints>;
|
|
45
|
+
/** Actual environment variable names for each credential value */
|
|
46
|
+
env?: Partial<EnvironmentVars>;
|
|
47
|
+
/** Should a particular credential value _not_ be loaded from the environment? */
|
|
48
|
+
suppress?: Partial<EnvVarSuppression>;
|
|
49
|
+
localhost?: OAuth2CLI.Options['localhost'];
|
|
50
|
+
};
|
|
51
|
+
export declare class OAuth2Plugin<C extends OAuth2CLI.Credentials = OAuth2CLI.Credentials, L extends Client<C> = Client<C>> {
|
|
52
|
+
readonly name: string;
|
|
53
|
+
[key: string]: unknown;
|
|
54
|
+
private static names;
|
|
55
|
+
private static registeredPorts;
|
|
56
|
+
private overrideName?;
|
|
57
|
+
private reason?;
|
|
58
|
+
/**
|
|
59
|
+
* @param name Human-readable name for client in messages. Must also be a
|
|
60
|
+
* unique qui-cli plugin name.
|
|
61
|
+
*/
|
|
62
|
+
constructor(name?: string);
|
|
63
|
+
/** Configured client credentials */
|
|
64
|
+
private credentials?;
|
|
65
|
+
/** Configured client base_url */
|
|
66
|
+
private base_url?;
|
|
67
|
+
/** Configured usage information */
|
|
68
|
+
private man;
|
|
69
|
+
/** Configured reference URLs for credentials */
|
|
70
|
+
private url?;
|
|
71
|
+
/** Configured hint values for credentials */
|
|
72
|
+
private hint;
|
|
73
|
+
/** Configured environment variable names for credentials */
|
|
74
|
+
private env;
|
|
75
|
+
/** Configured credentials to suppress in usage and init */
|
|
76
|
+
private suppress?;
|
|
77
|
+
/** Configured request components for client to inject */
|
|
78
|
+
private inject?;
|
|
79
|
+
/** Configured {@link OAuth2CLI.Localhost.Options} to pass to client */
|
|
80
|
+
private localhost?;
|
|
81
|
+
/** Configured client refresh token storage strategy */
|
|
82
|
+
private storage?;
|
|
83
|
+
private _client?;
|
|
84
|
+
/**
|
|
85
|
+
* Configured oauth2-cli client
|
|
86
|
+
*
|
|
87
|
+
* Do _not_ access until intitialization is complete -- the client will be
|
|
88
|
+
* configured upon first access based on available configuration known at that
|
|
89
|
+
* time
|
|
90
|
+
*/
|
|
91
|
+
get client(): L;
|
|
92
|
+
/**
|
|
93
|
+
* Configure plugin for use
|
|
94
|
+
*
|
|
95
|
+
* May be called repeatedly, overlaying different options as they become
|
|
96
|
+
* available
|
|
97
|
+
*
|
|
98
|
+
* Invoked automatically by
|
|
99
|
+
* {@link https://github.com/battis/qui-cli#readme qui-cli} during
|
|
100
|
+
* initialization
|
|
101
|
+
*
|
|
102
|
+
* @see {@link Configuration}
|
|
103
|
+
*/
|
|
104
|
+
configure(proposal?: Configuration<C>): void;
|
|
105
|
+
/**
|
|
106
|
+
* Provide usage options to
|
|
107
|
+
* {@link https://github.com/battis/qui-cli#readme qui-cli} for display to user
|
|
108
|
+
* on command line
|
|
109
|
+
*
|
|
110
|
+
* Invoked automatically by
|
|
111
|
+
* {@link https://github.com/battis/qui-cli#readme qui-cli} during
|
|
112
|
+
* initialization
|
|
113
|
+
*/
|
|
114
|
+
options(): Plugin.Options;
|
|
115
|
+
/**
|
|
116
|
+
* Intialize plugin configuration from command line options and environment
|
|
117
|
+
*
|
|
118
|
+
* Invoked automatically by
|
|
119
|
+
* {@link https://github.com/battis/qui-cli#readme qui-cli} during
|
|
120
|
+
* initialization
|
|
121
|
+
*/
|
|
122
|
+
init(_: Plugin.ExpectedArguments<typeof this.options>): Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* Instantiate the `oauth2-cli` client
|
|
125
|
+
*
|
|
126
|
+
* Available hook for custom configurations in plugin development
|
|
127
|
+
*/
|
|
128
|
+
protected instantiateClient(options: OAuth2CLI.Options<C>): L;
|
|
129
|
+
/**
|
|
130
|
+
* Convenience method
|
|
131
|
+
*
|
|
132
|
+
* @see {@link OAuth2CLI.Client.request}
|
|
133
|
+
*/
|
|
134
|
+
request(...args: Parameters<OAuth2CLI.Client<C>['request']>): Promise<Response>;
|
|
135
|
+
/**
|
|
136
|
+
* Convenience method
|
|
137
|
+
*
|
|
138
|
+
* @see {@link OAuth2CLI.Client.requestJSON}
|
|
139
|
+
*/
|
|
140
|
+
requestJSON<T extends JSONValue>(...args: Parameters<OAuth2CLI.Client<C>['requestJSON']>): Promise<T>;
|
|
141
|
+
/**
|
|
142
|
+
* Convenience method
|
|
143
|
+
*
|
|
144
|
+
* @see {@link OAuth2CLI.Client.fetch}
|
|
145
|
+
*/
|
|
146
|
+
fetch(...args: Parameters<OAuth2CLI.Client<C>['fetch']>): Promise<Response>;
|
|
147
|
+
/**
|
|
148
|
+
* Convenience method
|
|
149
|
+
*
|
|
150
|
+
* @see {@link OAuth2CLI.Client.fetchJSON}
|
|
151
|
+
*/
|
|
152
|
+
fetchJSON<T extends JSONValue>(...args: Parameters<OAuth2CLI.Client<C>['fetchJSON']>): Promise<T>;
|
|
153
|
+
}
|
|
154
|
+
export {};
|