Skip to content

Commit d622da7

Browse files
committed
Add azure integration. WIP.
1 parent 2c0a381 commit d622da7

File tree

6 files changed

+283
-0
lines changed

6 files changed

+283
-0
lines changed

integrations/va-azure/.eslintrc.json

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: VA-Azure
2+
title: VA Azure
3+
description: Visitor Authentication with Azure
4+
externalLinks:
5+
- label: Documentation
6+
url: https://www.gitbook.com/integrations/heap
7+
visibility: public
8+
script: ./src/index.ts
9+
# The following scope(s) are available only to GitBook Staff
10+
# See https://developer.gitbook.com/integrations/configurations#scopes
11+
scopes:
12+
- space:metadata:read
13+
- space:visitor:auth
14+
organization: w45sBUBc1JWE1ktYkQfI
15+
summary: |
16+
# Overview
17+
18+
categories:
19+
- analytics
20+
configurations:
21+
space:
22+
properties:
23+
client_id:
24+
type: string
25+
title: Client ID
26+
description: Client ID of your Azure app
27+
issuer_base_url:
28+
type: string
29+
title: Issuer Base URL
30+
description: Issuer Base URL of your Azure instance
31+
client_secret:
32+
type: string
33+
title: Client Secret
34+
description: The Client Secret of your Azure app
35+
36+
required:
37+
- client_id
38+
- issuer_base_url
39+
- client_secret

integrations/va-azure/package.json

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "@gitbook/integration-va-azure",
3+
"version": "0.0.1",
4+
"private": true,
5+
"dependencies": {
6+
"@gitbook/api": "*",
7+
"@gitbook/runtime": "*",
8+
"itty-router": "^4.0.14",
9+
"@tsndr/cloudflare-worker-jwt": "2.3.2"
10+
},
11+
"devDependencies": {
12+
"@gitbook/cli": "*"
13+
},
14+
"scripts": {
15+
"lint": "eslint ./src/**/*.ts",
16+
"typecheck": "tsc --noEmit",
17+
"publish-integrations-staging": "gitbook publish .",
18+
"publish-integrations": "gitbook publish ."
19+
}
20+
}

integrations/va-azure/src/index.ts

+200
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
import { sign } from '@tsndr/cloudflare-worker-jwt';
2+
import { Router } from 'itty-router';
3+
// import * as jwt from 'jsonwebtoken';
4+
5+
import {
6+
createIntegration,
7+
FetchEventCallback,
8+
Logger,
9+
RuntimeContext,
10+
RuntimeEnvironment,
11+
} from '@gitbook/runtime';
12+
13+
const logger = Logger('auth0.visitor-auth');
14+
15+
type Auth0RuntimeEnvironment = RuntimeEnvironment<
16+
{},
17+
{
18+
client_id?: string;
19+
issuer_base_url?: string;
20+
private_key?: string;
21+
client_secret?: string;
22+
}
23+
>;
24+
25+
// https://dev-qyd2bk185i3mltdi.us.auth0.com/authorize?response_type=code&client_id=xEyiJiDYHQ6JQrOVBvhgXQxhi2KY4cC8&redirect_uri=${installationURL}/visitor-auth/response&state=${location}`
26+
27+
type Auth0RuntimeContext = RuntimeContext<Auth0RuntimeEnvironment>;
28+
const handleFetchEvent: FetchEventCallback<Auth0RuntimeContext> = async (request, context) => {
29+
const { environment } = context;
30+
const installationURL = environment.spaceInstallation?.urls?.publicEndpoint;
31+
if (installationURL) {
32+
const router = Router({
33+
base: new URL(installationURL).pathname,
34+
});
35+
router.get('/visitor-auth', async (request) => {
36+
// eslint-disable-next-line no-console
37+
console.log('redirecting bby');
38+
logger.debug('Got a request');
39+
const location = request.query.location;
40+
const issuerBaseUrl = environment.spaceInstallation?.configuration.issuer_base_url;
41+
const clientId = environment.spaceInstallation?.configuration.client_id;
42+
43+
// return Response.json({ url_received: request.url, query: request.query });
44+
// return Response.json({ error: installationURL });
45+
try {
46+
return Response.redirect(
47+
`${issuerBaseUrl}/authorize?response_type=code&client_id=${clientId}&redirect_uri=${installationURL}/visitor-auth/response&state=${location}`
48+
);
49+
} catch (e) {
50+
return Response.json({ error: e.stack });
51+
}
52+
// return Response.redirect(`${installationURL}/visitor-auth/response`);
53+
});
54+
55+
router.get('/visitor-auth/response', async (request) => {
56+
// eslint-disable-next-line no-console
57+
console.log('yaaay');
58+
// redirect to published content URL
59+
if (context.environment.spaceInstallation?.space) {
60+
const space = await context.api.spaces.getSpaceById(
61+
context.environment.spaceInstallation?.space
62+
);
63+
// eslint-disable-next-line no-console
64+
console.log('space', space);
65+
// return Response.json({ url: request.url });
66+
// WORKS;
67+
const obj = space.data;
68+
const privateKey = context.environment.spaceInstallation.configuration.private_key;
69+
// eslint-disable-next-line no-console
70+
console.log('space', obj, privateKey);
71+
// return Response.json({ error: privateKey });
72+
// return Response.redirect('https://www.google.in');
73+
let token;
74+
try {
75+
token = await sign(
76+
{ exp: Math.floor(Date.now() / 1000) + 2 * (60 * 60) },
77+
privateKey ? privateKey : ''
78+
);
79+
} catch (e) {
80+
return Response.json({ error: e.stack });
81+
}
82+
// return Response.json({ query: request.query });
83+
const issuerBaseUrl = environment.spaceInstallation?.configuration.issuer_base_url;
84+
const clientId = environment.spaceInstallation?.configuration.client_id;
85+
const clientSecret = environment.spaceInstallation?.configuration.client_secret;
86+
if (clientId && clientSecret) {
87+
const searchParams = new URLSearchParams({
88+
grant_type: 'authorization_code',
89+
client_id: clientId,
90+
client_secret: clientSecret,
91+
code: `${request.query.code}`,
92+
redirect_uri: `${installationURL}/visitor-auth/response`,
93+
});
94+
// return Response.json({ searchParams });
95+
const url = `${issuerBaseUrl}/oauth/token/`;
96+
// return Response.json({ url });
97+
const resp: any = await fetch(url, {
98+
method: 'POST',
99+
headers: { 'content-type': 'application/x-www-form-urlencoded' },
100+
body: searchParams,
101+
})
102+
.then((response) => response.json())
103+
.catch((err) => {
104+
return Response.json({ err });
105+
});
106+
107+
if ('access_token' in resp) {
108+
let url;
109+
// return Response.json({ state: request.query.state });
110+
if (request.query.state) {
111+
url = `${obj.urls?.published}${request.query.state}/?jwt_token=${token}`;
112+
} else {
113+
url = `${obj.urls?.published}/?jwt_token=${token}`;
114+
}
115+
return Response.redirect(
116+
obj.urls?.published && token ? url : 'https://www.google.dk'
117+
);
118+
} else {
119+
return Response.json({
120+
Error: 'No Access Token found in the response from Auth0',
121+
});
122+
}
123+
} else {
124+
return Response.json({
125+
Error: 'Either ClientId or ClientSecret is missing',
126+
});
127+
}
128+
// // return Response.redirect('https://www.google.no');
129+
// return Response.redirect(
130+
// obj.urls?.published && token
131+
// ? `${obj.urls?.published}/?jwt_token=${token}`
132+
// : 'https://www.google.dk'
133+
// );
134+
}
135+
// eslint-disable-next-line no-console
136+
console.log('noting here');
137+
// return Response.redirect('https://www.google.com');
138+
});
139+
/**
140+
* Handle GitHub App webhook events
141+
*/
142+
143+
let response;
144+
try {
145+
response = await router.handle(request, context);
146+
} catch (error: any) {
147+
logger.error('error handling request', error);
148+
return new Response(error.message, {
149+
status: error.status || 500,
150+
});
151+
}
152+
153+
if (!response) {
154+
return new Response(`No route matching ${request.method} ${request.url}`, {
155+
status: 404,
156+
});
157+
}
158+
159+
return response;
160+
}
161+
};
162+
163+
export default createIntegration({
164+
fetch: handleFetchEvent,
165+
events: {
166+
space_installation_setup: async (event, context) => {
167+
// eslint-disable-next-line no-console
168+
console.log(
169+
'received event',
170+
context.environment.integration.name,
171+
event.installationId,
172+
event.spaceId
173+
);
174+
// eslint-disable-next-line no-console
175+
console.log(
176+
'context.environment.installation?.configuration.private_key',
177+
context.environment.installation?.configuration
178+
);
179+
if (!context.environment.spaceInstallation?.configuration.private_key) {
180+
const res = await context.api.integrations.updateIntegrationSpaceInstallation(
181+
context.environment.integration.name,
182+
event.installationId,
183+
event.spaceId,
184+
{
185+
configuration: {
186+
private_key: crypto.randomUUID(),
187+
// client_id:
188+
// context.environment.spaceInstallation?.configuration.client_id,
189+
// issuer_base_url:
190+
// context.environment.spaceInstallation?.configuration
191+
// .issuer_base_url,
192+
},
193+
}
194+
);
195+
// eslint-disable-next-line no-console
196+
console.log('recevied response', res.data);
197+
}
198+
},
199+
},
200+
});

integrations/va-azure/tsconfig.json

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "@gitbook/tsconfig/integration.json",
3+
"compilerOptions": {
4+
"strict": true,
5+
"lib": ["ESNext", "DOM"],
6+
"downlevelIteration": true
7+
}
8+
}

package-lock.json

+16
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)