Skip to content

Commit ee00386

Browse files
authored
chore: add composite metadata bearer auth example (#286)
* chore: add composite metadata bearer auth example Signed-off-by: Kevin Viglucci <[email protected]> * chore: apply linting Signed-off-by: Kevin Viglucci <[email protected]> * chore: update license header at top of example Signed-off-by: Kevin Viglucci <[email protected]> --------- Signed-off-by: Kevin Viglucci <[email protected]>
1 parent ef1d12b commit ee00386

File tree

3 files changed

+440
-1
lines changed

3 files changed

+440
-1
lines changed

packages/rsocket-examples/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
"start-client-server-rxjs-messaging-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/RxjsMessagingCompositeMetadataRouteExample.ts",
2222
"start-client-server-rxjs-requester-responder": "ts-node -r tsconfig-paths/register src/rxjs/RxjsRequesterResponderExample.ts",
2323
"start-client-apollo-graphql": "ts-node -r tsconfig-paths/register src/graphql/apollo/client/example.ts",
24-
"start-client-server-apollo-graphql": "ts-node -r tsconfig-paths/register src/graphql/apollo/client-server/example.ts"
24+
"start-client-server-apollo-graphql": "ts-node -r tsconfig-paths/register src/graphql/apollo/client-server/example.ts",
25+
"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"
2527
},
2628
"dependencies": {
2729
"@apollo/client": "^3.5.10",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
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 makeConnector() {
31+
// NOTE: THIS EXAMPLE DOES NOT COVER TLS.
32+
// ALWAYS USE A SECURE CONNECTION SUCH AS TLS WHEN TRANSMITTING SENSITIVE INFORMATION SUCH AS AUTH TOKENS.
33+
return new RSocketConnector({
34+
transport: new TcpClientTransport({
35+
connectionOptions: {
36+
host: "127.0.0.1",
37+
port: 9090,
38+
},
39+
}),
40+
});
41+
}
42+
43+
function makeMetadata(bearerToken?: string, route?: string) {
44+
const map = new Map<WellKnownMimeType, Buffer>();
45+
46+
if (bearerToken) {
47+
map.set(
48+
MESSAGE_RSOCKET_AUTHENTICATION,
49+
encodeBearerAuthMetadata(Buffer.from(bearerToken))
50+
);
51+
}
52+
53+
if (route) {
54+
const encodedRoute = encodeRoute(route);
55+
map.set(MESSAGE_RSOCKET_ROUTING, encodedRoute);
56+
}
57+
58+
return encodeCompositeMetadata(map);
59+
}
60+
61+
async function requestResponse(
62+
rsocket: RSocket,
63+
compositeMetaData: Buffer,
64+
message: string = ""
65+
): Promise<Payload> {
66+
return new Promise((resolve, reject) => {
67+
return rsocket.requestResponse(
68+
{
69+
data: Buffer.from(message),
70+
metadata: compositeMetaData,
71+
},
72+
{
73+
onError: (e) => {
74+
reject(e);
75+
},
76+
onNext: (payload, isComplete) => {
77+
Logger.info(
78+
`payload[data: ${payload.data}; metadata: ${payload.metadata}]|${isComplete}`
79+
);
80+
resolve(payload);
81+
},
82+
onComplete: () => {},
83+
onExtension: () => {},
84+
}
85+
);
86+
});
87+
}
88+
89+
async function main() {
90+
const connector = makeConnector();
91+
92+
const rsocket = await connector.connect();
93+
94+
// NOTE: YOU SHOULD NEVER HARD CODE AN AUTH TOKEN IN A FILE IN THIS WAY. THIS IS PURELY FOR EXAMPLE PURPOSES.
95+
// The SHA1 HASH of rsocket-js-2024-10
96+
const exampleToken = "8a7d50f76ef86c75bd3563e55f8835515189dbff";
97+
98+
// this request SHOULD pass
99+
const echoResponse = await requestResponse(
100+
rsocket,
101+
makeMetadata(exampleToken, "EchoService.echo"),
102+
"Hello World"
103+
);
104+
Logger.info(`EchoService.echo response: ${echoResponse.data.toString()}`);
105+
106+
// this request will reject (unknown route)
107+
try {
108+
await requestResponse(
109+
rsocket,
110+
makeMetadata(exampleToken, "UnknownService.unknown"),
111+
"Hello World"
112+
);
113+
} catch (e) {
114+
Logger.error(`Expected error: ${e}`);
115+
}
116+
117+
// this request will reject (no routing data)
118+
try {
119+
await requestResponse(rsocket, makeMetadata(exampleToken), "Hello World");
120+
} catch (e) {
121+
Logger.error(`Expected error: ${e}`);
122+
}
123+
124+
// this request will reject (unknown auth token)
125+
try {
126+
await requestResponse(
127+
rsocket,
128+
makeMetadata("abc12345", "EchoService.echo"),
129+
"Hello World"
130+
);
131+
} catch (e) {
132+
Logger.error(`Expected error: ${e}`);
133+
}
134+
135+
// this request will reject no auth token)
136+
try {
137+
await requestResponse(
138+
rsocket,
139+
makeMetadata(null, "EchoService.echo"),
140+
"Hello World"
141+
);
142+
} catch (e) {
143+
Logger.error(`Expected error: ${e}`);
144+
}
145+
146+
const whoAmiResponse = await requestResponse(
147+
rsocket,
148+
makeMetadata(exampleToken, "AuthService.whoAmI")
149+
);
150+
Logger.info(`AuthService.whoAmI response: ${whoAmiResponse.data.toString()}`);
151+
}
152+
153+
main()
154+
.then(() => exit())
155+
.catch((error: Error) => {
156+
Logger.error(error);
157+
setTimeout(() => {
158+
exit(1);
159+
});
160+
});

0 commit comments

Comments
 (0)