imapkit 5.2.0 → 5.3.1
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/README.md +37 -21
- package/bin/help.txt +25 -1
- package/bin/imapkit.js +35 -0
- package/dist/browser/imapkit.js +101 -35
- package/dist/cjs/control.d.ts +16 -5
- package/dist/cjs/control.js +35 -4
- package/dist/cjs/oauth/http.d.ts +28 -0
- package/dist/cjs/oauth/http.js +216 -0
- package/dist/cjs/oauth/jwt.d.ts +33 -0
- package/dist/cjs/oauth/jwt.js +58 -0
- package/dist/cjs/oauth/pages.d.ts +47 -0
- package/dist/cjs/oauth/pages.js +317 -0
- package/dist/cjs/oauth/policy.d.ts +48 -0
- package/dist/cjs/oauth/policy.js +66 -0
- package/dist/cjs/oauth/provider.d.ts +455 -0
- package/dist/cjs/oauth/provider.js +1422 -0
- package/dist/cjs/plugins/oauthbearer.js +10 -15
- package/dist/cjs/plugins/xoauth2.js +4 -3
- package/dist/cjs/rest.d.ts +18 -1
- package/dist/cjs/rest.js +49 -31
- package/dist/cjs/server.d.ts +25 -1
- package/dist/cjs/server.js +73 -11
- package/dist/cjs/smtp-listener.d.ts +3 -2
- package/dist/cjs/smtp-listener.js +15 -3
- package/dist/cjs/types.d.ts +10 -0
- package/dist/esm/control.d.ts +16 -5
- package/dist/esm/control.js +35 -5
- package/dist/esm/oauth/http.d.ts +28 -0
- package/dist/esm/oauth/http.js +211 -0
- package/dist/esm/oauth/jwt.d.ts +33 -0
- package/dist/esm/oauth/jwt.js +50 -0
- package/dist/esm/oauth/pages.d.ts +47 -0
- package/dist/esm/oauth/pages.js +312 -0
- package/dist/esm/oauth/policy.d.ts +48 -0
- package/dist/esm/oauth/policy.js +59 -0
- package/dist/esm/oauth/provider.d.ts +455 -0
- package/dist/esm/oauth/provider.js +1415 -0
- package/dist/esm/plugins/oauthbearer.js +10 -15
- package/dist/esm/plugins/xoauth2.js +4 -3
- package/dist/esm/rest.d.ts +18 -1
- package/dist/esm/rest.js +48 -32
- package/dist/esm/server.d.ts +25 -1
- package/dist/esm/server.js +74 -12
- package/dist/esm/smtp-listener.d.ts +3 -2
- package/dist/esm/smtp-listener.js +15 -3
- package/dist/esm/types.d.ts +10 -0
- package/dist/plugin-help.json +2 -2
- package/package.json +6 -6
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The OAuth 2.0 / OpenID Connect provider of the `oauth` option (README "OAuth 2.0 and OpenID Connect"): the
|
|
3
|
+
* authorization code flow with PKCE for mail clients, with tokens that IMAP (XOAUTH2, OAUTHBEARER) and SMTP (AUTH
|
|
4
|
+
* XOAUTH2) accept. No passwords: a consent policy decides every sign-in, from the first rung that has one: a queued
|
|
5
|
+
* decision, the user (picked by `login_hint`), the client, the server default. `prompt` shows the consent page,
|
|
6
|
+
* where the tester picks an account and clicks Allow or Deny. Strict like the IMAP side: a request that breaks a
|
|
7
|
+
* MUST of the RFCs is refused and the error description names the rule.
|
|
8
|
+
*
|
|
9
|
+
* This file holds the protocol logic and the state, src/oauth/http.ts the HTTP server and src/oauth/pages.ts the
|
|
10
|
+
* pages. Times come from `server.now()`, so tests with a fixed clock can let tokens expire.
|
|
11
|
+
*/
|
|
12
|
+
import type { ConsentPolicy, Outcome } from './policy.js';
|
|
13
|
+
import type { SigningKey } from './jwt.js';
|
|
14
|
+
import type { IMAPServer } from '../types.js';
|
|
15
|
+
/** A client of the `oauth.clients` option */
|
|
16
|
+
export interface OAuthClientOptions {
|
|
17
|
+
/** the name the consent page shows, the client ID if not set */
|
|
18
|
+
name?: string | undefined;
|
|
19
|
+
/** a confidential client authenticates with this secret, a client without one is public and must use PKCE */
|
|
20
|
+
secret?: string | undefined;
|
|
21
|
+
/** registered redirect URIs. A loopback http URI matches any port (RFC 8252 section 7.3), a trailing `*` any rest */
|
|
22
|
+
redirectUris?: string[] | undefined;
|
|
23
|
+
/** the consent policy of the client, the server default if not set */
|
|
24
|
+
consent?: ConsentPolicy | undefined;
|
|
25
|
+
}
|
|
26
|
+
/** The `oauth` option */
|
|
27
|
+
export interface OAuthOptions {
|
|
28
|
+
port?: number | undefined;
|
|
29
|
+
/** address to listen on, 127.0.0.1 by default */
|
|
30
|
+
host?: string | undefined;
|
|
31
|
+
/** HTTPS with the `credentials` or the bundled localhost certificate */
|
|
32
|
+
secure?: boolean | undefined;
|
|
33
|
+
/** the public base URL, when clients reach the provider through another address (a tunnel, a proxy) */
|
|
34
|
+
issuer?: string | undefined;
|
|
35
|
+
/** the default consent policy, `prompt` if not set */
|
|
36
|
+
consent?: ConsentPolicy | undefined;
|
|
37
|
+
/** registered clients by client ID, `imapkit`, `imapkit-approve` and `imapkit-deny` if not set */
|
|
38
|
+
clients?: Record<string, OAuthClientOptions> | undefined;
|
|
39
|
+
/** more scopes, name to the description the consent page shows */
|
|
40
|
+
scopes?: Record<string, string> | undefined;
|
|
41
|
+
/** the scope that IMAP and SMTP logins need, `mail` by default */
|
|
42
|
+
mailScope?: string | undefined;
|
|
43
|
+
/** `refuse` (default) answers a request for an unknown scope with invalid_scope, `drop` grants the others */
|
|
44
|
+
unknownScopes?: 'refuse' | 'drop' | undefined;
|
|
45
|
+
/** `offline_access` (default) issues refresh tokens only for that scope, `always` for every code exchange */
|
|
46
|
+
refreshTokens?: 'offline_access' | 'always' | undefined;
|
|
47
|
+
/** a new refresh token on every refresh, reuse of an old one revokes the grant */
|
|
48
|
+
rotateRefreshTokens?: boolean | undefined;
|
|
49
|
+
/** access token lifetime in seconds, 3600 by default */
|
|
50
|
+
accessTokenTtl?: number | undefined;
|
|
51
|
+
/** authorization code lifetime in seconds, 60 by default, at most 600 (RFC 6749 section 4.1.2) */
|
|
52
|
+
codeTtl?: number | undefined;
|
|
53
|
+
/** accepts the `plain` PKCE method, which RFC 7636 section 4.2 only allows for clients that can not do S256 */
|
|
54
|
+
allowPlainPkce?: boolean | undefined;
|
|
55
|
+
/** RSA private key in PEM for the ID tokens, a new key on every start if not set */
|
|
56
|
+
signingKey?: string | Buffer | undefined;
|
|
57
|
+
}
|
|
58
|
+
/** A registered client */
|
|
59
|
+
export interface OAuthClient {
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
secret: string | null;
|
|
63
|
+
redirectUris: string[];
|
|
64
|
+
consent: ConsentPolicy | null;
|
|
65
|
+
}
|
|
66
|
+
/** One line of the request checklist on the consent page */
|
|
67
|
+
export interface Check {
|
|
68
|
+
level: 'ok' | 'note' | 'warn';
|
|
69
|
+
text: string;
|
|
70
|
+
}
|
|
71
|
+
/** A checked authorization request */
|
|
72
|
+
export interface AuthRequest {
|
|
73
|
+
client: OAuthClient;
|
|
74
|
+
redirectUri: string;
|
|
75
|
+
/** false when the request left redirect_uri out and the only registered URI was used */
|
|
76
|
+
redirectUriSent: boolean;
|
|
77
|
+
state: string | undefined;
|
|
78
|
+
scope: string[];
|
|
79
|
+
codeChallenge: string | undefined;
|
|
80
|
+
codeChallengeMethod: string | undefined;
|
|
81
|
+
nonce: string | undefined;
|
|
82
|
+
loginHint: string | undefined;
|
|
83
|
+
/** the user that login_hint names, null when it names nobody */
|
|
84
|
+
hintUser: string | null | undefined;
|
|
85
|
+
prompt: string[];
|
|
86
|
+
checks: Check[];
|
|
87
|
+
/** other parameters the request sent, they are ignored */
|
|
88
|
+
ignored: string[];
|
|
89
|
+
}
|
|
90
|
+
/** A request waiting on the consent page */
|
|
91
|
+
export interface PendingRequest extends AuthRequest {
|
|
92
|
+
id: string;
|
|
93
|
+
expiresAt: number;
|
|
94
|
+
source: string;
|
|
95
|
+
}
|
|
96
|
+
/** A page to show instead of a redirect */
|
|
97
|
+
export interface PageData {
|
|
98
|
+
status: number;
|
|
99
|
+
title: string;
|
|
100
|
+
message: string;
|
|
101
|
+
details?: string[] | undefined;
|
|
102
|
+
tone: 'error' | 'info';
|
|
103
|
+
}
|
|
104
|
+
/** What the authorization endpoint answers */
|
|
105
|
+
export type AuthorizeResult = {
|
|
106
|
+
type: 'redirect';
|
|
107
|
+
location: string;
|
|
108
|
+
} | {
|
|
109
|
+
type: 'page';
|
|
110
|
+
page: PageData;
|
|
111
|
+
} | {
|
|
112
|
+
type: 'consent';
|
|
113
|
+
request: PendingRequest;
|
|
114
|
+
};
|
|
115
|
+
/** A JSON answer of the token, revocation or userinfo endpoint */
|
|
116
|
+
export interface JsonResult {
|
|
117
|
+
status: number;
|
|
118
|
+
body: unknown;
|
|
119
|
+
headers?: Record<string, string> | undefined;
|
|
120
|
+
/** answer with an HTML error page instead of JSON, the html token fault */
|
|
121
|
+
htmlError?: boolean | undefined;
|
|
122
|
+
}
|
|
123
|
+
/** A queued decision, see queueOAuthDecision() */
|
|
124
|
+
export interface QueuedDecision {
|
|
125
|
+
id: number;
|
|
126
|
+
decision: Outcome;
|
|
127
|
+
client: string | undefined;
|
|
128
|
+
user: string | undefined;
|
|
129
|
+
remaining: number;
|
|
130
|
+
}
|
|
131
|
+
/** A queued fault of the token endpoint, see queueOAuthTokenFault() */
|
|
132
|
+
export interface TokenFault {
|
|
133
|
+
id: number;
|
|
134
|
+
grant: 'authorization_code' | 'refresh_token' | undefined;
|
|
135
|
+
error: string | undefined;
|
|
136
|
+
description: string | undefined;
|
|
137
|
+
status: number | undefined;
|
|
138
|
+
html: boolean;
|
|
139
|
+
delay: number;
|
|
140
|
+
/** claims to change in the ID token, null removes one */
|
|
141
|
+
claims: Record<string, unknown> | undefined;
|
|
142
|
+
remaining: number;
|
|
143
|
+
}
|
|
144
|
+
interface CodeRecord {
|
|
145
|
+
clientId: string;
|
|
146
|
+
user: string;
|
|
147
|
+
redirectUri: string;
|
|
148
|
+
redirectUriSent: boolean;
|
|
149
|
+
scope: string[];
|
|
150
|
+
challenge: string | undefined;
|
|
151
|
+
method: string | undefined;
|
|
152
|
+
nonce: string | undefined;
|
|
153
|
+
expiresAt: number;
|
|
154
|
+
authTime: number;
|
|
155
|
+
grantId: string;
|
|
156
|
+
used: boolean;
|
|
157
|
+
}
|
|
158
|
+
interface TokenRecord {
|
|
159
|
+
token: string;
|
|
160
|
+
type: 'access' | 'refresh';
|
|
161
|
+
clientId: string;
|
|
162
|
+
user: string;
|
|
163
|
+
scope: string[];
|
|
164
|
+
grantId: string;
|
|
165
|
+
/** null for refresh tokens, which do not expire */
|
|
166
|
+
expiresAt: number | null;
|
|
167
|
+
revoked: boolean;
|
|
168
|
+
/** a refresh token that rotation replaced */
|
|
169
|
+
rotated: boolean;
|
|
170
|
+
/** when the token was revoked or replaced, prune() forgets it a day later */
|
|
171
|
+
endedAt: number | null;
|
|
172
|
+
}
|
|
173
|
+
/** What `server.checkAccessToken()` gets from the provider */
|
|
174
|
+
export type TokenCheck = {
|
|
175
|
+
user: string;
|
|
176
|
+
} | {
|
|
177
|
+
error: 'invalid_token' | 'insufficient_scope';
|
|
178
|
+
reason: string;
|
|
179
|
+
};
|
|
180
|
+
/**
|
|
181
|
+
* Checks a registered redirect URI against the one a request sent
|
|
182
|
+
*
|
|
183
|
+
* @param {String} registered Registered URI, a trailing `*` matches any rest
|
|
184
|
+
* @param {String} given URI of the request
|
|
185
|
+
* @return {Boolean} true if they match
|
|
186
|
+
*/
|
|
187
|
+
declare function redirectMatches(registered: string, given: string): boolean;
|
|
188
|
+
declare class OAuthProvider {
|
|
189
|
+
server: IMAPServer;
|
|
190
|
+
options: OAuthOptions;
|
|
191
|
+
/** the base URL of the endpoints, set when the HTTP server listens (see listening()) */
|
|
192
|
+
issuer: string;
|
|
193
|
+
clients: Map<string, OAuthClient>;
|
|
194
|
+
consent: ConsentPolicy;
|
|
195
|
+
decisions: QueuedDecision[];
|
|
196
|
+
tokenFaults: TokenFault[];
|
|
197
|
+
pending: Map<string, PendingRequest>;
|
|
198
|
+
codes: Map<string, CodeRecord>;
|
|
199
|
+
tokens: Map<string, TokenRecord>;
|
|
200
|
+
scopes: Record<string, string>;
|
|
201
|
+
mailScope: string;
|
|
202
|
+
accessTokenTtl: number;
|
|
203
|
+
codeTtl: number;
|
|
204
|
+
queueCounter: number;
|
|
205
|
+
key: SigningKey | null;
|
|
206
|
+
constructor(server: IMAPServer, options: OAuthOptions);
|
|
207
|
+
/**
|
|
208
|
+
* Checks an issuer URL of the options: http or https, no query or fragment (RFC 8414 section 2)
|
|
209
|
+
*
|
|
210
|
+
* @param {String} issuer URL
|
|
211
|
+
* @return {String} the URL without a trailing slash
|
|
212
|
+
*/
|
|
213
|
+
checkIssuer(issuer: unknown): string;
|
|
214
|
+
/** Restores the clients and the default policy of the options and forgets every token, request and queue */
|
|
215
|
+
reset(): void;
|
|
216
|
+
/** Milliseconds since the epoch, from the `now` option */
|
|
217
|
+
nowMs(): number;
|
|
218
|
+
/**
|
|
219
|
+
* Sets the issuer from the address the HTTP server listens on, unless the `issuer` option gave one
|
|
220
|
+
*
|
|
221
|
+
* @param {String} host Address
|
|
222
|
+
* @param {Number} port Port
|
|
223
|
+
*/
|
|
224
|
+
listening(host: string, port: number): void;
|
|
225
|
+
/** The URL of the discovery document */
|
|
226
|
+
discoveryUrl(): string;
|
|
227
|
+
/** The users as the consent and index pages show them, the default user first */
|
|
228
|
+
pageUsers(): {
|
|
229
|
+
name: string;
|
|
230
|
+
displayName: string | undefined;
|
|
231
|
+
consent: ConsentPolicy | undefined;
|
|
232
|
+
}[];
|
|
233
|
+
/**
|
|
234
|
+
* Marks a token as revoked or replaced by rotation
|
|
235
|
+
*
|
|
236
|
+
* @param {Object} record Token
|
|
237
|
+
* @param {String} how "revoked" or "rotated"
|
|
238
|
+
*/
|
|
239
|
+
endToken(record: TokenRecord, how: 'revoked' | 'rotated'): void;
|
|
240
|
+
/**
|
|
241
|
+
* Emits an `oauth` event, `{ type, ... }`, and logs it with the debug option
|
|
242
|
+
*
|
|
243
|
+
* @param {String} type Event type
|
|
244
|
+
* @param {Object} data Event data
|
|
245
|
+
*/
|
|
246
|
+
emit(type: string, data: Record<string, unknown>): void;
|
|
247
|
+
/**
|
|
248
|
+
* Answers an authorization request (RFC 6749 section 4.1.1, OpenID Connect Core 1.0 section 3.1.2.1)
|
|
249
|
+
*
|
|
250
|
+
* @param {URLSearchParams} input Query (GET) or form (POST) parameters
|
|
251
|
+
* @return {Object} a redirect, a page, or a request for the consent page
|
|
252
|
+
*/
|
|
253
|
+
authorize(input: URLSearchParams): AuthorizeResult;
|
|
254
|
+
/**
|
|
255
|
+
* Checks the parameters of an authorization request after the client and the redirect URI
|
|
256
|
+
*
|
|
257
|
+
* @return {Object} the request, or the error redirect
|
|
258
|
+
*/
|
|
259
|
+
checkRequest(client: OAuthClient, redirectUri: string, p: Record<string, string>, duplicates: string[], fail: (error: string, description: string) => AuthorizeResult): AuthRequest | AuthorizeResult;
|
|
260
|
+
/**
|
|
261
|
+
* Finds the redirect URI of a request
|
|
262
|
+
*
|
|
263
|
+
* @return {String|Object} the URI, or the error page
|
|
264
|
+
*/
|
|
265
|
+
resolveRedirect(client: OAuthClient, given: string | undefined): string | AuthorizeResult;
|
|
266
|
+
/**
|
|
267
|
+
* Checks the scope parameter
|
|
268
|
+
*
|
|
269
|
+
* @return {Array|String} the granted scopes, or the error description
|
|
270
|
+
*/
|
|
271
|
+
checkScope(value: string | undefined, checks: Check[]): string[] | string;
|
|
272
|
+
/**
|
|
273
|
+
* Checks the PKCE parameters (RFC 7636 section 4.3, RFC 9700 section 2.1.1)
|
|
274
|
+
*
|
|
275
|
+
* @return {String|null} the error description, null if they are fine
|
|
276
|
+
*/
|
|
277
|
+
checkPkce(client: OAuthClient, p: Record<string, string>, checks: Check[]): string | null;
|
|
278
|
+
/**
|
|
279
|
+
* Finds the decision of a request: a queued decision, the user of login_hint, the client, the server default
|
|
280
|
+
*
|
|
281
|
+
* @param {Object} request Checked request
|
|
282
|
+
* @return {Object} `{ outcome, source }`
|
|
283
|
+
*/
|
|
284
|
+
decide(request: AuthRequest): {
|
|
285
|
+
outcome: Outcome;
|
|
286
|
+
source: string;
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* Carries out a decision
|
|
290
|
+
*
|
|
291
|
+
* @param {Object} request Checked request
|
|
292
|
+
* @param {String|Object} outcome Decision
|
|
293
|
+
* @param {String} source Where the decision came from
|
|
294
|
+
* @param {String} [user] The user picked on the consent page
|
|
295
|
+
* @return {Object} redirect, page or consent request
|
|
296
|
+
*/
|
|
297
|
+
finish(request: AuthRequest, outcome: Outcome, source: string, user?: string): AuthorizeResult;
|
|
298
|
+
/**
|
|
299
|
+
* The user an approved request signs in: the user of login_hint, or the first user
|
|
300
|
+
*
|
|
301
|
+
* @return {String|null} user name, null if there is none
|
|
302
|
+
*/
|
|
303
|
+
pickUser(request: AuthRequest): string | null;
|
|
304
|
+
/** Sorted user names, the default user first */
|
|
305
|
+
userNames(): string[];
|
|
306
|
+
/**
|
|
307
|
+
* Answers the form of the consent page
|
|
308
|
+
*
|
|
309
|
+
* @param {URLSearchParams} form Form fields: request, action (allow, deny, outcome), user, remember, outcome, description
|
|
310
|
+
* @return {Object} redirect or page
|
|
311
|
+
*/
|
|
312
|
+
answerConsent(form: URLSearchParams): AuthorizeResult;
|
|
313
|
+
/**
|
|
314
|
+
* Drops expired consent requests and codes, and tokens a day after they expired or ended. Until then a login with
|
|
315
|
+
* one is refused as expired or revoked, after that as unknown
|
|
316
|
+
*/
|
|
317
|
+
prune(): void;
|
|
318
|
+
issueCode(request: AuthRequest, user: string): string;
|
|
319
|
+
/**
|
|
320
|
+
* Builds a redirect to the client, with `iss` (RFC 9207 section 2)
|
|
321
|
+
*
|
|
322
|
+
* @param {String} redirectUri Redirect URI, its query is kept (RFC 6749 section 3.1.2)
|
|
323
|
+
* @param {Object} params Response parameters
|
|
324
|
+
* @param {Boolean} [wrongIss] true sends another issuer, the wrong-iss fault
|
|
325
|
+
* @return {String} URL
|
|
326
|
+
*/
|
|
327
|
+
redirectUrl(redirectUri: string, params: Record<string, string>, wrongIss?: boolean): string;
|
|
328
|
+
redirectError(target: {
|
|
329
|
+
redirectUri: string;
|
|
330
|
+
state: string | undefined;
|
|
331
|
+
}, error: string, description: string): AuthorizeResult;
|
|
332
|
+
errorPage(title: string, message: string, details?: string[]): AuthorizeResult;
|
|
333
|
+
clientList(): string[];
|
|
334
|
+
/**
|
|
335
|
+
* Answers a token request (RFC 6749 sections 4.1.3 and 6)
|
|
336
|
+
*
|
|
337
|
+
* @param {URLSearchParams} form Form parameters
|
|
338
|
+
* @param {String} [authorization] Authorization header
|
|
339
|
+
* @return {Promise<Object>} JSON answer
|
|
340
|
+
*/
|
|
341
|
+
token(form: URLSearchParams, authorization: string | undefined): Promise<JsonResult>;
|
|
342
|
+
/**
|
|
343
|
+
* Authenticates the client of a token or revocation request (RFC 6749 section 2.3)
|
|
344
|
+
*
|
|
345
|
+
* @return {Object} `{ client }` or the error answer
|
|
346
|
+
*/
|
|
347
|
+
authenticateClient(p: Record<string, string>, authorization: string | undefined): {
|
|
348
|
+
client: OAuthClient;
|
|
349
|
+
} | JsonResult;
|
|
350
|
+
exchangeCode(client: OAuthClient, p: Record<string, string>, fault: TokenFault | null): JsonResult;
|
|
351
|
+
refresh(client: OAuthClient, p: Record<string, string>): JsonResult;
|
|
352
|
+
/**
|
|
353
|
+
* Issues an access token, and a refresh token and an ID token when the grant calls for them
|
|
354
|
+
*
|
|
355
|
+
* @return {Object} token response (RFC 6749 section 5.1)
|
|
356
|
+
*/
|
|
357
|
+
issueTokens(client: OAuthClient, user: string, scope: string[], grantId: string, extra: {
|
|
358
|
+
nonce?: string | undefined;
|
|
359
|
+
authTime?: number | undefined;
|
|
360
|
+
fault?: TokenFault | null | undefined;
|
|
361
|
+
refresh?: TokenRecord | undefined;
|
|
362
|
+
}): Record<string, unknown>;
|
|
363
|
+
newRefreshToken(client: OAuthClient, user: string, scope: string[], grantId: string): string;
|
|
364
|
+
/**
|
|
365
|
+
* Signs an ID token (OpenID Connect Core 1.0 section 2). The user name is the email address
|
|
366
|
+
*
|
|
367
|
+
* @return {String} JWT
|
|
368
|
+
*/
|
|
369
|
+
idToken(client: OAuthClient, user: string, scope: string[], nonce: string | undefined, authTime: number | undefined, changes: Record<string, unknown> | undefined): string;
|
|
370
|
+
/** The claims of the email and profile scopes */
|
|
371
|
+
userClaims(user: string, scope: string[]): Record<string, unknown>;
|
|
372
|
+
/** The public key of the ID tokens (RFC 7517) */
|
|
373
|
+
jwks(): {
|
|
374
|
+
keys: Record<string, string>[];
|
|
375
|
+
};
|
|
376
|
+
takeTokenFault(grant: string | undefined): TokenFault | null;
|
|
377
|
+
/**
|
|
378
|
+
* Revokes every token of a grant
|
|
379
|
+
*
|
|
380
|
+
* @return {Number} how many tokens were revoked
|
|
381
|
+
*/
|
|
382
|
+
revokeGrant(grantId: string): number;
|
|
383
|
+
/**
|
|
384
|
+
* Answers a revocation request (RFC 7009 section 2)
|
|
385
|
+
*
|
|
386
|
+
* @return {Object} JSON answer
|
|
387
|
+
*/
|
|
388
|
+
revoke(form: URLSearchParams, authorization: string | undefined): JsonResult;
|
|
389
|
+
/**
|
|
390
|
+
* Answers a UserInfo request (OpenID Connect Core 1.0 section 5.3)
|
|
391
|
+
*
|
|
392
|
+
* @param {String} [authorization] Authorization header with the access token
|
|
393
|
+
* @return {Object} JSON answer
|
|
394
|
+
*/
|
|
395
|
+
userinfo(authorization: string | undefined): JsonResult;
|
|
396
|
+
/**
|
|
397
|
+
* Why an access token can not be used
|
|
398
|
+
*
|
|
399
|
+
* @return {String|null} "expired", "revoked" ..., null for a usable token
|
|
400
|
+
*/
|
|
401
|
+
tokenProblem(record: TokenRecord | undefined): string | null;
|
|
402
|
+
/**
|
|
403
|
+
* Checks an access token for an IMAP or SMTP login
|
|
404
|
+
*
|
|
405
|
+
* @param {String} token Access token
|
|
406
|
+
* @param {String} [username] The user the client logs in as, any if not set
|
|
407
|
+
* @param {String} via "imap" or "smtp", for the event
|
|
408
|
+
* @return {Object|null} `{ user }` or `{ error, reason }`, null for a token the provider did not issue
|
|
409
|
+
*/
|
|
410
|
+
verifyAccessToken(token: string, username: string | undefined, via: string): TokenCheck | null;
|
|
411
|
+
/** The discovery document (OpenID Connect Discovery 1.0 section 3, RFC 8414 section 2) */
|
|
412
|
+
metadata(): Record<string, unknown>;
|
|
413
|
+
describeClient(client: OAuthClient): Record<string, unknown>;
|
|
414
|
+
describeToken(record: TokenRecord): Record<string, unknown>;
|
|
415
|
+
/**
|
|
416
|
+
* Selects tokens for the control API
|
|
417
|
+
*
|
|
418
|
+
* @param {Object} [filter] `{ user, client, token, type }`
|
|
419
|
+
* @return {Array} token records
|
|
420
|
+
*/
|
|
421
|
+
findTokens(filter?: {
|
|
422
|
+
user?: unknown;
|
|
423
|
+
client?: unknown;
|
|
424
|
+
token?: unknown;
|
|
425
|
+
type?: unknown;
|
|
426
|
+
}): TokenRecord[];
|
|
427
|
+
queueDecision(options?: {
|
|
428
|
+
decision?: unknown;
|
|
429
|
+
client?: unknown;
|
|
430
|
+
user?: unknown;
|
|
431
|
+
count?: unknown;
|
|
432
|
+
}): {
|
|
433
|
+
id: number;
|
|
434
|
+
};
|
|
435
|
+
queueTokenFault(options?: Record<string, unknown>): {
|
|
436
|
+
id: number;
|
|
437
|
+
};
|
|
438
|
+
listClients(): Record<string, unknown>[];
|
|
439
|
+
setClient(id: string, options: OAuthClientOptions): Record<string, unknown>;
|
|
440
|
+
deleteClient(id: string): void;
|
|
441
|
+
setConsent(consent: unknown): {
|
|
442
|
+
consent: ConsentPolicy;
|
|
443
|
+
};
|
|
444
|
+
listTokens(filter?: Record<string, unknown>): Record<string, unknown>[];
|
|
445
|
+
expireTokens(filter?: Record<string, unknown>): {
|
|
446
|
+
expired: number;
|
|
447
|
+
};
|
|
448
|
+
revokeTokens(filter?: Record<string, unknown>): {
|
|
449
|
+
revoked: number;
|
|
450
|
+
};
|
|
451
|
+
info(): Record<string, unknown>;
|
|
452
|
+
/** Adds the control operations and their REST routes, see README "Control API" */
|
|
453
|
+
registerControl(): void;
|
|
454
|
+
}
|
|
455
|
+
export { OAuthProvider, redirectMatches };
|