@vercel/cli-auth 0.1.0-canary.20260211174907.cdd2da6 → 0.1.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/credentials-store.d.ts +29 -0
- package/credentials-store.js +108 -0
- package/credentials-store.js.map +1 -0
- package/oauth.d.ts +207 -0
- package/oauth.js +311 -0
- package/oauth.js.map +1 -0
- package/package.json +1 -1
- package/sso.d.ts +24 -0
- package/sso.js +136 -0
- package/sso.js.map +1 -0
- package/user-agent.d.ts +13 -0
- package/user-agent.js +20 -0
- package/user-agent.js.map +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod/mini';
|
|
2
|
+
declare const Credentials: z.ZodMiniObject<{
|
|
3
|
+
/** An `access_token` obtained using the OAuth Device Authorization flow. */
|
|
4
|
+
token: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
5
|
+
/** A `refresh_token` obtained using the OAuth Device Authorization flow. */
|
|
6
|
+
refreshToken: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
7
|
+
/**
|
|
8
|
+
* The absolute time (seconds) when the {@link Credentials.token} expires.
|
|
9
|
+
* Used to optimistically check if the token is still valid.
|
|
10
|
+
*/
|
|
11
|
+
expiresAt: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
|
|
12
|
+
/** Whether to skip writing the credentials to disk during {@link CredentialsStore.update} */
|
|
13
|
+
skipWrite: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
|
|
14
|
+
'// Note': z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
15
|
+
'// Docs': z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
export type Credentials = z.infer<typeof Credentials>;
|
|
18
|
+
/**
|
|
19
|
+
* Returns in which directory the config should be present
|
|
20
|
+
* @internal Should only be used in {@link CredentialsStore} or tests.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getGlobalPathConfig(dir: string): string;
|
|
23
|
+
export declare function CredentialsStore(dir: string): {
|
|
24
|
+
configPath: string;
|
|
25
|
+
get(): Credentials;
|
|
26
|
+
/** Update the credentials store. If `skipWrite` is set, the update will be skipped. */
|
|
27
|
+
update(config: Partial<Credentials>): void;
|
|
28
|
+
};
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.getGlobalPathConfig = getGlobalPathConfig;
|
|
40
|
+
exports.CredentialsStore = CredentialsStore;
|
|
41
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
42
|
+
const fs = __importStar(require("node:fs"));
|
|
43
|
+
const node_os_1 = require("node:os");
|
|
44
|
+
// NOTE: We are pinned on v5 because newer versions behave differently
|
|
45
|
+
// when there are dots in the application name, eg. `com.vercel.cli` becomes `com.vercel`
|
|
46
|
+
const xdg_app_paths_1 = __importDefault(require("xdg-app-paths"));
|
|
47
|
+
const mini_1 = require("zod/mini");
|
|
48
|
+
const Credentials = mini_1.z.object({
|
|
49
|
+
/** An `access_token` obtained using the OAuth Device Authorization flow. */
|
|
50
|
+
token: mini_1.z.optional(mini_1.z.string()),
|
|
51
|
+
/** A `refresh_token` obtained using the OAuth Device Authorization flow. */
|
|
52
|
+
refreshToken: mini_1.z.optional(mini_1.z.string()),
|
|
53
|
+
/**
|
|
54
|
+
* The absolute time (seconds) when the {@link Credentials.token} expires.
|
|
55
|
+
* Used to optimistically check if the token is still valid.
|
|
56
|
+
*/
|
|
57
|
+
expiresAt: mini_1.z.optional(mini_1.z.number()),
|
|
58
|
+
/** Whether to skip writing the credentials to disk during {@link CredentialsStore.update} */
|
|
59
|
+
skipWrite: mini_1.z.optional(mini_1.z.boolean()),
|
|
60
|
+
'// Note': mini_1.z.optional(mini_1.z.string()),
|
|
61
|
+
'// Docs': mini_1.z.optional(mini_1.z.string()),
|
|
62
|
+
});
|
|
63
|
+
/** Returns whether a directory exists */
|
|
64
|
+
function isDirectory(path) {
|
|
65
|
+
try {
|
|
66
|
+
return fs.lstatSync(path).isDirectory();
|
|
67
|
+
}
|
|
68
|
+
catch (_) {
|
|
69
|
+
// We don't care which kind of error occured, it isn't a directory anyway.
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns in which directory the config should be present
|
|
75
|
+
* @internal Should only be used in {@link CredentialsStore} or tests.
|
|
76
|
+
*/
|
|
77
|
+
function getGlobalPathConfig(dir) {
|
|
78
|
+
const vercelDirectories = (0, xdg_app_paths_1.default)(dir).dataDirs();
|
|
79
|
+
const possibleConfigPaths = [
|
|
80
|
+
...vercelDirectories, // latest vercel directory
|
|
81
|
+
node_path_1.default.join((0, node_os_1.homedir)(), '.now'), // legacy config in user's home directory
|
|
82
|
+
...(0, xdg_app_paths_1.default)('now').dataDirs(), // legacy XDG directory
|
|
83
|
+
];
|
|
84
|
+
// The customPath flag is the preferred location,
|
|
85
|
+
// followed by the vercel directory,
|
|
86
|
+
// followed by the now directory.
|
|
87
|
+
// If none of those exist, use the vercel directory.
|
|
88
|
+
return (possibleConfigPaths.find(configPath => isDirectory(configPath)) ||
|
|
89
|
+
vercelDirectories[0]);
|
|
90
|
+
}
|
|
91
|
+
function CredentialsStore(dir) {
|
|
92
|
+
const configPath = node_path_1.default.join(getGlobalPathConfig(dir), 'auth.json');
|
|
93
|
+
return {
|
|
94
|
+
configPath,
|
|
95
|
+
get() {
|
|
96
|
+
return Credentials.parse(JSON.parse(fs.readFileSync(configPath, 'utf8')));
|
|
97
|
+
},
|
|
98
|
+
/** Update the credentials store. If `skipWrite` is set, the update will be skipped. */
|
|
99
|
+
update(config) {
|
|
100
|
+
if (config.skipWrite)
|
|
101
|
+
return;
|
|
102
|
+
const parsedConfig = Credentials.parse(config);
|
|
103
|
+
fs.mkdirSync(node_path_1.default.dirname(configPath), { recursive: true });
|
|
104
|
+
fs.writeFileSync(configPath, JSON.stringify(parsedConfig, null, 2) + '\n', { mode: 0o600 });
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=credentials-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials-store.js","sourceRoot":"","sources":["credentials-store.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,kDAiBC;AAED,4CAmBC;AA9ED,0DAA6B;AAC7B,4CAA8B;AAC9B,qCAAkC;AAClC,sEAAsE;AACtE,yFAAyF;AACzF,kEAAwC;AACxC,mCAA6B;AAE7B,MAAM,WAAW,GAAG,QAAC,CAAC,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,KAAK,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;IAC7B,4EAA4E;IAC5E,YAAY,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;IACpC;;;OAGG;IACH,SAAS,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;IACjC,6FAA6F;IAC7F,SAAS,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,OAAO,EAAE,CAAC;IAClC,SAAS,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;IACjC,SAAS,EAAE,QAAC,CAAC,QAAQ,CAAC,QAAC,CAAC,MAAM,EAAE,CAAC;CAClC,CAAC,CAAC;AAIH,yCAAyC;AACzC,SAAS,WAAW,CAAC,IAAY;IAC/B,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,0EAA0E;QAC1E,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,GAAW;IAC7C,MAAM,iBAAiB,GAAG,IAAA,uBAAW,EAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEtD,MAAM,mBAAmB,GAAG;QAC1B,GAAG,iBAAiB,EAAE,0BAA0B;QAChD,mBAAI,CAAC,IAAI,CAAC,IAAA,iBAAO,GAAE,EAAE,MAAM,CAAC,EAAE,yCAAyC;QACvE,GAAG,IAAA,uBAAW,EAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,uBAAuB;KAC1D,CAAC;IAEF,iDAAiD;IACjD,oCAAoC;IACpC,iCAAiC;IACjC,oDAAoD;IACpD,OAAO,CACL,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC/D,iBAAiB,CAAC,CAAC,CAAC,CACrB,CAAC;AACJ,CAAC;AAED,SAAgB,gBAAgB,CAAC,GAAW;IAC1C,MAAM,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,CAAC;IACpE,OAAO;QACL,UAAU;QACV,GAAG;YACD,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAC5E,CAAC;QACD,uFAAuF;QACvF,MAAM,CAAC,MAA4B;YACjC,IAAI,MAAM,CAAC,SAAS;gBAAE,OAAO;YAC7B,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC/C,EAAE,CAAC,SAAS,CAAC,mBAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5D,EAAE,CAAC,aAAa,CACd,UAAU,EACV,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAC5C,EAAE,IAAI,EAAE,KAAK,EAAE,CAChB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/oauth.d.ts
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import * as z from 'zod/mini';
|
|
2
|
+
declare const AuthorizationServerMetadata: z.ZodMiniObject<{
|
|
3
|
+
issuer: z.ZodMiniURL;
|
|
4
|
+
device_authorization_endpoint: z.ZodMiniURL;
|
|
5
|
+
token_endpoint: z.ZodMiniURL;
|
|
6
|
+
revocation_endpoint: z.ZodMiniURL;
|
|
7
|
+
jwks_uri: z.ZodMiniURL;
|
|
8
|
+
introspection_endpoint: z.ZodMiniURL;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
export type AuthorizationServerMetadata = z.infer<typeof AuthorizationServerMetadata>;
|
|
11
|
+
declare const IntrospectionResponse: z.ZodMiniObject<{
|
|
12
|
+
active: z.ZodMiniBoolean<boolean>;
|
|
13
|
+
client_id: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
14
|
+
session_id: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
export declare function OAuth(config: {
|
|
17
|
+
issuer: URL;
|
|
18
|
+
clientId: string;
|
|
19
|
+
userAgent: string;
|
|
20
|
+
}): {
|
|
21
|
+
init(): Promise<{
|
|
22
|
+
as: {
|
|
23
|
+
issuer: string;
|
|
24
|
+
device_authorization_endpoint: string;
|
|
25
|
+
token_endpoint: string;
|
|
26
|
+
revocation_endpoint: string;
|
|
27
|
+
jwks_uri: string;
|
|
28
|
+
introspection_endpoint: string;
|
|
29
|
+
};
|
|
30
|
+
init(): Promise</*elided*/ any>;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the Authorization Server Metadata
|
|
33
|
+
*
|
|
34
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest
|
|
35
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse
|
|
36
|
+
*/
|
|
37
|
+
authorizationServerMetadata(): Promise<AuthorizationServerMetadata>;
|
|
38
|
+
/**
|
|
39
|
+
* Perform the Device Authorization Request
|
|
40
|
+
*
|
|
41
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.1
|
|
42
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
|
|
43
|
+
*/
|
|
44
|
+
deviceAuthorizationRequest(): Promise<{
|
|
45
|
+
/** The device verification code. */
|
|
46
|
+
device_code: string;
|
|
47
|
+
/** The end-user verification code. */
|
|
48
|
+
user_code: string;
|
|
49
|
+
/**
|
|
50
|
+
* The minimum amount of time in seconds that the client
|
|
51
|
+
* SHOULD wait between polling requests to the token endpoint.
|
|
52
|
+
*/
|
|
53
|
+
interval: number;
|
|
54
|
+
/** The end-user verification URI on the authorization server. */
|
|
55
|
+
verification_uri: string;
|
|
56
|
+
/**
|
|
57
|
+
* The end-user verification URI on the authorization server,
|
|
58
|
+
* including the `user_code`, without redirection.
|
|
59
|
+
*/
|
|
60
|
+
verification_uri_complete: string;
|
|
61
|
+
/**
|
|
62
|
+
* The absolute lifetime of the `device_code` and `user_code`.
|
|
63
|
+
* Calculated from `expires_in`.
|
|
64
|
+
*/
|
|
65
|
+
expiresAt: number;
|
|
66
|
+
}>;
|
|
67
|
+
/**
|
|
68
|
+
* Perform the Device Access Token Request
|
|
69
|
+
*
|
|
70
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.4
|
|
71
|
+
*/
|
|
72
|
+
deviceAccessTokenRequest(device_code: string): Promise<[Error] | [null, Response]>;
|
|
73
|
+
/**
|
|
74
|
+
* Process the Token request Response
|
|
75
|
+
*
|
|
76
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.5
|
|
77
|
+
*/
|
|
78
|
+
processTokenResponse(response: Response): Promise<[OAuthError] | [null, TokenSet]>;
|
|
79
|
+
/**
|
|
80
|
+
* Perform a Token Revocation Request.
|
|
81
|
+
*
|
|
82
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7009#section-2.1
|
|
83
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7009#section-2.2
|
|
84
|
+
*/
|
|
85
|
+
revokeToken(token: string): Promise<OAuthError | undefined>;
|
|
86
|
+
/**
|
|
87
|
+
* Perform Refresh Token Request.
|
|
88
|
+
*
|
|
89
|
+
* @see https://datatracker.ietf.org/doc/html/rfc6749#section-6
|
|
90
|
+
*/
|
|
91
|
+
refreshToken(token: string): Promise<TokenSet>;
|
|
92
|
+
/**
|
|
93
|
+
* Perform Token Introspection Request.
|
|
94
|
+
*
|
|
95
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7662#section-2.1
|
|
96
|
+
*/
|
|
97
|
+
introspectToken(token: string): Promise<z.infer<typeof IntrospectionResponse>>;
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* Returns the Authorization Server Metadata
|
|
101
|
+
*
|
|
102
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest
|
|
103
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse
|
|
104
|
+
*/
|
|
105
|
+
authorizationServerMetadata(): Promise<AuthorizationServerMetadata>;
|
|
106
|
+
/**
|
|
107
|
+
* Perform the Device Authorization Request
|
|
108
|
+
*
|
|
109
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.1
|
|
110
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
|
|
111
|
+
*/
|
|
112
|
+
deviceAuthorizationRequest(): Promise<{
|
|
113
|
+
/** The device verification code. */
|
|
114
|
+
device_code: string;
|
|
115
|
+
/** The end-user verification code. */
|
|
116
|
+
user_code: string;
|
|
117
|
+
/**
|
|
118
|
+
* The minimum amount of time in seconds that the client
|
|
119
|
+
* SHOULD wait between polling requests to the token endpoint.
|
|
120
|
+
*/
|
|
121
|
+
interval: number;
|
|
122
|
+
/** The end-user verification URI on the authorization server. */
|
|
123
|
+
verification_uri: string;
|
|
124
|
+
/**
|
|
125
|
+
* The end-user verification URI on the authorization server,
|
|
126
|
+
* including the `user_code`, without redirection.
|
|
127
|
+
*/
|
|
128
|
+
verification_uri_complete: string;
|
|
129
|
+
/**
|
|
130
|
+
* The absolute lifetime of the `device_code` and `user_code`.
|
|
131
|
+
* Calculated from `expires_in`.
|
|
132
|
+
*/
|
|
133
|
+
expiresAt: number;
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Perform the Device Access Token Request
|
|
137
|
+
*
|
|
138
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.4
|
|
139
|
+
*/
|
|
140
|
+
deviceAccessTokenRequest(device_code: string): Promise<[Error] | [null, Response]>;
|
|
141
|
+
/**
|
|
142
|
+
* Process the Token request Response
|
|
143
|
+
*
|
|
144
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.5
|
|
145
|
+
*/
|
|
146
|
+
processTokenResponse(response: Response): Promise<[OAuthError] | [null, TokenSet]>;
|
|
147
|
+
/**
|
|
148
|
+
* Perform a Token Revocation Request.
|
|
149
|
+
*
|
|
150
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7009#section-2.1
|
|
151
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7009#section-2.2
|
|
152
|
+
*/
|
|
153
|
+
revokeToken(token: string): Promise<OAuthError | undefined>;
|
|
154
|
+
/**
|
|
155
|
+
* Perform Refresh Token Request.
|
|
156
|
+
*
|
|
157
|
+
* @see https://datatracker.ietf.org/doc/html/rfc6749#section-6
|
|
158
|
+
*/
|
|
159
|
+
refreshToken(token: string): Promise<TokenSet>;
|
|
160
|
+
/**
|
|
161
|
+
* Perform Token Introspection Request.
|
|
162
|
+
*
|
|
163
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7662#section-2.1
|
|
164
|
+
*/
|
|
165
|
+
introspectToken(token: string): Promise<z.infer<typeof IntrospectionResponse>>;
|
|
166
|
+
};
|
|
167
|
+
export type OAuth = ReturnType<typeof OAuth>;
|
|
168
|
+
declare const TokenSet: z.ZodMiniObject<{
|
|
169
|
+
/** The access token issued by the authorization server. */
|
|
170
|
+
access_token: z.ZodMiniString<string>;
|
|
171
|
+
/** The type of the token issued */
|
|
172
|
+
token_type: z.ZodMiniLiteral<"Bearer">;
|
|
173
|
+
/** The lifetime in seconds of the access token. */
|
|
174
|
+
expires_in: z.ZodMiniNumber<number>;
|
|
175
|
+
/** The refresh token, which can be used to obtain new access tokens. */
|
|
176
|
+
refresh_token: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
177
|
+
/** The scope of the access token. */
|
|
178
|
+
scope: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
179
|
+
}, z.core.$strip>;
|
|
180
|
+
type TokenSet = z.infer<typeof TokenSet>;
|
|
181
|
+
declare const OAuthErrorResponse: z.ZodMiniObject<{
|
|
182
|
+
error: z.ZodMiniEnum<{
|
|
183
|
+
invalid_request: "invalid_request";
|
|
184
|
+
invalid_client: "invalid_client";
|
|
185
|
+
invalid_grant: "invalid_grant";
|
|
186
|
+
unauthorized_client: "unauthorized_client";
|
|
187
|
+
unsupported_grant_type: "unsupported_grant_type";
|
|
188
|
+
invalid_scope: "invalid_scope";
|
|
189
|
+
server_error: "server_error";
|
|
190
|
+
authorization_pending: "authorization_pending";
|
|
191
|
+
slow_down: "slow_down";
|
|
192
|
+
access_denied: "access_denied";
|
|
193
|
+
expired_token: "expired_token";
|
|
194
|
+
unsupported_token_type: "unsupported_token_type";
|
|
195
|
+
}>;
|
|
196
|
+
error_description: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
197
|
+
error_uri: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
198
|
+
}, z.core.$strip>;
|
|
199
|
+
type OAuthErrorResponse = z.infer<typeof OAuthErrorResponse>;
|
|
200
|
+
declare class OAuthError extends Error {
|
|
201
|
+
name: string;
|
|
202
|
+
code: OAuthErrorResponse['error'];
|
|
203
|
+
cause: Error;
|
|
204
|
+
constructor(message: string, response: unknown);
|
|
205
|
+
}
|
|
206
|
+
export declare function isOAuthError(error: unknown): error is OAuthError;
|
|
207
|
+
export {};
|
package/oauth.js
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.OAuth = OAuth;
|
|
37
|
+
exports.isOAuthError = isOAuthError;
|
|
38
|
+
const z = __importStar(require("zod/mini"));
|
|
39
|
+
const AuthorizationServerMetadata = z.object({
|
|
40
|
+
issuer: z.url(),
|
|
41
|
+
device_authorization_endpoint: z.url(),
|
|
42
|
+
token_endpoint: z.url(),
|
|
43
|
+
revocation_endpoint: z.url(),
|
|
44
|
+
jwks_uri: z.url(),
|
|
45
|
+
introspection_endpoint: z.url(),
|
|
46
|
+
});
|
|
47
|
+
const DeviceAuthorization = z.object({
|
|
48
|
+
device_code: z.string(),
|
|
49
|
+
user_code: z.string(),
|
|
50
|
+
verification_uri: z.url(),
|
|
51
|
+
verification_uri_complete: z.url(),
|
|
52
|
+
expires_in: z.number(),
|
|
53
|
+
interval: z.number(),
|
|
54
|
+
});
|
|
55
|
+
const IntrospectionResponse = z.object({
|
|
56
|
+
active: z.boolean(),
|
|
57
|
+
client_id: z.optional(z.string()),
|
|
58
|
+
session_id: z.optional(z.string()),
|
|
59
|
+
});
|
|
60
|
+
function OAuth(config) {
|
|
61
|
+
const { issuer, clientId, userAgent } = config;
|
|
62
|
+
let as;
|
|
63
|
+
function assertAs(as) {
|
|
64
|
+
if (as)
|
|
65
|
+
return;
|
|
66
|
+
throw new Error('Authorization Server Metadata not initialized. Call init() first.');
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
async init() {
|
|
70
|
+
as ??= await this.authorizationServerMetadata();
|
|
71
|
+
return { ...this, as };
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* Returns the Authorization Server Metadata
|
|
75
|
+
*
|
|
76
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest
|
|
77
|
+
* @see https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse
|
|
78
|
+
*/
|
|
79
|
+
async authorizationServerMetadata() {
|
|
80
|
+
const response = await fetch(new URL('.well-known/openid-configuration', issuer), {
|
|
81
|
+
headers: {
|
|
82
|
+
'Content-Type': 'application/json',
|
|
83
|
+
'user-agent': userAgent,
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
const json = await response.json();
|
|
87
|
+
as = AuthorizationServerMetadata.parse(json);
|
|
88
|
+
if (as.issuer !== issuer.origin) {
|
|
89
|
+
throw new OAuthError(`Issuer mismatch: expected ${issuer}, got ${as.issuer}`, json);
|
|
90
|
+
}
|
|
91
|
+
return as;
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* Perform the Device Authorization Request
|
|
95
|
+
*
|
|
96
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.1
|
|
97
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.2
|
|
98
|
+
*/
|
|
99
|
+
async deviceAuthorizationRequest() {
|
|
100
|
+
assertAs(as);
|
|
101
|
+
const response = await fetch(as.device_authorization_endpoint, {
|
|
102
|
+
method: 'POST',
|
|
103
|
+
headers: {
|
|
104
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
105
|
+
'user-agent': userAgent,
|
|
106
|
+
},
|
|
107
|
+
body: new URLSearchParams({
|
|
108
|
+
client_id: clientId,
|
|
109
|
+
scope: 'openid offline_access',
|
|
110
|
+
}),
|
|
111
|
+
});
|
|
112
|
+
const json = await response.json();
|
|
113
|
+
const parsed = DeviceAuthorization.safeParse(json);
|
|
114
|
+
if (!parsed.success) {
|
|
115
|
+
throw new OAuthError(`Failed to parse device authorization response: ${parsed.error.message}`, json);
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
device_code: parsed.data.device_code,
|
|
119
|
+
user_code: parsed.data.user_code,
|
|
120
|
+
verification_uri: parsed.data.verification_uri,
|
|
121
|
+
verification_uri_complete: parsed.data.verification_uri_complete,
|
|
122
|
+
expiresAt: Date.now() + parsed.data.expires_in * 1000,
|
|
123
|
+
interval: parsed.data.interval,
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
/**
|
|
127
|
+
* Perform the Device Access Token Request
|
|
128
|
+
*
|
|
129
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.4
|
|
130
|
+
*/
|
|
131
|
+
async deviceAccessTokenRequest(device_code) {
|
|
132
|
+
assertAs(as);
|
|
133
|
+
try {
|
|
134
|
+
return [
|
|
135
|
+
null,
|
|
136
|
+
await fetch(as.token_endpoint, {
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: {
|
|
139
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
140
|
+
'user-agent': userAgent,
|
|
141
|
+
},
|
|
142
|
+
body: new URLSearchParams({
|
|
143
|
+
client_id: clientId,
|
|
144
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
145
|
+
device_code,
|
|
146
|
+
}),
|
|
147
|
+
signal: AbortSignal.timeout(10 * 1000),
|
|
148
|
+
}),
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (error instanceof Error)
|
|
153
|
+
return [error];
|
|
154
|
+
return [
|
|
155
|
+
new Error('An unknown error occurred. See the logs for details.', {
|
|
156
|
+
cause: error,
|
|
157
|
+
}),
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
/**
|
|
162
|
+
* Process the Token request Response
|
|
163
|
+
*
|
|
164
|
+
* @see https://datatracker.ietf.org/doc/html/rfc8628#section-3.5
|
|
165
|
+
*/
|
|
166
|
+
async processTokenResponse(response) {
|
|
167
|
+
const json = await response.json();
|
|
168
|
+
const processed = TokenSet.safeParse(json);
|
|
169
|
+
if (!processed.success) {
|
|
170
|
+
return [
|
|
171
|
+
new OAuthError(`Failed to parse token response: ${processed.error.message}`, json),
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
return [null, processed.data];
|
|
175
|
+
},
|
|
176
|
+
/**
|
|
177
|
+
* Perform a Token Revocation Request.
|
|
178
|
+
*
|
|
179
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7009#section-2.1
|
|
180
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7009#section-2.2
|
|
181
|
+
*/
|
|
182
|
+
async revokeToken(token) {
|
|
183
|
+
assertAs(as);
|
|
184
|
+
const response = await fetch(as.revocation_endpoint, {
|
|
185
|
+
method: 'POST',
|
|
186
|
+
headers: {
|
|
187
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
188
|
+
'user-agent': userAgent,
|
|
189
|
+
},
|
|
190
|
+
body: new URLSearchParams({ token, client_id: clientId }),
|
|
191
|
+
});
|
|
192
|
+
if (response.ok)
|
|
193
|
+
return;
|
|
194
|
+
const json = await response.json();
|
|
195
|
+
return new OAuthError('Revocation request failed', json);
|
|
196
|
+
},
|
|
197
|
+
/**
|
|
198
|
+
* Perform Refresh Token Request.
|
|
199
|
+
*
|
|
200
|
+
* @see https://datatracker.ietf.org/doc/html/rfc6749#section-6
|
|
201
|
+
*/
|
|
202
|
+
async refreshToken(token) {
|
|
203
|
+
assertAs(as);
|
|
204
|
+
const response = await fetch(as.token_endpoint, {
|
|
205
|
+
method: 'POST',
|
|
206
|
+
headers: {
|
|
207
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
208
|
+
'user-agent': userAgent,
|
|
209
|
+
},
|
|
210
|
+
body: new URLSearchParams({
|
|
211
|
+
client_id: clientId,
|
|
212
|
+
grant_type: 'refresh_token',
|
|
213
|
+
refresh_token: token,
|
|
214
|
+
}),
|
|
215
|
+
});
|
|
216
|
+
const [tokensError, tokenSet] = await this.processTokenResponse(response);
|
|
217
|
+
if (tokensError)
|
|
218
|
+
throw tokensError;
|
|
219
|
+
return tokenSet;
|
|
220
|
+
},
|
|
221
|
+
/**
|
|
222
|
+
* Perform Token Introspection Request.
|
|
223
|
+
*
|
|
224
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7662#section-2.1
|
|
225
|
+
*/
|
|
226
|
+
async introspectToken(token) {
|
|
227
|
+
assertAs(as);
|
|
228
|
+
const response = await fetch(as.introspection_endpoint, {
|
|
229
|
+
method: 'POST',
|
|
230
|
+
headers: {
|
|
231
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
232
|
+
'user-agent': userAgent,
|
|
233
|
+
},
|
|
234
|
+
body: new URLSearchParams({ token }),
|
|
235
|
+
});
|
|
236
|
+
const json = await response.json();
|
|
237
|
+
const processed = IntrospectionResponse.safeParse(json);
|
|
238
|
+
if (!processed.success) {
|
|
239
|
+
throw new OAuthError(`Failed to parse introspection response: ${processed.error.message}`, json);
|
|
240
|
+
}
|
|
241
|
+
return processed.data;
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
const TokenSet = z.object({
|
|
246
|
+
/** The access token issued by the authorization server. */
|
|
247
|
+
access_token: z.string(),
|
|
248
|
+
/** The type of the token issued */
|
|
249
|
+
token_type: z.literal('Bearer'),
|
|
250
|
+
/** The lifetime in seconds of the access token. */
|
|
251
|
+
expires_in: z.number(),
|
|
252
|
+
/** The refresh token, which can be used to obtain new access tokens. */
|
|
253
|
+
refresh_token: z.optional(z.string()),
|
|
254
|
+
/** The scope of the access token. */
|
|
255
|
+
scope: z.optional(z.string()),
|
|
256
|
+
});
|
|
257
|
+
const OAuthErrorResponse = z.object({
|
|
258
|
+
error: z.enum([
|
|
259
|
+
'invalid_request',
|
|
260
|
+
'invalid_client',
|
|
261
|
+
'invalid_grant',
|
|
262
|
+
'unauthorized_client',
|
|
263
|
+
'unsupported_grant_type',
|
|
264
|
+
'invalid_scope',
|
|
265
|
+
'server_error',
|
|
266
|
+
// Device Authorization Response Errors
|
|
267
|
+
'authorization_pending',
|
|
268
|
+
'slow_down',
|
|
269
|
+
'access_denied',
|
|
270
|
+
'expired_token',
|
|
271
|
+
// Revocation Response Errors
|
|
272
|
+
'unsupported_token_type',
|
|
273
|
+
]),
|
|
274
|
+
error_description: z.optional(z.string()),
|
|
275
|
+
error_uri: z.optional(z.string()),
|
|
276
|
+
});
|
|
277
|
+
function processOAuthErrorResponse(json) {
|
|
278
|
+
try {
|
|
279
|
+
return OAuthErrorResponse.parse(json);
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
if (error instanceof z.core.$ZodError) {
|
|
283
|
+
return new TypeError(`Invalid OAuth error response: ${error.message}`);
|
|
284
|
+
}
|
|
285
|
+
return new TypeError('Failed to parse OAuth error response');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
class OAuthError extends Error {
|
|
289
|
+
constructor(message, response) {
|
|
290
|
+
super(message);
|
|
291
|
+
this.name = 'OAuthError';
|
|
292
|
+
const error = processOAuthErrorResponse(response);
|
|
293
|
+
if (error instanceof TypeError) {
|
|
294
|
+
const message = `Unexpected server response: ${JSON.stringify(response)}`;
|
|
295
|
+
this.cause = new Error(message, { cause: error });
|
|
296
|
+
this.code = 'server_error';
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
let cause = error.error;
|
|
300
|
+
if (error.error_description)
|
|
301
|
+
cause += `: ${error.error_description}`;
|
|
302
|
+
if (error.error_uri)
|
|
303
|
+
cause += ` (${error.error_uri})`;
|
|
304
|
+
this.cause = new Error(cause.toString());
|
|
305
|
+
this.code = error.error;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function isOAuthError(error) {
|
|
309
|
+
return error instanceof OAuthError;
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=oauth.js.map
|
package/oauth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["oauth.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/sso.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as z from 'zod/mini';
|
|
2
|
+
import type { OAuth } from './oauth';
|
|
3
|
+
import type { Credentials } from './credentials-store';
|
|
4
|
+
/**
|
|
5
|
+
* Re-authorize a team's SSO session by opening the browser and waiting for the user to complete
|
|
6
|
+
* the SSO flow. Use when the user's SSO session has expired or missing.
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
9
|
+
export declare function reauthorizeTeam(params: {
|
|
10
|
+
/** The team's slug that requires re-authorization */
|
|
11
|
+
team: string;
|
|
12
|
+
/** The current access token that needs to be re-authorized */
|
|
13
|
+
token: Credentials['token'];
|
|
14
|
+
oauth: OAuth;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
declare const SSOError: z.ZodMiniObject<{
|
|
17
|
+
code: z.ZodMiniString<string>;
|
|
18
|
+
message: z.ZodMiniString<string>;
|
|
19
|
+
scope: z.ZodMiniOptional<z.ZodMiniString<string>>;
|
|
20
|
+
enforced: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
/** Parse an error-like object to determine if SSO re-authorization is required. */
|
|
23
|
+
export declare function parseSSOError(error: unknown): z.infer<typeof SSOError> | undefined;
|
|
24
|
+
export {};
|
package/sso.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.reauthorizeTeam = reauthorizeTeam;
|
|
40
|
+
exports.parseSSOError = parseSSOError;
|
|
41
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
42
|
+
const async_listen_1 = require("async-listen");
|
|
43
|
+
const open_1 = __importDefault(require("open"));
|
|
44
|
+
const z = __importStar(require("zod/mini"));
|
|
45
|
+
/**
|
|
46
|
+
* Re-authorize a team's SSO session by opening the browser and waiting for the user to complete
|
|
47
|
+
* the SSO flow. Use when the user's SSO session has expired or missing.
|
|
48
|
+
*
|
|
49
|
+
*/
|
|
50
|
+
async function reauthorizeTeam(params) {
|
|
51
|
+
const { team, token, oauth } = params;
|
|
52
|
+
if (!token) {
|
|
53
|
+
throw new TypeError('Token is missing, cannot initiate SSO re-authorization. Please log in again.');
|
|
54
|
+
}
|
|
55
|
+
const introspection = await oauth.introspectToken(token);
|
|
56
|
+
const { active, session_id, client_id } = introspection;
|
|
57
|
+
if (!active || !session_id || !client_id) {
|
|
58
|
+
throw new Error('Introspection failed. Token is either expired or otherwise invalid. Please log in again.');
|
|
59
|
+
}
|
|
60
|
+
const verificationToken = await waitForVerification({
|
|
61
|
+
team,
|
|
62
|
+
session_id,
|
|
63
|
+
client_id,
|
|
64
|
+
});
|
|
65
|
+
await fetch(`https://api.vercel.com/registration/verify?${new URLSearchParams({ token: verificationToken })}`);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get a verification token by spawning a localhost HTTP server
|
|
69
|
+
* that gets redirected to as the OAuth callback URL.
|
|
70
|
+
*
|
|
71
|
+
* The token returned can be sent back to the Vercel API to complete
|
|
72
|
+
* the SSO re-authorization.
|
|
73
|
+
*/
|
|
74
|
+
async function waitForVerification(params) {
|
|
75
|
+
const { team, session_id, client_id } = params;
|
|
76
|
+
const server = node_http_1.default.createServer();
|
|
77
|
+
const { port } = await (0, async_listen_1.listen)(server, 0, '127.0.0.1');
|
|
78
|
+
const initSSOUrl = new URL(`/sso/${team}?${new URLSearchParams({
|
|
79
|
+
session_id,
|
|
80
|
+
client_id,
|
|
81
|
+
next: `http://localhost:${port}`,
|
|
82
|
+
})}`, `https://vercel.com`);
|
|
83
|
+
try {
|
|
84
|
+
const [query] = await Promise.all([
|
|
85
|
+
new Promise((resolve, reject) => {
|
|
86
|
+
server.once('request', (req, res) => {
|
|
87
|
+
// Close the HTTP connection to prevent `server.close()` from hanging
|
|
88
|
+
res.setHeader('connection', 'close');
|
|
89
|
+
const { searchParams } = new URL(req.url || '/', 'http://localhost');
|
|
90
|
+
resolve(searchParams);
|
|
91
|
+
// Redirect the user back to the Vercel login notification page
|
|
92
|
+
res.statusCode = 302;
|
|
93
|
+
res.setHeader('location', getNotificationUrl(searchParams)).end();
|
|
94
|
+
});
|
|
95
|
+
server.once('error', reject);
|
|
96
|
+
}),
|
|
97
|
+
(0, open_1.default)(initSSOUrl.href),
|
|
98
|
+
]);
|
|
99
|
+
const loginError = query.get('loginError');
|
|
100
|
+
if (loginError) {
|
|
101
|
+
const error = new Error('Login failed.');
|
|
102
|
+
error.cause = JSON.parse(loginError);
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
const token = query.get('token');
|
|
106
|
+
if (!token) {
|
|
107
|
+
throw new TypeError('Could not get verification token. Please contact support.');
|
|
108
|
+
}
|
|
109
|
+
return token;
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
server.close();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function getNotificationUrl(params) {
|
|
116
|
+
const loginState = params.has('loginError')
|
|
117
|
+
? 'failed'
|
|
118
|
+
: params.has('ssoEmail')
|
|
119
|
+
? 'incomplete'
|
|
120
|
+
: 'success';
|
|
121
|
+
return `https://vercel.com/notifications/cli-login-${loginState}?${params}`;
|
|
122
|
+
}
|
|
123
|
+
const SSOError = z.object({
|
|
124
|
+
code: z.string(),
|
|
125
|
+
message: z.string(),
|
|
126
|
+
scope: z.optional(z.string()),
|
|
127
|
+
enforced: z.optional(z.boolean()),
|
|
128
|
+
});
|
|
129
|
+
/** Parse an error-like object to determine if SSO re-authorization is required. */
|
|
130
|
+
function parseSSOError(error) {
|
|
131
|
+
const { data } = SSOError.safeParse(error);
|
|
132
|
+
if (!data?.enforced)
|
|
133
|
+
return;
|
|
134
|
+
return data;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=sso.js.map
|
package/sso.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sso.js","sourceRoot":"","sources":["sso.ts"],"names":[],"mappings":"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"}
|
package/user-agent.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the user agent string for the current environment.
|
|
3
|
+
*
|
|
4
|
+
* @exapmle
|
|
5
|
+
* ```
|
|
6
|
+
* getUserAgent({ name: 'my-cli', version: '1.0.0' });
|
|
7
|
+
* // 'hostname @ my-cli 1.0.0 node-v18.16.0 linux (x64)'
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export declare function getUserAgent(pkg: {
|
|
11
|
+
name: string;
|
|
12
|
+
version: string;
|
|
13
|
+
}): string;
|
package/user-agent.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getUserAgent = getUserAgent;
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
/**
|
|
9
|
+
* Get the user agent string for the current environment.
|
|
10
|
+
*
|
|
11
|
+
* @exapmle
|
|
12
|
+
* ```
|
|
13
|
+
* getUserAgent({ name: 'my-cli', version: '1.0.0' });
|
|
14
|
+
* // 'hostname @ my-cli 1.0.0 node-v18.16.0 linux (x64)'
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
function getUserAgent(pkg) {
|
|
18
|
+
return `${node_os_1.default.hostname()} @ ${pkg.name} ${pkg.version} node-${process.version} ${node_os_1.default.platform()} (${node_os_1.default.arch()})`;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=user-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-agent.js","sourceRoot":"","sources":["user-agent.ts"],"names":[],"mappings":";;;;;AAWA,oCAIC;AAfD,sDAAyB;AAEzB;;;;;;;;GAQG;AACH,SAAgB,YAAY,CAAC,GAAsC;IACjE,OAAO,GAAG,iBAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,SAClD,OAAO,CAAC,OACV,IAAI,iBAAE,CAAC,QAAQ,EAAE,KAAK,iBAAE,CAAC,IAAI,EAAE,GAAG,CAAC;AACrC,CAAC"}
|