Skip to content

Commit 310dccb

Browse files
authored
Merge pull request #428 from MatrixAI/feature-align-with-tailscale-login
Aligned command with tailscale login flow
2 parents 006ff63 + 80aaa86 commit 310dccb

File tree

9 files changed

+205
-185
lines changed

9 files changed

+205
-185
lines changed

npmDepsHash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
sha256-23Yx1RJcaNEL1YmNz/LRFYL+5g++B+aoT0CSSbreAx8=
1+
sha256-j3S6Zig9cm8n29qoJxBmj82WE6YHG2SOSFBuDhJ7xmo=

package-lock.json

Lines changed: 138 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,21 +126,21 @@
126126
},
127127
"optionalDependencies": {
128128
"@matrixai/db": "*",
129+
"@matrixai/exec-darwin-universal": "*",
130+
"@matrixai/exec-linux-x64": "*",
129131
"@matrixai/mdns-linux-x64": "*",
130132
"@matrixai/quic-darwin-universal": "*",
131133
"@matrixai/quic-linux-x64": "*",
132134
"@matrixai/quic-win32-x64": "*",
133-
"@matrixai/exec-darwin-universal": "*",
134-
"@matrixai/exec-linux-x64": "*",
135135
"fd-lock": "*",
136136
"sodium-native": "*"
137137
},
138138
"devDependencies": {
139-
"@matrixai/lint": "^0.2.11",
139+
"@fast-check/jest": "^2.1.1",
140140
"@matrixai/errors": "^2.1.3",
141-
"@matrixai/logger": "^4.0.3",
142141
"@matrixai/exec": "^1.0.3",
143-
"@fast-check/jest": "^2.1.1",
142+
"@matrixai/lint": "^0.2.11",
143+
"@matrixai/logger": "^4.0.3",
144144
"@swc/core": "1.3.82",
145145
"@swc/jest": "^0.2.29",
146146
"@types/jest": "^29.5.14",
@@ -161,7 +161,8 @@
161161
"mocked-env": "^1.3.5",
162162
"nexpect": "^0.6.0",
163163
"node-gyp-build": "^4.8.4",
164-
"polykey": "^2.4.0",
164+
"open": "^10.1.2",
165+
"polykey": "^2.5.0",
165166
"shelljs": "^0.8.5",
166167
"shx": "^0.3.4",
167168
"tsx": "^3.12.7",

src/auth/CommandLogin.ts

Lines changed: 25 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,24 @@
11
import type PolykeyClient from 'polykey/PolykeyClient.js';
2-
import type {
3-
TokenPayloadEncoded,
4-
TokenProtectedHeaderEncoded,
5-
TokenSignatureEncoded,
6-
} from 'polykey/tokens/types.js';
7-
import type { IdentityRequestData } from 'polykey/client/types.js';
82
import CommandPolykey from '../CommandPolykey.js';
93
import * as binProcessors from '../utils/processors.js';
10-
import * as binParsers from '../utils/parsers.js';
114
import * as binUtils from '../utils/index.js';
125
import * as binOptions from '../utils/options.js';
13-
import * as errors from '../errors.js';
146

157
class CommandLogin extends CommandPolykey {
168
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
179
super(...args);
1810
this.name('login');
19-
this.description('Login to a platform with Polykey identity');
20-
this.argument(
21-
'<token>',
22-
'Token provided by platform for logging in',
23-
binParsers.parseCompactJWT,
24-
);
11+
this.description('Login to a platform with your Polykey identity');
12+
this.argument('<url>', 'The URL to login using Polykey');
2513
this.addOption(binOptions.nodeId);
2614
this.addOption(binOptions.clientHost);
2715
this.addOption(binOptions.clientPort);
28-
this.action(async (encodedToken, options) => {
16+
this.addOption(binOptions.returnURLPath);
17+
this.action(async (url: string, options) => {
2918
const { default: PolykeyClient } = await import(
3019
'polykey/PolykeyClient.js'
3120
);
32-
const tokensUtils = await import('polykey/tokens/utils.js');
21+
const { default: open } = await import('open');
3322
const clientOptions = await binProcessors.processClientOptions(
3423
options.nodePath,
3524
options.nodeId,
@@ -58,51 +47,35 @@ class CommandLogin extends CommandPolykey {
5847
logger: this.logger.getChild(PolykeyClient.name),
5948
});
6049

61-
// Create a JSON representation of the encoded header
62-
const [protectedHeader, payload, signature] = encodedToken;
63-
const incomingTokenEncoded = {
64-
payload: payload as TokenPayloadEncoded,
65-
signatures: [
66-
{
67-
protected: protectedHeader as TokenProtectedHeaderEncoded,
68-
signature: signature as TokenSignatureEncoded,
69-
},
70-
],
71-
};
72-
73-
// Get it verified and signed by the agent
50+
// Get a signed token by the agent
7451
const response = await binUtils.retryAuthentication(
7552
(auth) =>
76-
pkClient.rpcClient.methods.authSignToken({
77-
metadata: auth,
78-
...incomingTokenEncoded,
79-
}),
53+
pkClient.rpcClient.methods.authIdentityToken({ metadata: auth }),
8054
meta,
8155
);
8256

8357
// Send the returned JWT to the returnURL provided by the initial token
8458
const compactHeader = binUtils.jsonToCompactJWT(response);
85-
const incomingPayload =
86-
tokensUtils.parseTokenPayload<IdentityRequestData>(payload);
87-
let result: Response;
88-
try {
89-
result = await fetch(incomingPayload.returnURL, {
90-
method: 'POST',
91-
headers: { 'Content-Type': 'application/json' },
92-
body: JSON.stringify({ token: compactHeader }),
93-
});
94-
} catch (e) {
95-
throw new errors.ErrorPolykeyCLILoginFailed(
96-
'Failed to send token to return url',
97-
{ cause: e },
98-
);
99-
}
59+
const targetURL = new URL(
60+
url.endsWith('/') ? url.slice(0, url.length) : url,
61+
);
62+
const subPath: string = options.returnURLPath ?? '/oauth2/oidc';
63+
targetURL.pathname = subPath.startsWith('/') ? subPath : `/${subPath}`;
64+
targetURL.searchParams.append('token', compactHeader);
65+
66+
// Print out the URL to stderr
67+
process.stderr.write(
68+
`Open the following URL in your browser:\n\t${targetURL}\n`,
69+
);
10070

101-
// Handle non-200 response
102-
if (!result.ok) {
103-
throw new errors.ErrorPolykeyCLILoginFailed(
104-
`Return url returned failure with code ${result.status}`,
71+
// Try to open the URL in the browser
72+
try {
73+
process.stderr.write(
74+
'Attempting to open this URL in your browser...\n',
10575
);
76+
await open(targetURL.toString());
77+
} catch (e) {
78+
process.stderr.write(`Failed to open browser: ${e.message}\n`);
10679
}
10780
} finally {
10881
if (pkClient! != null) await pkClient.stop();

src/errors.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,6 @@ class ErrorPolykeyCLIInvalidJWT<T> extends ErrorPolykeyCLI<T> {
201201
exitCode = sysexits.USAGE;
202202
}
203203

204-
class ErrorPolykeyCLILoginFailed<T> extends ErrorPolykeyCLI<T> {
205-
static description = 'Failed to login using Polykey';
206-
exitCode = sysexits.SOFTWARE;
207-
}
208-
209204
export {
210205
ErrorPolykeyCLI,
211206
ErrorPolykeyCLIUncaughtException,
@@ -235,5 +230,4 @@ export {
235230
ErrorPolykeyCLIEditSecret,
236231
ErrorPolykeyCLITouchSecret,
237232
ErrorPolykeyCLIInvalidJWT,
238-
ErrorPolykeyCLILoginFailed,
239233
};

0 commit comments

Comments
 (0)