|
1 | 1 | 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'; |
8 | 2 | import CommandPolykey from '../CommandPolykey.js'; |
9 | 3 | import * as binProcessors from '../utils/processors.js'; |
10 | | -import * as binParsers from '../utils/parsers.js'; |
11 | 4 | import * as binUtils from '../utils/index.js'; |
12 | 5 | import * as binOptions from '../utils/options.js'; |
13 | | -import * as errors from '../errors.js'; |
14 | 6 |
|
15 | 7 | class CommandLogin extends CommandPolykey { |
16 | 8 | constructor(...args: ConstructorParameters<typeof CommandPolykey>) { |
17 | 9 | super(...args); |
18 | 10 | 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'); |
25 | 13 | this.addOption(binOptions.nodeId); |
26 | 14 | this.addOption(binOptions.clientHost); |
27 | 15 | this.addOption(binOptions.clientPort); |
28 | | - this.action(async (encodedToken, options) => { |
| 16 | + this.addOption(binOptions.returnURLPath); |
| 17 | + this.action(async (url: string, options) => { |
29 | 18 | const { default: PolykeyClient } = await import( |
30 | 19 | 'polykey/PolykeyClient.js' |
31 | 20 | ); |
32 | | - const tokensUtils = await import('polykey/tokens/utils.js'); |
| 21 | + const { default: open } = await import('open'); |
33 | 22 | const clientOptions = await binProcessors.processClientOptions( |
34 | 23 | options.nodePath, |
35 | 24 | options.nodeId, |
@@ -58,51 +47,35 @@ class CommandLogin extends CommandPolykey { |
58 | 47 | logger: this.logger.getChild(PolykeyClient.name), |
59 | 48 | }); |
60 | 49 |
|
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 |
74 | 51 | const response = await binUtils.retryAuthentication( |
75 | 52 | (auth) => |
76 | | - pkClient.rpcClient.methods.authSignToken({ |
77 | | - metadata: auth, |
78 | | - ...incomingTokenEncoded, |
79 | | - }), |
| 53 | + pkClient.rpcClient.methods.authIdentityToken({ metadata: auth }), |
80 | 54 | meta, |
81 | 55 | ); |
82 | 56 |
|
83 | 57 | // Send the returned JWT to the returnURL provided by the initial token |
84 | 58 | 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 | + ); |
100 | 70 |
|
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', |
105 | 75 | ); |
| 76 | + await open(targetURL.toString()); |
| 77 | + } catch (e) { |
| 78 | + process.stderr.write(`Failed to open browser: ${e.message}\n`); |
106 | 79 | } |
107 | 80 | } finally { |
108 | 81 | if (pkClient! != null) await pkClient.stop(); |
|
0 commit comments