Skip to content

Commit da1c878

Browse files
committed
chore: add example of passing bearer auth token with setup frame
Signed-off-by: Kevin Viglucci <[email protected]>
1 parent ee00386 commit da1c878

File tree

4 files changed

+514
-56
lines changed

4 files changed

+514
-56
lines changed

packages/rsocket-examples/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
"start-client-apollo-graphql": "ts-node -r tsconfig-paths/register src/graphql/apollo/client/example.ts",
2424
"start-client-server-apollo-graphql": "ts-node -r tsconfig-paths/register src/graphql/apollo/client-server/example.ts",
2525
"start-client-server-composite-metadata-auth-example-client": "ts-node -r tsconfig-paths/register src/composite-metadata/bearer-token-auth/client.ts",
26-
"start-client-server-composite-metadata-auth-example-server": "ts-node -r tsconfig-paths/register src/composite-metadata/bearer-token-auth/server.ts"
26+
"start-client-server-composite-metadata-auth-example-server": "ts-node -r tsconfig-paths/register src/composite-metadata/bearer-token-auth/server.ts",
27+
"start-client-server-composite-metadata-auth-setup-frame-example-client": "ts-node -r tsconfig-paths/register src/composite-metadata/bearer-token-auth-setup-frame/client.ts",
28+
"start-client-server-composite-metadata-auth-setup-frame-example-server": "ts-node -r tsconfig-paths/register src/composite-metadata/bearer-token-auth-setup-frame/server.ts"
2729
},
2830
"dependencies": {
2931
"@apollo/client": "^3.5.10",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* Copyright 2021-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { Payload, RSocket, RSocketConnector } from "rsocket-core";
18+
import { TcpClientTransport } from "rsocket-tcp-client";
19+
import {
20+
encodeBearerAuthMetadata,
21+
encodeCompositeMetadata,
22+
encodeRoute,
23+
WellKnownMimeType,
24+
} from "rsocket-composite-metadata";
25+
import { exit } from "process";
26+
import Logger from "../../shared/logger";
27+
import MESSAGE_RSOCKET_ROUTING = WellKnownMimeType.MESSAGE_RSOCKET_ROUTING;
28+
import MESSAGE_RSOCKET_AUTHENTICATION = WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION;
29+
30+
function makeMetadata(bearerToken?: string, route?: string) {
31+
const map = new Map<WellKnownMimeType, Buffer>();
32+
33+
if (bearerToken) {
34+
map.set(
35+
MESSAGE_RSOCKET_AUTHENTICATION,
36+
encodeBearerAuthMetadata(Buffer.from(bearerToken))
37+
);
38+
}
39+
40+
if (route) {
41+
const encodedRoute = encodeRoute(route);
42+
map.set(MESSAGE_RSOCKET_ROUTING, encodedRoute);
43+
}
44+
45+
return encodeCompositeMetadata(map);
46+
}
47+
48+
function makeConnector(token: string) {
49+
// NOTE: THIS EXAMPLE DOES NOT COVER TLS.
50+
// ALWAYS USE A SECURE CONNECTION SUCH AS TLS WHEN TRANSMITTING SENSITIVE INFORMATION SUCH AS AUTH TOKENS.
51+
return new RSocketConnector({
52+
transport: new TcpClientTransport({
53+
connectionOptions: {
54+
host: "127.0.0.1",
55+
port: 9090,
56+
},
57+
}),
58+
setup: {
59+
payload: {
60+
data: Buffer.from([]),
61+
metadata: makeMetadata(token),
62+
},
63+
},
64+
});
65+
}
66+
67+
async function requestResponse(
68+
rsocket: RSocket,
69+
compositeMetaData: Buffer,
70+
message: string = ""
71+
): Promise<Payload> {
72+
return new Promise((resolve, reject) => {
73+
return rsocket.requestResponse(
74+
{
75+
data: Buffer.from(message),
76+
metadata: compositeMetaData,
77+
},
78+
{
79+
onError: (e) => {
80+
reject(e);
81+
},
82+
onNext: (payload, isComplete) => {
83+
Logger.info(
84+
`onNext payload[data: ${payload.data}; metadata: ${payload.metadata}]|${isComplete}`
85+
);
86+
resolve(payload);
87+
},
88+
onComplete: () => {},
89+
onExtension: () => {},
90+
}
91+
);
92+
});
93+
}
94+
95+
async function main() {
96+
try {
97+
// we expect this connection to fail because we aren't passing a valid token
98+
const connector = makeConnector("");
99+
const rsocket = await connector.connect();
100+
await new Promise(function (resolve, reject) {
101+
Logger.info("Rejecting once socket closes...");
102+
rsocket.onClose((e) => {
103+
reject(e);
104+
});
105+
});
106+
} catch (e) {
107+
Logger.error(`Expected error: ${e}`);
108+
}
109+
110+
// NOTE: YOU SHOULD NEVER HARD CODE AN AUTH TOKEN IN A FILE IN THIS WAY. THIS IS PURELY FOR EXAMPLE PURPOSES.
111+
// The SHA1 HASH of rsocket-js-2024-10
112+
const exampleToken = "8a7d50f76ef86c75bd3563e55f8835515189dbff";
113+
114+
// we expect this connection to succeed because we pass a valid token
115+
const connector = makeConnector(exampleToken);
116+
const rsocket = await connector.connect();
117+
118+
// this request SHOULD pass
119+
const echoResponse = await requestResponse(
120+
rsocket,
121+
makeMetadata(null, "EchoService.echo"),
122+
"Hello World"
123+
);
124+
Logger.info(`EchoService.echo response: ${echoResponse.data.toString()}`);
125+
126+
// this request will reject (unknown route)
127+
try {
128+
await requestResponse(
129+
rsocket,
130+
makeMetadata(null, "UnknownService.unknown"),
131+
"Hello World"
132+
);
133+
} catch (e) {
134+
Logger.error(`Expected error: ${e}`);
135+
}
136+
137+
// this request will reject (no routing data)
138+
try {
139+
await requestResponse(rsocket, makeMetadata(null), "Hello World");
140+
} catch (e) {
141+
Logger.error(`Expected error: ${e}`);
142+
}
143+
144+
const whoAmiResponse = await requestResponse(
145+
rsocket,
146+
makeMetadata(exampleToken, "AuthService.whoAmI")
147+
);
148+
Logger.info(`AuthService.whoAmI response: ${whoAmiResponse.data.toString()}`);
149+
}
150+
151+
main()
152+
.then(() => exit())
153+
.catch((error: Error) => {
154+
Logger.error(error);
155+
setTimeout(() => {
156+
exit(1);
157+
});
158+
});

0 commit comments

Comments
 (0)