Skip to content

Commit

Permalink
Add support for site installation in Okta VA integration
Browse files Browse the repository at this point in the history
  • Loading branch information
spastorelli committed Apr 10, 2024
1 parent e0c7c3c commit 851289c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 37 deletions.
1 change: 1 addition & 0 deletions integrations/va-okta/gitbook-manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ script: ./src/index.tsx
scopes:
- space:metadata:read
- space:visitor:auth
- site:visitor:auth
- space:content:read
organization: d8f63b60-89ae-11e7-8574-5927d48c4877
summary: |
Expand Down
114 changes: 77 additions & 37 deletions integrations/va-okta/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,27 @@ import {

const logger = Logger('okta.visitor-auth');

type OktaRuntimeEnvironment = RuntimeEnvironment<{}, OktaSpaceInstallationConfiguration>;
type OktaRuntimeEnvironment = RuntimeEnvironment<{}, OktaSiteOrSpaceInstallationConfiguration>;

type OktaRuntimeContext = RuntimeContext<OktaRuntimeEnvironment>;

type OktaSpaceInstallationConfiguration = {
type OktaSiteOrSpaceInstallationConfiguration = {
client_id?: string;
okta_domain?: string;
client_secret?: string;
};

type OktaState = OktaSpaceInstallationConfiguration;
type OktaState = OktaSiteOrSpaceInstallationConfiguration;

type OktaProps = {
installation: {
configuration?: IntegrationInstallationConfiguration;
};
spaceInstallation: {
configuration?: OktaSpaceInstallationConfiguration;
spaceInstallation?: {
configuration?: OktaSiteOrSpaceInstallationConfiguration;
};
siteInstallation?: {
configuration?: OktaSiteOrSpaceInstallationConfiguration;
};
};

Expand All @@ -39,39 +42,56 @@ export type OktaAction = { action: 'save.config' };
const configBlock = createComponent<OktaProps, OktaState, OktaAction, OktaRuntimeContext>({
componentId: 'config',
initialState: (props) => {
const siteOrSpaceInstallation = props.siteInstallation ?? props.spaceInstallation;
return {
client_id: props.spaceInstallation.configuration?.client_id?.toString() || '',
okta_domain: props.spaceInstallation.configuration?.okta_domain?.toString() || '',
client_secret: props.spaceInstallation.configuration?.client_secret?.toString() || '',
client_id: siteOrSpaceInstallation?.configuration?.client_id?.toString() || '',
okta_domain: siteOrSpaceInstallation?.configuration?.okta_domain?.toString() || '',
client_secret: siteOrSpaceInstallation?.configuration?.client_secret?.toString() || '',
};
},
action: async (element, action, context) => {
switch (action.action) {
case 'save.config':
const { api, environment } = context;
const spaceInstallation = environment.spaceInstallation;
const siteOrSpaceInstallation =
environment.siteInstallation ?? environment.spaceInstallation;

const configurationBody = {
...spaceInstallation.configuration,
...siteOrSpaceInstallation.configuration,
client_id: element.state.client_id,
client_secret: element.state.client_secret,
okta_domain: element.state.okta_domain,
};
await api.integrations.updateIntegrationSpaceInstallation(
spaceInstallation.integration,
spaceInstallation.installation,
spaceInstallation.space,
{
configuration: {
...configurationBody,
},
}
);
if ('site' in siteOrSpaceInstallation) {
await api.integrations.updateIntegrationSiteInstallation(
siteOrSpaceInstallation.integration,
siteOrSpaceInstallation.installation,
siteOrSpaceInstallation.site,
{
configuration: {
...configurationBody,
},
}
);
} else {
await api.integrations.updateIntegrationSpaceInstallation(
siteOrSpaceInstallation.integration,
siteOrSpaceInstallation.installation,
siteOrSpaceInstallation.space,
{
configuration: {
...configurationBody,
},
}
);
}
return element;
}
},
render: async (element, context) => {
const VACallbackURL = `${context.environment.spaceInstallation?.urls?.publicEndpoint}/visitor-auth/response`;
const siteOrSpaceInstallation =
context.environment.siteInstallation ?? context.environment.spaceInstallation;
const VACallbackURL = `${siteOrSpaceInstallation?.urls?.publicEndpoint}/visitor-auth/response`;
return (
<block>
<input
Expand Down Expand Up @@ -154,21 +174,39 @@ const configBlock = createComponent<OktaProps, OktaState, OktaAction, OktaRuntim
},
});

/**
* Get the published content (site or space) related urls.
*/
async function getPublishedContentUrls(context: OktaRuntimeContext) {
const organizationId = context.environment.installation?.target?.organization;
const siteOrSpaceInstallation =
context.environment.siteInstallation ?? context.environment.spaceInstallation;
const publishedContentData =
'site' in siteOrSpaceInstallation
? await context.api.orgs.getSiteById(organizationId, siteOrSpaceInstallation.site)
: await context.api.spaces.getSpaceById(siteOrSpaceInstallation.space);

return publishedContentData.data.urls;
}

const handleFetchEvent: FetchEventCallback<OktaRuntimeContext> = async (request, context) => {
const { environment } = context;
const installationURL = environment.spaceInstallation?.urls?.publicEndpoint;
const siteOrSpaceInstallation = environment.siteInstallation ?? environment.spaceInstallation;
const installationURL = siteOrSpaceInstallation?.urls?.publicEndpoint;
if (installationURL) {
const router = Router({
base: new URL(installationURL).pathname,
});

router.get('/visitor-auth/response', async (request) => {
if (context.environment.spaceInstallation?.space) {
const space = await context.api.spaces.getSpaceById(
context.environment.spaceInstallation?.space
);
const spaceData = space.data;
const privateKey = context.environment.signingSecrets.spaceInstallation;
if (
('site' in siteOrSpaceInstallation && siteOrSpaceInstallation.site) ||
('space' in siteOrSpaceInstallation && siteOrSpaceInstallation.space)
) {
const publishedContentUrls = await getPublishedContentUrls(context);
const privateKey =
context.environment.signingSecrets.siteInstallation ??
context.environment.signingSecrets.spaceInstallation;
let token;
try {
token = await sign(
Expand All @@ -181,9 +219,9 @@ const handleFetchEvent: FetchEventCallback<OktaRuntimeContext> = async (request,
});
}

const oktaDomain = environment.spaceInstallation?.configuration.okta_domain;
const clientId = environment.spaceInstallation?.configuration.client_id;
const clientSecret = environment.spaceInstallation?.configuration.client_secret;
const oktaDomain = siteOrSpaceInstallation?.configuration.okta_domain;
const clientId = siteOrSpaceInstallation?.configuration.client_id;
const clientSecret = siteOrSpaceInstallation?.configuration.client_secret;

if (clientId && clientSecret) {
const searchParams = new URLSearchParams({
Expand Down Expand Up @@ -211,13 +249,13 @@ const handleFetchEvent: FetchEventCallback<OktaRuntimeContext> = async (request,
const state = request.query.state.toString();
const location = state.substring(state.indexOf('-') + 1);
if (location) {
url = new URL(`${spaceData.urls?.published}${location}`);
url = new URL(`${publishedContentUrls?.published}${location}`);
url.searchParams.append('jwt_token', token);
} else {
url = new URL(spaceData.urls?.published);
url = new URL(publishedContentUrls?.published);
url.searchParams.append('jwt_token', token);
}
if (token && spaceData.urls?.published) {
if (token && publishedContentUrls?.published) {
return Response.redirect(url.toString());
} else {
return new Response(
Expand Down Expand Up @@ -271,9 +309,11 @@ export default createIntegration({
components: [configBlock],
fetch_visitor_authentication: async (event, context) => {
const { environment } = context;
const installationURL = environment.spaceInstallation?.urls?.publicEndpoint;
const oktaDomain = environment.spaceInstallation?.configuration.okta_domain;
const clientId = environment.spaceInstallation?.configuration.client_id;
const siteOrSpaceInstallation =
environment.siteInstallation ?? environment.spaceInstallation;
const installationURL = siteOrSpaceInstallation?.urls?.publicEndpoint;
const oktaDomain = siteOrSpaceInstallation?.configuration.okta_domain;
const clientId = siteOrSpaceInstallation?.configuration.client_id;
const location = event.location ? event.location : '';

const url = new URL(`https://${oktaDomain}/oauth2/v1/authorize`);
Expand Down

0 comments on commit 851289c

Please sign in to comment.