@baseworks/auth 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +62 -0
- package/dist/edge.js +5 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -7
- package/dist/session.js +2 -2
- package/package.json +4 -1
- package/src/cli.ts +89 -0
- package/src/index.ts +2 -2
- package/dist/{chunk-5W4TEXCT.js → chunk-JS5Y2DTW.js} +4 -4
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
|
|
3
|
+
interface AuthCliDeps {
|
|
4
|
+
/** Origin of the auth mount, e.g. `http://127.0.0.1:3003` (no `/v1/auth`). */
|
|
5
|
+
authBase: string | (() => string);
|
|
6
|
+
cliName?: string;
|
|
7
|
+
/** Persist the identity token (app decides where). */
|
|
8
|
+
onToken: (token: string) => void | Promise<void>;
|
|
9
|
+
/** Clear persisted credentials/context. */
|
|
10
|
+
onLogout?: () => void | Promise<void>;
|
|
11
|
+
/** Open the browser automatically (default true). */
|
|
12
|
+
openBrowser?: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare function addAuthCommands(program: Command, deps: AuthCliDeps): void;
|
|
15
|
+
|
|
16
|
+
export { type AuthCliDeps, addAuthCommands };
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {
|
|
2
|
+
pollCliAuth,
|
|
3
|
+
startCliAuth
|
|
4
|
+
} from "./chunk-C4V5LCFA.js";
|
|
5
|
+
|
|
6
|
+
// src/cli.ts
|
|
7
|
+
import { spawn } from "child_process";
|
|
8
|
+
import { Command } from "commander";
|
|
9
|
+
import { clr, kv, success, warn, fatal } from "@baseworks/cli/display";
|
|
10
|
+
function resolveBase(b) {
|
|
11
|
+
return (typeof b === "function" ? b() : b).replace(/\/+$/, "");
|
|
12
|
+
}
|
|
13
|
+
function openInBrowser(url) {
|
|
14
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
15
|
+
const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
16
|
+
try {
|
|
17
|
+
spawn(cmd, args, { stdio: "ignore", detached: true }).unref();
|
|
18
|
+
} catch {
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function jwtSub(token) {
|
|
22
|
+
try {
|
|
23
|
+
const seg = token.split(".")[1];
|
|
24
|
+
if (!seg) return void 0;
|
|
25
|
+
const json = Buffer.from(seg.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf8");
|
|
26
|
+
return JSON.parse(json).sub;
|
|
27
|
+
} catch {
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function addAuthCommands(program, deps) {
|
|
32
|
+
const cli = deps.cliName ?? "cli";
|
|
33
|
+
program.addCommand(
|
|
34
|
+
new Command("login").description("Log in via browser (OIDC/PKCE)").option("--no-open", "Do not open the browser automatically").action(async (opts) => {
|
|
35
|
+
const base = resolveBase(deps.authBase);
|
|
36
|
+
const start = await startCliAuth(base).catch((e) => fatal(`Could not reach auth service at ${base}: ${e.message}`));
|
|
37
|
+
console.log(`
|
|
38
|
+
${clr.dim}Opening your browser to sign in\u2026${clr.reset}`);
|
|
39
|
+
console.log(` ${clr.dim}If it does not open, visit:${clr.reset}
|
|
40
|
+
${clr.cyan}${start.url}${clr.reset}
|
|
41
|
+
`);
|
|
42
|
+
if (deps.openBrowser !== false && opts.open !== false) openInBrowser(start.url);
|
|
43
|
+
const { token } = await pollCliAuth(base, start.state).catch((e) => fatal(e.message));
|
|
44
|
+
await deps.onToken(token);
|
|
45
|
+
const sub = jwtSub(token);
|
|
46
|
+
success("Logged in.");
|
|
47
|
+
if (sub) kv([["user id", sub]]);
|
|
48
|
+
console.log(` ${clr.dim}Next: ${cli} use \xB7 ${cli} orgs${clr.reset}
|
|
49
|
+
`);
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
program.addCommand(
|
|
53
|
+
new Command("logout").description("Clear saved credentials and active context").action(async () => {
|
|
54
|
+
if (deps.onLogout) await deps.onLogout();
|
|
55
|
+
else warn("No logout handler configured.");
|
|
56
|
+
success("Logged out.");
|
|
57
|
+
})
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
addAuthCommands
|
|
62
|
+
};
|
package/dist/edge.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getSessionFromCookies
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import {
|
|
5
|
-
parseJwtPayload
|
|
6
|
-
} from "./chunk-OD5XLL3O.js";
|
|
7
|
-
import "./chunk-34E5PYNA.js";
|
|
3
|
+
} from "./chunk-JS5Y2DTW.js";
|
|
8
4
|
import {
|
|
9
5
|
buildPublicUrl,
|
|
10
6
|
normalizeUrlLike
|
|
11
7
|
} from "./chunk-3NJASEF4.js";
|
|
8
|
+
import {
|
|
9
|
+
parseJwtPayload
|
|
10
|
+
} from "./chunk-OD5XLL3O.js";
|
|
11
|
+
import "./chunk-34E5PYNA.js";
|
|
12
12
|
|
|
13
13
|
// src/edge.ts
|
|
14
14
|
import { headers } from "next/headers";
|
package/dist/index.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ export { OidcHumanResolverConfig, createOidcHumanResolver } from './oidc-human.j
|
|
|
3
3
|
export { OidcAuthUrlConfig, PkceChallenge, buildOidcAuthUrl, generatePkce } from './pkce.js';
|
|
4
4
|
export { CliAuthResult, CliAuthStart, PollOptions, pollCliAuth, startCliAuth } from './cli-auth.js';
|
|
5
5
|
export { hashToken, looksLikeJwt, stripBearer } from './token.js';
|
|
6
|
-
export { JwtClaims, verifyHs256Jwt } from './jwt.js';
|
|
6
|
+
export { JwtClaims, signHs256Jwt, verifyHs256Jwt } from './jwt.js';
|
|
7
7
|
export { buildAccountProfileUrl, buildAuthLoginUrl, buildAuthLogoutUrl, buildPublicUrl, getAccountPublicUrl, getAppBasePath, getAuthPublicUrl, getPublicSiteUrl, normalizeUrlLike } from './url-helpers.js';
|
package/dist/index.js
CHANGED
|
@@ -13,13 +13,6 @@ import {
|
|
|
13
13
|
looksLikeJwt,
|
|
14
14
|
stripBearer
|
|
15
15
|
} from "./chunk-VBIQJKUU.js";
|
|
16
|
-
import {
|
|
17
|
-
verifyHs256Jwt
|
|
18
|
-
} from "./chunk-OD5XLL3O.js";
|
|
19
|
-
import {
|
|
20
|
-
buildOidcAuthUrl,
|
|
21
|
-
generatePkce
|
|
22
|
-
} from "./chunk-34E5PYNA.js";
|
|
23
16
|
import {
|
|
24
17
|
buildAccountProfileUrl,
|
|
25
18
|
buildAuthLoginUrl,
|
|
@@ -31,6 +24,14 @@ import {
|
|
|
31
24
|
getPublicSiteUrl,
|
|
32
25
|
normalizeUrlLike
|
|
33
26
|
} from "./chunk-3NJASEF4.js";
|
|
27
|
+
import {
|
|
28
|
+
signHs256Jwt,
|
|
29
|
+
verifyHs256Jwt
|
|
30
|
+
} from "./chunk-OD5XLL3O.js";
|
|
31
|
+
import {
|
|
32
|
+
buildOidcAuthUrl,
|
|
33
|
+
generatePkce
|
|
34
|
+
} from "./chunk-34E5PYNA.js";
|
|
34
35
|
export {
|
|
35
36
|
buildAccountProfileUrl,
|
|
36
37
|
buildAuthLoginUrl,
|
|
@@ -47,6 +48,7 @@ export {
|
|
|
47
48
|
looksLikeJwt,
|
|
48
49
|
normalizeUrlLike,
|
|
49
50
|
pollCliAuth,
|
|
51
|
+
signHs256Jwt,
|
|
50
52
|
startCliAuth,
|
|
51
53
|
stripBearer,
|
|
52
54
|
verifyHs256Jwt,
|
package/dist/session.js
CHANGED
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
handleAuthorizationCallback,
|
|
10
10
|
hasServerOidcSession,
|
|
11
11
|
oidcCookies
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JS5Y2DTW.js";
|
|
13
|
+
import "./chunk-3NJASEF4.js";
|
|
13
14
|
import "./chunk-OD5XLL3O.js";
|
|
14
15
|
import "./chunk-34E5PYNA.js";
|
|
15
|
-
import "./chunk-3NJASEF4.js";
|
|
16
16
|
export {
|
|
17
17
|
buildAuthorizationRedirect,
|
|
18
18
|
buildLogoutResponse,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baseworks/auth",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"./oidc-human": "./dist/oidc-human.js",
|
|
9
9
|
"./pkce": "./dist/pkce.js",
|
|
10
10
|
"./cli-auth": "./dist/cli-auth.js",
|
|
11
|
+
"./cli": "./dist/cli.js",
|
|
11
12
|
"./token": "./dist/token.js",
|
|
12
13
|
"./session": "./dist/session.js",
|
|
13
14
|
"./url-helpers": "./dist/url-helpers.js",
|
|
@@ -40,8 +41,10 @@
|
|
|
40
41
|
}
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
44
|
+
"@baseworks/cli": "workspace:*",
|
|
43
45
|
"@baseworks/tsconfig": "workspace:*",
|
|
44
46
|
"@types/node": "^26.0.1",
|
|
47
|
+
"commander": "^15.0.0",
|
|
45
48
|
"hono": "^4.12.27",
|
|
46
49
|
"tsup": "^8.5.1",
|
|
47
50
|
"typescript": "^5.6.0"
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Importable `login` / `logout` commands for any CLI that authenticates through
|
|
3
|
+
* an auth-service (OIDC/PKCE device flow). Mirrors the `@baseworks/org/cli` and
|
|
4
|
+
* `@baseworks/iam/cli` pattern — the commands live in auth's own package; the
|
|
5
|
+
* app composes them:
|
|
6
|
+
*
|
|
7
|
+
* import { addAuthCommands } from '@baseworks/auth/cli'
|
|
8
|
+
* addAuthCommands(program, { authBase, cliName: 'dtab', onToken, onLogout })
|
|
9
|
+
*
|
|
10
|
+
* The device flow is auth-service's `/v1/auth/start` + `/v1/auth/poll/:state`
|
|
11
|
+
* (see `@baseworks/auth/cli-auth`). auth mints an identity JWT (`{ sub, type }`,
|
|
12
|
+
* HS256) that org-service and iam-service verify with the shared realm secret —
|
|
13
|
+
* so ONE login token works across the whole plane. Org context is not in the
|
|
14
|
+
* token; the app resolves it via org-service (`use` / `ls`).
|
|
15
|
+
*/
|
|
16
|
+
import { spawn } from 'node:child_process'
|
|
17
|
+
import { Command } from 'commander'
|
|
18
|
+
import { clr, kv, success, warn, fatal } from '@baseworks/cli/display'
|
|
19
|
+
import { startCliAuth, pollCliAuth } from './cli-auth.js'
|
|
20
|
+
|
|
21
|
+
export interface AuthCliDeps {
|
|
22
|
+
/** Origin of the auth mount, e.g. `http://127.0.0.1:3003` (no `/v1/auth`). */
|
|
23
|
+
authBase: string | (() => string)
|
|
24
|
+
cliName?: string
|
|
25
|
+
/** Persist the identity token (app decides where). */
|
|
26
|
+
onToken: (token: string) => void | Promise<void>
|
|
27
|
+
/** Clear persisted credentials/context. */
|
|
28
|
+
onLogout?: () => void | Promise<void>
|
|
29
|
+
/** Open the browser automatically (default true). */
|
|
30
|
+
openBrowser?: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function resolveBase(b: AuthCliDeps['authBase']): string {
|
|
34
|
+
return (typeof b === 'function' ? b() : b).replace(/\/+$/, '')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function openInBrowser(url: string): void {
|
|
38
|
+
const cmd = process.platform === 'darwin' ? 'open'
|
|
39
|
+
: process.platform === 'win32' ? 'cmd'
|
|
40
|
+
: 'xdg-open'
|
|
41
|
+
const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url]
|
|
42
|
+
try { spawn(cmd, args, { stdio: 'ignore', detached: true }).unref() } catch { /* print fallback below */ }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Decode a JWT payload without verifying (display only). */
|
|
46
|
+
function jwtSub(token: string): string | undefined {
|
|
47
|
+
try {
|
|
48
|
+
const seg = token.split('.')[1]
|
|
49
|
+
if (!seg) return undefined
|
|
50
|
+
const json = Buffer.from(seg.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf8')
|
|
51
|
+
return (JSON.parse(json) as { sub?: string }).sub
|
|
52
|
+
} catch { return undefined }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function addAuthCommands(program: Command, deps: AuthCliDeps): void {
|
|
56
|
+
const cli = deps.cliName ?? 'cli'
|
|
57
|
+
|
|
58
|
+
program.addCommand(
|
|
59
|
+
new Command('login')
|
|
60
|
+
.description('Log in via browser (OIDC/PKCE)')
|
|
61
|
+
.option('--no-open', 'Do not open the browser automatically')
|
|
62
|
+
.action(async (opts: { open?: boolean }) => {
|
|
63
|
+
const base = resolveBase(deps.authBase)
|
|
64
|
+
const start = await startCliAuth(base).catch((e: Error) => fatal(`Could not reach auth service at ${base}: ${e.message}`))
|
|
65
|
+
|
|
66
|
+
console.log(`\n ${clr.dim}Opening your browser to sign in…${clr.reset}`)
|
|
67
|
+
console.log(` ${clr.dim}If it does not open, visit:${clr.reset}\n ${clr.cyan}${start.url}${clr.reset}\n`)
|
|
68
|
+
if (deps.openBrowser !== false && opts.open !== false) openInBrowser(start.url)
|
|
69
|
+
|
|
70
|
+
const { token } = await pollCliAuth(base, start.state).catch((e: Error) => fatal(e.message))
|
|
71
|
+
await deps.onToken(token)
|
|
72
|
+
|
|
73
|
+
const sub = jwtSub(token)
|
|
74
|
+
success('Logged in.')
|
|
75
|
+
if (sub) kv([['user id', sub]])
|
|
76
|
+
console.log(` ${clr.dim}Next: ${cli} use · ${cli} orgs${clr.reset}\n`)
|
|
77
|
+
}),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
program.addCommand(
|
|
81
|
+
new Command('logout')
|
|
82
|
+
.description('Clear saved credentials and active context')
|
|
83
|
+
.action(async () => {
|
|
84
|
+
if (deps.onLogout) await deps.onLogout()
|
|
85
|
+
else warn('No logout handler configured.')
|
|
86
|
+
success('Logged out.')
|
|
87
|
+
}),
|
|
88
|
+
)
|
|
89
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -17,8 +17,8 @@ export type { CliAuthStart, CliAuthResult, PollOptions } from './cli-auth';
|
|
|
17
17
|
// Token utilities
|
|
18
18
|
export { hashToken, looksLikeJwt, stripBearer } from './token';
|
|
19
19
|
|
|
20
|
-
// HS256 JWT
|
|
21
|
-
export { verifyHs256Jwt } from './jwt';
|
|
20
|
+
// HS256 JWT sign + verify (Node.js)
|
|
21
|
+
export { signHs256Jwt, verifyHs256Jwt } from './jwt';
|
|
22
22
|
export type { JwtClaims } from './jwt';
|
|
23
23
|
|
|
24
24
|
// URL helpers (auth/account public URLs, login/logout URL builders)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAuthPublicUrl,
|
|
3
|
+
normalizeUrlLike
|
|
4
|
+
} from "./chunk-3NJASEF4.js";
|
|
1
5
|
import {
|
|
2
6
|
parseJwtPayload
|
|
3
7
|
} from "./chunk-OD5XLL3O.js";
|
|
4
8
|
import {
|
|
5
9
|
generatePkce
|
|
6
10
|
} from "./chunk-34E5PYNA.js";
|
|
7
|
-
import {
|
|
8
|
-
getAuthPublicUrl,
|
|
9
|
-
normalizeUrlLike
|
|
10
|
-
} from "./chunk-3NJASEF4.js";
|
|
11
11
|
|
|
12
12
|
// src/session.ts
|
|
13
13
|
import { cookies } from "next/headers";
|