mirror of https://github.com/boxyhq/jackson.git
Compare commits
23 Commits
79936ab34a
...
671c721869
Author | SHA1 | Date |
---|---|---|
Deepak Prabhakara | 671c721869 | |
Deepak Prabhakara | 55d8f14d40 | |
Aswin V | 9943a06ace | |
Deepak Prabhakara | f08025cc31 | |
Deepak Prabhakara | 63baf12a38 | |
Deepak Prabhakara | 668a1ba499 | |
Deepak Prabhakara | b6adc308f7 | |
ukrocks007 | c7272dae67 | |
Deepak Prabhakara | e3ead0cdc8 | |
Deepak Prabhakara | 0439806021 | |
Deepak Prabhakara | 003d602d7d | |
Deepak Prabhakara | d4951f6f20 | |
Deepak Prabhakara | 382f2d6245 | |
Deepak Prabhakara | 08a9b6a28c | |
Deepak Prabhakara | a74dcfd9bb | |
Deepak Prabhakara | 2483827a7a | |
Deepak Prabhakara | b2a6ae5e67 | |
Deepak Prabhakara | a4ff7cebb0 | |
Deepak Prabhakara | 7658fcfa8e | |
Deepak Prabhakara | e5b068cb9e | |
Deepak Prabhakara | eedb1c91e6 | |
Deepak Prabhakara | 3e33d7415b | |
Deepak Prabhakara | 0aaa8f5762 |
|
@ -111,7 +111,7 @@ jobs:
|
|||
ports:
|
||||
- '8000:8000'
|
||||
mocksaml:
|
||||
image: boxyhq/mock-saml:1.2.0
|
||||
image: boxyhq/mock-saml:1.3.9
|
||||
ports:
|
||||
- 4000:4000
|
||||
env:
|
||||
|
|
|
@ -40,7 +40,7 @@ export const Sidebar = ({ isOpen, setIsOpen }: SidebarProps) => {
|
|||
href: '/admin/sso-connection',
|
||||
text: t('enterprise_sso'),
|
||||
icon: SSOLogo,
|
||||
active: asPath.includes('/admin/sso-connection') || asPath.includes('/admin/federated-saml'),
|
||||
active: asPath.includes('/admin/sso-connection'),
|
||||
items: [
|
||||
{
|
||||
href: '/admin/sso-connection',
|
||||
|
@ -54,14 +54,22 @@ export const Sidebar = ({ isOpen, setIsOpen }: SidebarProps) => {
|
|||
active: asPath.includes('/admin/sso-connection/setup-link'),
|
||||
},
|
||||
{
|
||||
href: '/admin/federated-saml',
|
||||
text: t('saml_federation'),
|
||||
active: asPath.includes('/admin/federated-saml'),
|
||||
},
|
||||
{
|
||||
href: '/admin/sso-tracer',
|
||||
href: '/admin/sso-traces',
|
||||
text: t('bui-tracer-title'),
|
||||
active: asPath.includes('/admin/sso-tracer'),
|
||||
active: asPath.includes('/admin/sso-traces'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
href: '/admin/identity-federation',
|
||||
text: t('identity_federation'),
|
||||
icon: SSOLogo,
|
||||
active: asPath.includes('/admin/identity-federation'),
|
||||
items: [
|
||||
{
|
||||
href: '/admin/identity-federation',
|
||||
text: t('apps'),
|
||||
active: asPath.includes('/admin/identity-federation'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { test, expect } from '@playwright/test';
|
||||
import { SAMLFederationApp } from '@boxyhq/saml-jackson';
|
||||
import { IdentityFederationApp } from '@boxyhq/saml-jackson';
|
||||
|
||||
test.use({
|
||||
extraHTTPHeaders: {
|
||||
|
@ -17,10 +17,10 @@ const expectedApp = {
|
|||
acsUrl: 'https://boxyhq.com/acs',
|
||||
};
|
||||
|
||||
let app = {} as SAMLFederationApp;
|
||||
let app = {} as IdentityFederationApp;
|
||||
|
||||
test.beforeAll(async ({ request }) => {
|
||||
const response = await request.post('/api/v1/federated-saml', {
|
||||
const response = await request.post('/api/v1/identity-federation', {
|
||||
data: {
|
||||
...expectedApp,
|
||||
},
|
||||
|
@ -32,9 +32,9 @@ test.beforeAll(async ({ request }) => {
|
|||
expect(response.status()).toBe(201);
|
||||
});
|
||||
|
||||
test.describe('GET /api/v1/federated-saml', () => {
|
||||
test.describe('GET /api/v1/identity-federation', () => {
|
||||
test('Fetch app by id', async ({ request }) => {
|
||||
const response = await request.get(`/api/v1/federated-saml?id=${app?.id}`);
|
||||
const response = await request.get(`/api/v1/identity-federation?id=${app?.id}`);
|
||||
|
||||
const { data } = await response.json();
|
||||
|
||||
|
@ -45,7 +45,7 @@ test.describe('GET /api/v1/federated-saml', () => {
|
|||
|
||||
test('Fetch app by tenant and product', async ({ request }) => {
|
||||
const response = await request.get(
|
||||
`/api/v1/federated-saml?tenant=${app?.tenant}&product=${app?.product}`
|
||||
`/api/v1/identity-federation?tenant=${app?.tenant}&product=${app?.product}`
|
||||
);
|
||||
|
||||
const { data } = await response.json();
|
||||
|
@ -56,7 +56,7 @@ test.describe('GET /api/v1/federated-saml', () => {
|
|||
});
|
||||
|
||||
test('Fetch app by product', async ({ request }) => {
|
||||
const response = await request.get(`/api/v1/federated-saml/product?product=${app?.product}`);
|
||||
const response = await request.get(`/api/v1/identity-federation/product?product=${app?.product}`);
|
||||
|
||||
const { data } = await response.json();
|
||||
|
||||
|
@ -66,9 +66,9 @@ test.describe('GET /api/v1/federated-saml', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test.describe('PATCH /api/v1/federated-saml', () => {
|
||||
test.describe('PATCH /api/v1/identity-federation', () => {
|
||||
test('Update app by id', async ({ request }) => {
|
||||
const response = await request.patch(`/api/v1/federated-saml`, {
|
||||
const response = await request.patch(`/api/v1/identity-federation`, {
|
||||
data: {
|
||||
id: app?.id,
|
||||
name: 'Updated App',
|
||||
|
@ -86,7 +86,7 @@ test.describe('PATCH /api/v1/federated-saml', () => {
|
|||
});
|
||||
|
||||
test('Update app by tenant and product', async ({ request }) => {
|
||||
const response = await request.patch(`/api/v1/federated-saml`, {
|
||||
const response = await request.patch(`/api/v1/identity-federation`, {
|
||||
data: {
|
||||
id: app?.id,
|
||||
name: 'Updated App 2',
|
||||
|
@ -104,9 +104,9 @@ test.describe('PATCH /api/v1/federated-saml', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test.describe('DELETE /api/v1/federated-saml', () => {
|
||||
test.describe('DELETE /api/v1/identity-federation', () => {
|
||||
test('Delete app by id', async ({ request }) => {
|
||||
const response = await request.delete(`/api/v1/federated-saml?id=${app?.id}`);
|
||||
const response = await request.delete(`/api/v1/identity-federation?id=${app?.id}`);
|
||||
|
||||
const { data } = await response.json();
|
||||
|
||||
|
@ -115,7 +115,7 @@ test.describe('DELETE /api/v1/federated-saml', () => {
|
|||
expect(data).toMatchObject({});
|
||||
|
||||
// Confirm app is deleted
|
||||
const response2 = await request.get(`/api/v1/federated-saml?id=${app?.id}`);
|
||||
const response2 = await request.get(`/api/v1/identity-federation?id=${app?.id}`);
|
||||
|
||||
expect(response2.ok()).toBe(false);
|
||||
expect(response2.status()).toBe(404);
|
|
@ -0,0 +1,2 @@
|
|||
export { Portal } from './portal';
|
||||
export { SSOPage } from './sso-page';
|
|
@ -0,0 +1,20 @@
|
|||
import { Locator, Page, expect } from '@playwright/test';
|
||||
|
||||
export class Portal {
|
||||
userAvatarLocator: Locator;
|
||||
constructor(public readonly page: Page) {
|
||||
this.userAvatarLocator = this.page.getByTestId('user-avatar');
|
||||
}
|
||||
|
||||
async doCredentialsLogin() {
|
||||
await this.page.goto('/admin/auth/login');
|
||||
await this.page.getByPlaceholder('Email').fill('super@boxyhq.com');
|
||||
await this.page.getByPlaceholder('Password').fill('999login');
|
||||
await this.page.getByRole('button', { name: 'Sign In' }).click();
|
||||
}
|
||||
|
||||
async isLoggedIn() {
|
||||
// assert login state
|
||||
await expect(this.userAvatarLocator).toBeVisible();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
import type { Page, Locator } from '@playwright/test';
|
||||
import { adminPortalSSODefaults } from '@lib/env';
|
||||
|
||||
const ADMIN_PORTAL_TENANT = adminPortalSSODefaults.tenant;
|
||||
const ADMIN_PORTAL_PRODUCT = adminPortalSSODefaults.product;
|
||||
|
||||
const MOCKSAML_ORIGIN = process.env.MOCKSAML_ORIGIN || 'https://mocksaml.com';
|
||||
const MOCKSAML_SIGNIN_BUTTON_NAME = 'Sign In';
|
||||
|
||||
const MOCKLAB_ORIGIN = 'https://oauth.wiremockapi.cloud';
|
||||
const MOCKLAB_CLIENT_ID = 'mocklab_oauth2';
|
||||
const MOCKLAB_CLIENT_SECRET = 'mocklab_secret';
|
||||
const MOCKLAB_SIGNIN_BUTTON_NAME = 'Login';
|
||||
const MOCKLAB_DISCOVERY_ENDPOINT = 'https://oauth.wiremockapi.cloud/.well-known/openid-configuration';
|
||||
|
||||
export class SSOPage {
|
||||
private readonly createConnection: Locator;
|
||||
private readonly nameInput: Locator;
|
||||
private readonly tenantInput: Locator;
|
||||
private readonly productInput: Locator;
|
||||
private readonly redirectURLSInput: Locator;
|
||||
private readonly defaultRedirectURLInput: Locator;
|
||||
private readonly metadataUrlInput: Locator;
|
||||
private readonly oidcDiscoveryUrlInput: Locator;
|
||||
private readonly oidcClientIdInput: Locator;
|
||||
private readonly oidcClientSecretInput: Locator;
|
||||
private readonly saveConnection: Locator;
|
||||
private readonly deleteButton: Locator;
|
||||
private readonly confirmButton: Locator;
|
||||
private readonly toggleConnectionStatusCheckbox: Locator;
|
||||
private readonly toggleConnectionStatusLabel: Locator;
|
||||
private connections: string[];
|
||||
|
||||
constructor(public readonly page: Page) {
|
||||
this.connections = [];
|
||||
this.createConnection = this.page.getByTestId('create-connection');
|
||||
this.nameInput = this.page.getByLabel('Connection name (Optional)');
|
||||
this.tenantInput = this.page.getByLabel('Tenant');
|
||||
this.productInput = this.page.getByLabel('Product');
|
||||
this.redirectURLSInput = page
|
||||
.getByRole('group')
|
||||
.filter({ hasText: 'Allowed redirect URLs' })
|
||||
.locator(page.getByRole('textbox').first());
|
||||
this.defaultRedirectURLInput = this.page.getByLabel('Default redirect URL');
|
||||
this.metadataUrlInput = this.page.getByLabel('Metadata URL');
|
||||
this.oidcDiscoveryUrlInput = this.page.getByLabel('Well-known URL of OpenID Provider');
|
||||
this.oidcClientIdInput = this.page.getByLabel('Client ID');
|
||||
this.oidcClientSecretInput = this.page.getByLabel('Client Secret');
|
||||
this.saveConnection = this.page.getByRole('button', { name: /save/i });
|
||||
this.toggleConnectionStatusCheckbox = this.page.getByRole('checkbox', { name: 'Active' });
|
||||
this.toggleConnectionStatusLabel = this.page.locator('label').filter({ hasText: 'Active' });
|
||||
this.deleteButton = this.page.getByRole('button', { name: 'Delete' });
|
||||
this.confirmButton = this.page.getByRole('button', { name: 'Confirm' });
|
||||
}
|
||||
|
||||
async goto() {
|
||||
const url = new URL(this.page.url());
|
||||
if (url.pathname !== '/admin/sso-connection') {
|
||||
await this.page.goto('/admin/sso-connection');
|
||||
}
|
||||
}
|
||||
|
||||
async addSSOConnection({
|
||||
name,
|
||||
type = 'saml',
|
||||
baseURL,
|
||||
}: {
|
||||
name: string;
|
||||
type: 'saml' | 'oidc';
|
||||
baseURL: string;
|
||||
}) {
|
||||
const connectionIndex = this.connections.length + 1;
|
||||
const ssoName = `${name}-${connectionIndex}`;
|
||||
// Find the new connection button and click on it
|
||||
await this.createConnection.click();
|
||||
if (type === 'oidc') {
|
||||
// Toggle connection type to OIDC
|
||||
await this.page.getByLabel('OIDC').check();
|
||||
}
|
||||
// Fill the name for the connection
|
||||
await this.nameInput.fill(ssoName);
|
||||
// Fill the tenant for the connection
|
||||
await this.tenantInput.fill(ADMIN_PORTAL_TENANT);
|
||||
// Fill the product for the connection
|
||||
await this.productInput.fill(ADMIN_PORTAL_PRODUCT);
|
||||
// Fill the Allowed redirect URLs for the connection
|
||||
|
||||
await this.redirectURLSInput.fill(baseURL!);
|
||||
// Fill the default redirect URLs for the connection
|
||||
await this.defaultRedirectURLInput.fill(`${baseURL}/admin/auth/idp-login`);
|
||||
if (type === 'saml') {
|
||||
// Enter the metadata url for mocksaml in the form
|
||||
await this.metadataUrlInput.fill(`${MOCKSAML_ORIGIN}/api/namespace/${ssoName}/saml/metadata`);
|
||||
}
|
||||
if (type === 'oidc') {
|
||||
// Enter the OIDC client credentials for mocklab in the form
|
||||
await this.oidcClientIdInput.fill(`${MOCKLAB_CLIENT_ID}-${connectionIndex}`);
|
||||
await this.oidcClientSecretInput.fill(`${MOCKLAB_CLIENT_SECRET}-${connectionIndex}`);
|
||||
// Enter the OIDC discovery url for mocklab in the form
|
||||
await this.oidcDiscoveryUrlInput.fill(MOCKLAB_DISCOVERY_ENDPOINT);
|
||||
}
|
||||
// submit the form
|
||||
await this.saveConnection.click();
|
||||
this.connections = [...this.connections, ssoName];
|
||||
}
|
||||
|
||||
async gotoEditView(name: string) {
|
||||
await this.goto();
|
||||
const editButton = this.page.getByText(name).locator('xpath=..').getByLabel('Edit');
|
||||
await editButton.click();
|
||||
}
|
||||
|
||||
async toggleConnectionStatus(newStatus: boolean) {
|
||||
const isChecked = await this.toggleConnectionStatusCheckbox.isChecked();
|
||||
if (isChecked && !newStatus) {
|
||||
await this.toggleConnectionStatusLabel.click();
|
||||
await this.confirmButton.click();
|
||||
} else if (!isChecked && newStatus) {
|
||||
await this.toggleConnectionStatusLabel.click();
|
||||
await this.confirmButton.click();
|
||||
}
|
||||
}
|
||||
|
||||
async updateSSOConnection({ name, url, newStatus }: { name: string; url: string; newStatus?: boolean }) {
|
||||
await this.gotoEditView(name);
|
||||
await this.redirectURLSInput.fill(url);
|
||||
await this.saveConnection.click();
|
||||
if (typeof newStatus === 'boolean') {
|
||||
await this.gotoEditView(name);
|
||||
await this.toggleConnectionStatus(newStatus);
|
||||
}
|
||||
}
|
||||
|
||||
async deleteSSOConnection(name: string) {
|
||||
await this.gotoEditView(name);
|
||||
// click the delete and confirm deletion
|
||||
await this.deleteButton.click();
|
||||
await this.confirmButton.click();
|
||||
}
|
||||
|
||||
async deleteAllSSOConnections() {
|
||||
let _connection;
|
||||
while ((_connection = this.connections.shift())) {
|
||||
await this.deleteSSOConnection(_connection);
|
||||
}
|
||||
}
|
||||
|
||||
async logout() {
|
||||
const userAvatarLocator = this.page.getByTestId('user-avatar');
|
||||
// Logout from the magic link authentication
|
||||
await userAvatarLocator.click();
|
||||
await this.page.getByTestId('logout').click();
|
||||
}
|
||||
|
||||
async signInWithSSO() {
|
||||
await this.page.getByTestId('sso-login-button').click();
|
||||
}
|
||||
|
||||
async selectIdP(name: string) {
|
||||
const idpSelectionTitle = 'Select an Identity Provider to continue';
|
||||
await this.page.getByText(idpSelectionTitle).waitFor();
|
||||
await this.page.getByRole('button', { name }).click();
|
||||
}
|
||||
|
||||
async signInWithMockSAML() {
|
||||
// Perform sign in at mocksaml
|
||||
await this.page.waitForURL((url) => url.origin === MOCKSAML_ORIGIN);
|
||||
await this.page.getByPlaceholder('jackson').fill('bob');
|
||||
await this.page.getByRole('button', { name: MOCKSAML_SIGNIN_BUTTON_NAME }).click();
|
||||
}
|
||||
|
||||
async signInWithMockLab() {
|
||||
// Perform sign in at mocklab
|
||||
await this.page.waitForURL((url) => url.origin === MOCKLAB_ORIGIN);
|
||||
await this.page.getByPlaceholder('yours@example.com').fill('bob@oidc.com');
|
||||
await this.page.getByRole('button', { name: MOCKLAB_SIGNIN_BUTTON_NAME }).click();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
import { test as baseTest, expect } from '@playwright/test';
|
||||
import { Portal, SSOPage } from 'e2e/support/fixtures';
|
||||
|
||||
type MyFixtures = {
|
||||
ssoPage: SSOPage;
|
||||
portal: Portal;
|
||||
};
|
||||
|
||||
export const test = baseTest.extend<MyFixtures>({
|
||||
portal: async ({ page }, use) => {
|
||||
const portal = new Portal(page);
|
||||
await use(portal);
|
||||
},
|
||||
ssoPage: async ({ page, portal }, use) => {
|
||||
const ssoPage = new SSOPage(page);
|
||||
await ssoPage.goto();
|
||||
await use(ssoPage);
|
||||
await portal.doCredentialsLogin();
|
||||
await portal.isLoggedIn();
|
||||
await ssoPage.deleteAllSSOConnections();
|
||||
},
|
||||
});
|
||||
|
||||
test('OAuth2 wrapper + SAML provider + wrong redirectUrl', async ({ ssoPage, page, baseURL }, testInfo) => {
|
||||
const ssoName = `saml-${testInfo.workerIndex}`;
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'saml', baseURL: baseURL! });
|
||||
// check if the first added connection appears in the connection list
|
||||
await expect(page.getByText(`${ssoName}-1`)).toBeVisible();
|
||||
await ssoPage.updateSSOConnection({
|
||||
name: `${ssoName}-1`,
|
||||
url: 'https://invalid-url.com',
|
||||
});
|
||||
// Logout of magic link login
|
||||
await ssoPage.logout();
|
||||
await ssoPage.signInWithSSO();
|
||||
// Wait for browser to redirect to error page
|
||||
await page.waitForURL((url) => url.origin === baseURL && url.pathname === '/error');
|
||||
// Assert error text
|
||||
await expect(page.getByText(`SSO error: Redirect URL is not allowed.`)).toBeVisible();
|
||||
});
|
||||
|
||||
test('OAuth2 wrapper + SAML provider + inactive connection', async ({ ssoPage, page, baseURL }, testInfo) => {
|
||||
const ssoName = `saml-${testInfo.workerIndex}`;
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'saml', baseURL: baseURL! });
|
||||
// check if the first added connection appears in the connection list
|
||||
await expect(page.getByText(`${ssoName}-1`)).toBeVisible();
|
||||
await ssoPage.updateSSOConnection({
|
||||
name: `${ssoName}-1`,
|
||||
url: baseURL!,
|
||||
newStatus: false,
|
||||
});
|
||||
// Confirm connection label inactive is displayed
|
||||
await expect(
|
||||
page.getByText(`${ssoName}-1`).locator('xpath=..').getByRole('cell', { name: 'Inactive', exact: true })
|
||||
).toBeVisible();
|
||||
// Logout and try to sign in with connection
|
||||
// Logout of magic link login
|
||||
await ssoPage.logout();
|
||||
await ssoPage.signInWithSSO();
|
||||
// Wait for browser to redirect to error page
|
||||
await page.waitForURL((url) => url.origin === baseURL && url.pathname === '/error');
|
||||
// Assert error text
|
||||
await expect(
|
||||
page.getByText('SSO error: SSO connection is deactivated. Please contact your administrator.')
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('OAuth2 wrapper + OIDC provider + wrong redirectUrl', async ({ ssoPage, page, baseURL }, testInfo) => {
|
||||
const ssoName = `oidc-${testInfo.workerIndex}`;
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'oidc', baseURL: baseURL! });
|
||||
// check if the oidc connection appears in the connection list
|
||||
await expect(page.getByText(`${ssoName}-1`)).toBeVisible();
|
||||
await ssoPage.updateSSOConnection({
|
||||
name: `${ssoName}-1`,
|
||||
url: 'https://invalid-url.com',
|
||||
});
|
||||
// Logout of magic link login
|
||||
await ssoPage.logout();
|
||||
await ssoPage.signInWithSSO();
|
||||
// Wait for browser to redirect to error page
|
||||
await page.waitForURL((url) => url.origin === baseURL && url.pathname === '/error');
|
||||
// Assert error text
|
||||
await expect(page.getByText('SSO error: Redirect URL is not allowed.')).toBeVisible();
|
||||
});
|
||||
|
||||
test('OAuth2 wrapper + OIDC provider + inactive connection', async ({ ssoPage, page, baseURL }, testInfo) => {
|
||||
const ssoName = `oidc-${testInfo.workerIndex}`;
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'oidc', baseURL: baseURL! });
|
||||
// check if the oidc connection appears in the connection list
|
||||
await expect(page.getByText(`${ssoName}-1`)).toBeVisible();
|
||||
await ssoPage.updateSSOConnection({
|
||||
name: `${ssoName}-1`,
|
||||
url: baseURL!,
|
||||
newStatus: false,
|
||||
});
|
||||
// Confirm connection label inactive is displayed
|
||||
await expect(
|
||||
page.getByText(`${ssoName}-1`).locator('xpath=..').getByRole('cell', { name: 'Inactive', exact: true })
|
||||
).toBeVisible();
|
||||
// Logout and try to sign in with connection
|
||||
// Logout of magic link login
|
||||
await ssoPage.logout();
|
||||
await ssoPage.signInWithSSO();
|
||||
// Wait for browser to redirect to error page
|
||||
await page.waitForURL((url) => url.origin === baseURL && url.pathname === '/error');
|
||||
// Assert error text
|
||||
await expect(
|
||||
page.getByText('SSO error: SSO connection is deactivated. Please contact your administrator.')
|
||||
).toBeVisible();
|
||||
});
|
|
@ -0,0 +1,57 @@
|
|||
import { test as baseTest, expect } from '@playwright/test';
|
||||
import { Portal, SSOPage } from 'e2e/support/fixtures';
|
||||
|
||||
type MyFixtures = {
|
||||
ssoPage: SSOPage;
|
||||
portal: Portal;
|
||||
};
|
||||
|
||||
export const test = baseTest.extend<MyFixtures>({
|
||||
ssoPage: async ({ page, baseURL }, use, testInfo) => {
|
||||
const ssoPage = new SSOPage(page);
|
||||
const ssoName = `oidc-${testInfo.workerIndex}`;
|
||||
await ssoPage.goto();
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'oidc', baseURL: baseURL! });
|
||||
await use(ssoPage);
|
||||
await ssoPage.deleteAllSSOConnections();
|
||||
},
|
||||
portal: async ({ page }, use) => {
|
||||
const portal = new Portal(page);
|
||||
await use(portal);
|
||||
},
|
||||
});
|
||||
|
||||
test('OAuth2 wrapper + OIDC provider', async ({ ssoPage, portal, page, baseURL }, testInfo) => {
|
||||
// check if the first added connection appears in the connection list
|
||||
await expect(page.getByText(`oidc-${testInfo.workerIndex}-1`)).toBeVisible();
|
||||
// Logout of magic link login
|
||||
await ssoPage.logout();
|
||||
await ssoPage.signInWithSSO();
|
||||
// Login using MockLab
|
||||
await ssoPage.signInWithMockLab();
|
||||
// Wait for browser to redirect back to admin portal
|
||||
await page.waitForURL((url) => url.origin === baseURL);
|
||||
// Assert logged in state
|
||||
await portal.isLoggedIn();
|
||||
});
|
||||
|
||||
test('OAuth2 wrapper + 2 OIDC providers', async ({ ssoPage, portal, page, baseURL }, testInfo) => {
|
||||
const ssoName = `oidc-${testInfo.workerIndex}`;
|
||||
// check if the first added connection appears in the connection list
|
||||
await expect(page.getByText(`${ssoName}-1`)).toBeVisible();
|
||||
// Add second OIDC connection
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'oidc', baseURL: baseURL! });
|
||||
// check if the second added connection appears in the connection list
|
||||
await expect(page.getByText(`${ssoName}-2`)).toBeVisible();
|
||||
// Logout of magic link login
|
||||
await ssoPage.logout();
|
||||
// Login using MockLab
|
||||
await ssoPage.signInWithSSO();
|
||||
// Select IdP from selection screen
|
||||
await ssoPage.selectIdP(`${ssoName}-2`);
|
||||
await ssoPage.signInWithMockLab();
|
||||
// Wait for browser to redirect back to admin portal
|
||||
await page.waitForURL((url) => url.origin === baseURL);
|
||||
// Assert logged in state
|
||||
await portal.isLoggedIn();
|
||||
});
|
|
@ -0,0 +1,62 @@
|
|||
import { test as baseTest, expect } from '@playwright/test';
|
||||
import { Portal, SSOPage } from 'e2e/support/fixtures';
|
||||
|
||||
type MyFixtures = {
|
||||
ssoPage: SSOPage;
|
||||
portal: Portal;
|
||||
};
|
||||
|
||||
export const test = baseTest.extend<MyFixtures>({
|
||||
ssoPage: async ({ page, baseURL }, use, testInfo) => {
|
||||
const ssoPage = new SSOPage(page);
|
||||
let ssoName = `saml-${testInfo.workerIndex}`;
|
||||
await ssoPage.goto();
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'saml', baseURL: baseURL! });
|
||||
await ssoPage.goto();
|
||||
ssoName = `oidc-${testInfo.workerIndex}`;
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'oidc', baseURL: baseURL! });
|
||||
await use(ssoPage);
|
||||
await ssoPage.deleteAllSSOConnections();
|
||||
},
|
||||
portal: async ({ page }, use) => {
|
||||
const portal = new Portal(page);
|
||||
await use(portal);
|
||||
},
|
||||
});
|
||||
|
||||
test('OAuth2 wrapper + SAML provider + OIDC provider', async ({
|
||||
ssoPage,
|
||||
portal,
|
||||
page,
|
||||
baseURL,
|
||||
}, testInfo) => {
|
||||
// check if the first added connection appears in the connection list
|
||||
await expect(page.getByText(`saml-${testInfo.workerIndex}-1`)).toBeVisible();
|
||||
// check if the second added connection appears in the connection list
|
||||
await expect(page.getByText(`oidc-${testInfo.workerIndex}-2`)).toBeVisible();
|
||||
// Logout of magic link login
|
||||
await ssoPage.logout();
|
||||
// Login using MockSAML
|
||||
await ssoPage.signInWithSSO();
|
||||
// Select IdP from selection screen
|
||||
await ssoPage.selectIdP(`saml-${testInfo.workerIndex}-1`);
|
||||
// Login using MockSAML
|
||||
await ssoPage.signInWithMockSAML();
|
||||
// Wait for browser to redirect back to admin portal
|
||||
await page.waitForURL((url) => url.origin === baseURL);
|
||||
// Assert logged in state
|
||||
await portal.isLoggedIn();
|
||||
|
||||
// Logout of SAML login
|
||||
await ssoPage.logout();
|
||||
// Login using MockLab
|
||||
await ssoPage.signInWithSSO();
|
||||
// Select IdP from selection screen
|
||||
await ssoPage.selectIdP(`oidc-${testInfo.workerIndex}-2`);
|
||||
// Login using MockLab
|
||||
await ssoPage.signInWithMockLab();
|
||||
// Wait for browser to redirect back to admin portal
|
||||
await page.waitForURL((url) => url.origin === baseURL);
|
||||
// Assert logged in state
|
||||
await portal.isLoggedIn();
|
||||
});
|
|
@ -0,0 +1,57 @@
|
|||
import { test as baseTest, expect } from '@playwright/test';
|
||||
import { Portal, SSOPage } from 'e2e/support/fixtures';
|
||||
|
||||
type MyFixtures = {
|
||||
ssoPage: SSOPage;
|
||||
portal: Portal;
|
||||
};
|
||||
|
||||
export const test = baseTest.extend<MyFixtures>({
|
||||
ssoPage: async ({ page, baseURL }, use, testInfo) => {
|
||||
const ssoPage = new SSOPage(page);
|
||||
const ssoName = `saml-${testInfo.workerIndex}`;
|
||||
await ssoPage.goto();
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'saml', baseURL: baseURL! });
|
||||
await use(ssoPage);
|
||||
await ssoPage.deleteAllSSOConnections();
|
||||
},
|
||||
portal: async ({ page }, use) => {
|
||||
const portal = new Portal(page);
|
||||
await use(portal);
|
||||
},
|
||||
});
|
||||
|
||||
test('OAuth2 wrapper + SAML provider', async ({ ssoPage, portal, page, baseURL }, testInfo) => {
|
||||
// check if the first added connection appears in the connection list
|
||||
await expect(page.getByText(`saml-${testInfo.workerIndex}-1`)).toBeVisible();
|
||||
// Logout of magic link login
|
||||
await ssoPage.logout();
|
||||
await ssoPage.signInWithSSO();
|
||||
// Login using MockSAML
|
||||
await ssoPage.signInWithMockSAML();
|
||||
// Wait for browser to redirect back to admin portal
|
||||
await page.waitForURL((url) => url.origin === baseURL);
|
||||
// Assert logged in state
|
||||
await portal.isLoggedIn();
|
||||
});
|
||||
|
||||
test('OAuth2 wrapper + 2 SAML providers', async ({ ssoPage, portal, page, baseURL }, testInfo) => {
|
||||
const ssoName = `saml-${testInfo.workerIndex}`;
|
||||
// check if the first added connection appears in the connection list
|
||||
await expect(page.getByText(`${ssoName}-1`)).toBeVisible();
|
||||
// Add second SAML connection
|
||||
await ssoPage.addSSOConnection({ name: ssoName, type: 'saml', baseURL: baseURL! });
|
||||
// check if the second added connection appears in the connection list
|
||||
await expect(page.getByText(`${ssoName}-2`)).toBeVisible();
|
||||
// Logout of magic link login
|
||||
await ssoPage.logout();
|
||||
// Login using MockSAML
|
||||
await ssoPage.signInWithSSO();
|
||||
// Select IdP from selection screen
|
||||
await ssoPage.selectIdP(`${ssoName}-2`);
|
||||
await ssoPage.signInWithMockSAML();
|
||||
// Wait for browser to redirect back to admin portal
|
||||
await page.waitForURL((url) => url.origin === baseURL);
|
||||
// Assert logged in state
|
||||
await portal.isLoggedIn();
|
||||
});
|
|
@ -75,7 +75,7 @@ test.describe('Admin Portal SSO - SAML', () => {
|
|||
test('delete the SAML SSO connection', async ({ page }) => {
|
||||
await page.goto('/admin/settings');
|
||||
// select the row of the connection list table, then locate the edit button
|
||||
const editButton = page.getByText(TEST_SAML_SSO_CONNECTION_NAME).locator('..').getByLabel('Edit');
|
||||
const editButton = page.getByText(TEST_SAML_SSO_CONNECTION_NAME).locator('xpath=..').getByLabel('Edit');
|
||||
await editButton.click();
|
||||
// click the delete and confirm deletion
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
|
@ -138,7 +138,7 @@ test.describe('Admin Portal SSO - OIDC', () => {
|
|||
await page.getByTestId('logout').click();
|
||||
// Click on login with sso button
|
||||
await page.getByTestId('sso-login-button').click();
|
||||
// Perform sign in at mocksaml
|
||||
// Perform sign in at mocklab
|
||||
await page.waitForURL((url) => url.origin === MOCKLAB_ORIGIN);
|
||||
await page.getByPlaceholder('yours@example.com').fill('bob@oidc.com');
|
||||
await page.getByRole('button', { name: MOCKLAB_SIGNIN_BUTTON_NAME }).click();
|
||||
|
|
|
@ -18,19 +18,19 @@ const UpdateApp = ({ hasValidLicense }: { hasValidLicense: boolean }) => {
|
|||
|
||||
return (
|
||||
<div className='space-y-4'>
|
||||
<LinkBack href='/admin/federated-saml' />
|
||||
<LinkBack href='/admin/identity-federation' />
|
||||
<EditFederatedSAMLApp
|
||||
urls={{
|
||||
getApp: `/api/admin/federated-saml/${id}`,
|
||||
updateApp: `/api/admin/federated-saml/${id}`,
|
||||
deleteApp: `/api/admin/federated-saml/${id}`,
|
||||
getApp: `/api/admin/identity-federation/${id}`,
|
||||
updateApp: `/api/admin/identity-federation/${id}`,
|
||||
deleteApp: `/api/admin/identity-federation/${id}`,
|
||||
}}
|
||||
onUpdate={() => {
|
||||
successToast(t('saml_federation_update_success'));
|
||||
}}
|
||||
onDelete={() => {
|
||||
successToast(t('saml_federation_delete_success'));
|
||||
router.push('/admin/federated-saml');
|
||||
router.push('/admin/identity-federation');
|
||||
}}
|
||||
onError={(error) => {
|
||||
errorToast(error.message);
|
|
@ -9,10 +9,10 @@ const AppsList = ({ hasValidLicense }: { hasValidLicense: boolean }) => {
|
|||
|
||||
return (
|
||||
<FederatedSAMLApps
|
||||
urls={{ getApps: '/api/admin/federated-saml' }}
|
||||
onEdit={(app) => router.push(`/admin/federated-saml/${app.id}/edit`)}
|
||||
urls={{ getApps: '/api/admin/identity-federation' }}
|
||||
onEdit={(app) => router.push(`/admin/identity-federation/${app.id}/edit`)}
|
||||
actions={{
|
||||
newApp: '/admin/federated-saml/new',
|
||||
newApp: '/admin/identity-federation/new',
|
||||
samlConfiguration: '/.well-known/idp-configuration',
|
||||
oidcConfiguration: '/.well-known/openid-configuration',
|
||||
}}
|
|
@ -1,12 +1,12 @@
|
|||
import Link from 'next/link';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import type { SAMLFederationAppWithMetadata } from '@boxyhq/saml-jackson';
|
||||
import type { IdentityFederationAppWithMetadata } from '@boxyhq/saml-jackson';
|
||||
import { Toaster } from '@components/Toaster';
|
||||
import { InputWithCopyButton, CopyToClipboardButton, LinkOutline } from '@boxyhq/internal-ui';
|
||||
import LicenseRequired from '@components/LicenseRequired';
|
||||
|
||||
type MetadataProps = {
|
||||
metadata: Pick<SAMLFederationAppWithMetadata, 'metadata'>['metadata'];
|
||||
metadata: Pick<IdentityFederationAppWithMetadata, 'metadata'>['metadata'];
|
||||
hasValidLicense: boolean;
|
||||
};
|
||||
|
|
@ -16,12 +16,12 @@ const NewApp = ({ hasValidLicense, samlAudience }: { hasValidLicense: boolean; s
|
|||
|
||||
return (
|
||||
<div className='space-y-4'>
|
||||
<LinkBack href='/admin/federated-saml' />
|
||||
<LinkBack href='/admin/identity-federation' />
|
||||
<NewFederatedSAMLApp
|
||||
urls={{ createApp: '/api/admin/federated-saml' }}
|
||||
urls={{ createApp: '/api/admin/identity-federation' }}
|
||||
onSuccess={(data) => {
|
||||
successToast(t('saml_federation_new_success'));
|
||||
router.replace(`/admin/federated-saml/${data.id}/edit`);
|
||||
router.replace(`/admin/identity-federation/${data.id}/edit`);
|
||||
}}
|
||||
onError={(error) => {
|
||||
errorToast(error.message);
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +0,0 @@
|
|||
export { NewFederatedSAMLApp } from './NewFederatedSAMLApp';
|
||||
export { EditFederatedSAMLApp } from './EditFederatedSAMLApp';
|
||||
export { FederatedSAMLApps } from './FederatedSAMLApps';
|
|
@ -1,6 +1,6 @@
|
|||
import { useState } from 'react';
|
||||
import { Button } from 'react-daisyui';
|
||||
import type { SAMLFederationApp } from '../types';
|
||||
import type { IdentityFederationApp } from '../types';
|
||||
import TagsInput from 'react-tagsinput';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useFormik } from 'formik';
|
||||
|
@ -13,7 +13,7 @@ import { ItemList } from '@boxyhq/react-ui/shared';
|
|||
import { CopyToClipboardButton } from '../shared/InputWithCopyButton';
|
||||
import { IconButton } from '../shared/IconButton';
|
||||
|
||||
type EditApp = Pick<SAMLFederationApp, 'name' | 'acsUrl' | 'tenants' | 'redirectUrl'>;
|
||||
type EditApp = Pick<IdentityFederationApp, 'name' | 'acsUrl' | 'tenants' | 'redirectUrl'>;
|
||||
|
||||
export const Edit = ({
|
||||
app,
|
||||
|
@ -22,9 +22,9 @@ export const Edit = ({
|
|||
onUpdate,
|
||||
excludeFields,
|
||||
}: {
|
||||
app: SAMLFederationApp;
|
||||
app: IdentityFederationApp;
|
||||
urls: { patch: string };
|
||||
onUpdate?: (data: SAMLFederationApp) => void;
|
||||
onUpdate?: (data: IdentityFederationApp) => void;
|
||||
onError?: (error: Error) => void;
|
||||
excludeFields?: 'product'[];
|
||||
}) => {
|
|
@ -1,12 +1,12 @@
|
|||
import { Button } from 'react-daisyui';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import type { SAMLFederationApp } from '../types';
|
||||
import type { IdentityFederationApp } from '../types';
|
||||
import { useFormik } from 'formik';
|
||||
import { defaultHeaders } from '../utils';
|
||||
import { Card } from '../shared';
|
||||
import { AttributesMapping } from './AttributesMapping';
|
||||
|
||||
type Mappings = Pick<SAMLFederationApp, 'mappings'>;
|
||||
type Mappings = Pick<IdentityFederationApp, 'mappings'>;
|
||||
|
||||
export const EditAttributesMapping = ({
|
||||
app,
|
||||
|
@ -14,9 +14,9 @@ export const EditAttributesMapping = ({
|
|||
onUpdate,
|
||||
onError,
|
||||
}: {
|
||||
app: SAMLFederationApp;
|
||||
app: IdentityFederationApp;
|
||||
urls: { patch: string };
|
||||
onUpdate?: (data: SAMLFederationApp) => void;
|
||||
onUpdate?: (data: IdentityFederationApp) => void;
|
||||
onError?: (error: Error) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation('common');
|
|
@ -1,11 +1,11 @@
|
|||
import { Button } from 'react-daisyui';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import type { SAMLFederationApp } from '../types';
|
||||
import type { IdentityFederationApp } from '../types';
|
||||
import { useFormik } from 'formik';
|
||||
import { defaultHeaders } from '../utils';
|
||||
import { Card } from '../shared';
|
||||
|
||||
type Branding = Pick<SAMLFederationApp, 'logoUrl' | 'faviconUrl' | 'primaryColor'>;
|
||||
type Branding = Pick<IdentityFederationApp, 'logoUrl' | 'faviconUrl' | 'primaryColor'>;
|
||||
|
||||
export const EditBranding = ({
|
||||
app,
|
||||
|
@ -13,9 +13,9 @@ export const EditBranding = ({
|
|||
onUpdate,
|
||||
onError,
|
||||
}: {
|
||||
app: SAMLFederationApp;
|
||||
app: IdentityFederationApp;
|
||||
urls: { patch: string };
|
||||
onUpdate?: (data: SAMLFederationApp) => void;
|
||||
onUpdate?: (data: IdentityFederationApp) => void;
|
||||
onError?: (error: Error) => void;
|
||||
}) => {
|
||||
const { t } = useTranslation('common');
|
|
@ -1,5 +1,5 @@
|
|||
import useSWR from 'swr';
|
||||
import type { SAMLFederationApp } from '../types';
|
||||
import type { IdentityFederationApp } from '../types';
|
||||
import { EditBranding } from './EditBranding';
|
||||
import { Edit } from './Edit';
|
||||
import { EditAttributesMapping } from './EditAttributesMapping';
|
||||
|
@ -9,7 +9,7 @@ import { useEffect, useState } from 'react';
|
|||
import { defaultHeaders, fetcher } from '../utils';
|
||||
import { PageHeader } from '../shared';
|
||||
|
||||
export const EditFederatedSAMLApp = ({
|
||||
export const EditIdentityFederationApp = ({
|
||||
urls,
|
||||
onError,
|
||||
onUpdate,
|
||||
|
@ -17,7 +17,7 @@ export const EditFederatedSAMLApp = ({
|
|||
excludeFields,
|
||||
}: {
|
||||
urls: { getApp: string; updateApp: string; deleteApp: string };
|
||||
onUpdate?: (data: SAMLFederationApp) => void;
|
||||
onUpdate?: (data: IdentityFederationApp) => void;
|
||||
onError?: (error: Error) => void;
|
||||
onDelete?: () => void;
|
||||
excludeFields?: 'product'[];
|
||||
|
@ -25,7 +25,7 @@ export const EditFederatedSAMLApp = ({
|
|||
const { t } = useTranslation('common');
|
||||
const [delModalVisible, setDelModalVisible] = useState(false);
|
||||
|
||||
const { data, isLoading, error, mutate } = useSWR<{ data: SAMLFederationApp }>(urls.getApp, fetcher);
|
||||
const { data, isLoading, error, mutate } = useSWR<{ data: IdentityFederationApp }>(urls.getApp, fetcher);
|
||||
|
||||
useEffect(() => {
|
||||
if (error) {
|
|
@ -11,7 +11,7 @@ import {
|
|||
ButtonPrimary,
|
||||
} from '../shared';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import type { SAMLFederationApp } from '../types';
|
||||
import type { IdentityFederationApp } from '../types';
|
||||
import PencilIcon from '@heroicons/react/24/outline/PencilIcon';
|
||||
import { TableBodyType } from '../shared/Table';
|
||||
import { pageLimit } from '../shared/Pagination';
|
||||
|
@ -19,9 +19,9 @@ import { usePaginate } from '../hooks';
|
|||
import { useRouter } from '../hooks';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
type ExcludeFields = keyof Pick<SAMLFederationApp, 'product'>;
|
||||
type ExcludeFields = keyof Pick<IdentityFederationApp, 'product'>;
|
||||
|
||||
export const FederatedSAMLApps = ({
|
||||
export const IdentityFederationApps = ({
|
||||
urls,
|
||||
excludeFields,
|
||||
onEdit,
|
||||
|
@ -30,9 +30,9 @@ export const FederatedSAMLApps = ({
|
|||
}: {
|
||||
urls: { getApps: string };
|
||||
excludeFields?: ExcludeFields[];
|
||||
onEdit?: (app: SAMLFederationApp) => void;
|
||||
onEdit?: (app: IdentityFederationApp) => void;
|
||||
actions: { newApp: string; samlConfiguration: string; oidcConfiguration: string };
|
||||
actionCols?: { text: string; onClick: (app: SAMLFederationApp) => void; icon: JSX.Element }[];
|
||||
actionCols?: { text: string; onClick: (app: IdentityFederationApp) => void; icon: JSX.Element }[];
|
||||
}) => {
|
||||
const { router } = useRouter();
|
||||
const { t } = useTranslation('common');
|
||||
|
@ -45,7 +45,7 @@ export const FederatedSAMLApps = ({
|
|||
getAppsUrl += `&pageToken=${pageTokenMap[paginate.offset - pageLimit]}`;
|
||||
}
|
||||
|
||||
const { data, isLoading, error } = useSWR<{ data: SAMLFederationApp[]; pageToken?: string }>(
|
||||
const { data, isLoading, error } = useSWR<{ data: IdentityFederationApp[]; pageToken?: string }>(
|
||||
getAppsUrl,
|
||||
fetcher
|
||||
);
|
|
@ -2,19 +2,19 @@ import { useFormik } from 'formik';
|
|||
import TagsInput from 'react-tagsinput';
|
||||
import { Card, Button } from 'react-daisyui';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import type { SAMLFederationApp } from '../types';
|
||||
import type { IdentityFederationApp } from '../types';
|
||||
import QuestionMarkCircleIcon from '@heroicons/react/24/outline/QuestionMarkCircleIcon';
|
||||
import { defaultHeaders } from '../utils';
|
||||
import { AttributesMapping } from './AttributesMapping';
|
||||
import { PageHeader } from '../shared';
|
||||
import { ItemList } from '@boxyhq/react-ui/shared';
|
||||
|
||||
type NewSAMLFederationApp = Pick<
|
||||
SAMLFederationApp,
|
||||
type NewIdentityFederationApp = Pick<
|
||||
IdentityFederationApp,
|
||||
'name' | 'tenant' | 'product' | 'acsUrl' | 'entityId' | 'tenants' | 'mappings' | 'type' | 'redirectUrl'
|
||||
>;
|
||||
|
||||
export const NewFederatedSAMLApp = ({
|
||||
export const NewIdentityFederationApp = ({
|
||||
samlAudience = 'https://saml.boxyhq.com',
|
||||
urls,
|
||||
onSuccess,
|
||||
|
@ -24,14 +24,14 @@ export const NewFederatedSAMLApp = ({
|
|||
}: {
|
||||
samlAudience?: string;
|
||||
urls: { createApp: string };
|
||||
onSuccess?: (data: SAMLFederationApp) => void;
|
||||
onSuccess?: (data: IdentityFederationApp) => void;
|
||||
onError?: (error: Error) => void;
|
||||
onEntityIdGenerated?: (entityId: string) => void;
|
||||
excludeFields?: 'product'[];
|
||||
}) => {
|
||||
const { t } = useTranslation('common');
|
||||
|
||||
const initialValues: NewSAMLFederationApp = {
|
||||
const initialValues: NewIdentityFederationApp = {
|
||||
type: 'saml',
|
||||
name: '',
|
||||
tenant: '',
|
||||
|
@ -44,11 +44,11 @@ export const NewFederatedSAMLApp = ({
|
|||
|
||||
if (excludeFields) {
|
||||
excludeFields.forEach((key) => {
|
||||
delete initialValues[key as keyof NewSAMLFederationApp];
|
||||
delete initialValues[key as keyof NewIdentityFederationApp];
|
||||
});
|
||||
}
|
||||
|
||||
const formik = useFormik<NewSAMLFederationApp>({
|
||||
const formik = useFormik<NewIdentityFederationApp>({
|
||||
initialValues: initialValues,
|
||||
onSubmit: async (values) => {
|
||||
const rawResponse = await fetch(urls.createApp, {
|
|
@ -0,0 +1,3 @@
|
|||
export { NewIdentityFederationApp as NewFederatedSAMLApp } from './NewIdentityFederationApp';
|
||||
export { EditIdentityFederationApp as EditFederatedSAMLApp } from './EditIdentityFederationApp';
|
||||
export { IdentityFederationApps as FederatedSAMLApps } from './IdentityFederationApps';
|
|
@ -1,7 +1,7 @@
|
|||
export * from './well-known';
|
||||
export * from './federated-saml';
|
||||
export * from './identity-federation';
|
||||
export * from './shared';
|
||||
export * from './dsync';
|
||||
export * from './provider';
|
||||
export * from './sso-tracer';
|
||||
export * from './sso-traces';
|
||||
export * from './setup-link';
|
||||
|
|
|
@ -10,7 +10,7 @@ import { addQueryParamsToPath, copyToClipboard, fetcher } from '../utils';
|
|||
import { TableBodyType } from '../shared/Table';
|
||||
import { pageLimit } from '../shared/Pagination';
|
||||
import { usePaginate, useRouter } from '../hooks';
|
||||
import type { SAMLFederationApp, SetupLink, SetupLinkService } from '../types';
|
||||
import type { IdentityFederationApp, SetupLink, SetupLinkService } from '../types';
|
||||
import {
|
||||
Loading,
|
||||
Table,
|
||||
|
@ -24,7 +24,7 @@ import {
|
|||
} from '../shared';
|
||||
import { SetupLinkInfoModal } from './SetupLinkInfoModal';
|
||||
|
||||
type ExcludeFields = keyof Pick<SAMLFederationApp, 'product'>;
|
||||
type ExcludeFields = keyof Pick<IdentityFederationApp, 'product'>;
|
||||
|
||||
export const SetupLinks = ({
|
||||
urls,
|
||||
|
|
|
@ -90,7 +90,7 @@ export type AttributeMapping = {
|
|||
value: string;
|
||||
};
|
||||
|
||||
export type SAMLFederationApp = {
|
||||
export type IdentityFederationApp = {
|
||||
id: string;
|
||||
type?: string;
|
||||
clientID?: string;
|
||||
|
|
|
@ -22,4 +22,4 @@ patches:
|
|||
|
||||
images:
|
||||
- name: boxyhq/jackson
|
||||
newTag: 1.23.5
|
||||
newTag: 1.23.7
|
||||
|
|
|
@ -22,4 +22,4 @@ patches:
|
|||
|
||||
images:
|
||||
- name: boxyhq/jackson
|
||||
newTag: 1.23.5
|
||||
newTag: 1.23.7
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"apps": "Apps",
|
||||
"error_loading_page": "Unable to load this page. Maybe you don't have enough rights.",
|
||||
"documentation": "Documentation",
|
||||
"back": "Back",
|
||||
|
@ -41,7 +42,7 @@
|
|||
"directory_created_successfully": "Directory created successfully",
|
||||
"directory_updated_successfully": "Directory updated successfully",
|
||||
"dashboard": "Dashboard",
|
||||
"saml_federation": "Identity Federation",
|
||||
"identity_federation": "Identity Federation",
|
||||
"settings": "Settings",
|
||||
"admin_portal_sso": "SSO for Admin Portal",
|
||||
"configuration": "Configuration",
|
||||
|
@ -224,7 +225,7 @@
|
|||
"bui-dsync-authorization-google": "Authorize Google Workspace",
|
||||
"bui-dsync-authorization-google-desc": "You should authorize Google Workspace to sync your directory. Click the button below start the authorization process. Make sure you have the necessary permissions to authorize Google Workspace.",
|
||||
"bui-dsync-google-domain": "Google Domain",
|
||||
"bui-tracer-title": "SSO Tracer",
|
||||
"bui-tracer-title": "SSO Traces",
|
||||
"bui-tracer-id": "Trace ID",
|
||||
"bui-tracer-description": "Description",
|
||||
"bui-tracer-assertion-type": "Assertion Type",
|
||||
|
|
|
@ -11,6 +11,7 @@ const unAuthenticatedApiRoutes = [
|
|||
'/api/hello',
|
||||
'/api/auth/**',
|
||||
'/api/federated-saml/**',
|
||||
'/api/identity-federation/**',
|
||||
'/api/logout/**',
|
||||
'/api/oauth/**',
|
||||
'/api/scim/v2.0/**',
|
||||
|
|
|
@ -101,6 +101,10 @@ module.exports = {
|
|||
source: '/api/v1/saml-traces/:path*',
|
||||
destination: '/api/v1/sso-traces/:path*',
|
||||
},
|
||||
{
|
||||
source: '/api/v1/federated-saml/:path*',
|
||||
destination: '/api/v1/identity-federation/:path*',
|
||||
},
|
||||
];
|
||||
},
|
||||
images: {
|
||||
|
|
|
@ -26,8 +26,8 @@ const map = {
|
|||
'src/directory-sync/request.ts',
|
||||
],
|
||||
'test/dsync/events.test.ts': ['src/directory-sync/events.ts'],
|
||||
'test/federated-saml/app.test.ts': ['src/ee/federated-saml/app.ts'],
|
||||
'test/federated-saml/sso.test.ts': ['src/ee/federated-saml/sso.ts'],
|
||||
'test/identity-federation/app.test.ts': ['src/ee/identity-federation/app.ts'],
|
||||
'test/identity-federation/sso.test.ts': ['src/ee/identity-federation/sso.ts'],
|
||||
'test/event/index.test.ts': ['src/event/*'],
|
||||
'test/dsync/google_oauth.test.ts': [
|
||||
'src/directory-sync/non-scim/google/oauth.ts',
|
||||
|
|
|
@ -1151,7 +1151,7 @@
|
|||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "0.3.9"
|
||||
},
|
||||
|
@ -1339,7 +1339,7 @@
|
|||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
|
@ -1348,13 +1348,13 @@
|
|||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
||||
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.0.3",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
|
@ -3064,13 +3064,13 @@
|
|||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
|
||||
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node12": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
||||
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node14": {
|
||||
"version": "14.1.2",
|
||||
|
@ -3228,7 +3228,7 @@
|
|||
"version": "8.11.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
|
||||
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
|
@ -3240,7 +3240,7 @@
|
|||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz",
|
||||
"integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
|
@ -3339,7 +3339,7 @@
|
|||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/array-buffer-byte-length": {
|
||||
"version": "1.0.1",
|
||||
|
@ -4148,7 +4148,7 @@
|
|||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
|
@ -4813,63 +4813,6 @@
|
|||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/gcp-metadata": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz",
|
||||
"integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"gaxios": "^5.0.0",
|
||||
"json-bigint": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/gcp-metadata/node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/gcp-metadata/node_modules/gaxios": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz",
|
||||
"integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"extend": "^3.0.2",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"is-stream": "^2.0.0",
|
||||
"node-fetch": "^2.6.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/gcp-metadata/node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/generate-function": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
|
||||
|
@ -5400,7 +5343,7 @@
|
|||
"version": "9.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
|
||||
"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"jsbn": "1.1.0",
|
||||
"sprintf-js": "^1.1.3"
|
||||
|
@ -5843,7 +5786,7 @@
|
|||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
|
||||
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-bigint": {
|
||||
"version": "1.0.0",
|
||||
|
@ -6081,7 +6024,7 @@
|
|||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/make-fetch-happen": {
|
||||
"version": "13.0.0",
|
||||
|
@ -7429,20 +7372,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-element-to-jsx-string": {
|
||||
"version": "15.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz",
|
||||
|
@ -7921,7 +7850,7 @@
|
|||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
||||
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
|
@ -7931,7 +7860,7 @@
|
|||
"version": "2.8.3",
|
||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
|
||||
"integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ip-address": "^9.0.5",
|
||||
"smart-buffer": "^4.2.0"
|
||||
|
@ -8521,7 +8450,7 @@
|
|||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
|
@ -8564,19 +8493,19 @@
|
|||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
||||
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ts-node/node_modules/@tsconfig/node16": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
||||
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ts-node/node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
|
@ -8879,7 +8808,7 @@
|
|||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.4.5",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
|
@ -8967,7 +8896,7 @@
|
|||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/v8-to-istanbul": {
|
||||
"version": "9.2.0",
|
||||
|
@ -9417,7 +9346,7 @@
|
|||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import type {
|
|||
SSOTracerInstance,
|
||||
OAuthErrorHandlerParams,
|
||||
OIDCAuthzResponsePayload,
|
||||
SAMLFederationApp,
|
||||
IdentityFederationApp,
|
||||
} from '../typings';
|
||||
import {
|
||||
relayStatePrefix,
|
||||
|
@ -45,7 +45,7 @@ import { getDefaultCertificate } from '../saml/x509';
|
|||
import { SSOHandler } from './sso-handler';
|
||||
import { ValidateOption, extractSAMLResponseAttributes } from '../saml/lib';
|
||||
import { oidcIssuerInstance } from './oauth/oidc-issuer';
|
||||
import { App } from '../ee/federated-saml/app';
|
||||
import { App } from '../ee/identity-federation/app';
|
||||
|
||||
const deflateRawAsync = promisify(deflateRaw);
|
||||
|
||||
|
@ -96,7 +96,7 @@ export class OAuthController implements IOAuthController {
|
|||
let requestedOIDCFlow: boolean | undefined;
|
||||
let isOIDCFederated: boolean | undefined;
|
||||
let connection: SAMLSSORecord | OIDCSSORecord | undefined;
|
||||
let fedApp: SAMLFederationApp | undefined;
|
||||
let fedApp: IdentityFederationApp | undefined;
|
||||
|
||||
try {
|
||||
const tenant = 'tenant' in body ? body.tenant : undefined;
|
||||
|
|
|
@ -5,7 +5,13 @@ import { deflateRaw } from 'zlib';
|
|||
import type { SAMLProfile } from '@boxyhq/saml20/dist/typings';
|
||||
import { generators } from 'openid-client';
|
||||
|
||||
import type { JacksonOption, Storable, SAMLSSORecord, OIDCSSORecord, SAMLFederationApp } from '../typings';
|
||||
import type {
|
||||
JacksonOption,
|
||||
Storable,
|
||||
SAMLSSORecord,
|
||||
OIDCSSORecord,
|
||||
IdentityFederationApp,
|
||||
} from '../typings';
|
||||
import { getDefaultCertificate } from '../saml/x509';
|
||||
import * as dbutils from '../db/utils';
|
||||
import { JacksonError } from './error';
|
||||
|
@ -167,7 +173,7 @@ export class SSOHandler {
|
|||
}: {
|
||||
connection: SAMLSSORecord;
|
||||
requestParams: Record<string, any>;
|
||||
mappings: SAMLFederationApp['mappings'];
|
||||
mappings: IdentityFederationApp['mappings'];
|
||||
}) {
|
||||
// We have a connection now, so we can create the SAML request
|
||||
const certificate = await getDefaultCertificate();
|
||||
|
@ -240,7 +246,7 @@ export class SSOHandler {
|
|||
}: {
|
||||
connection: OIDCSSORecord;
|
||||
requestParams: Record<string, any>;
|
||||
mappings: SAMLFederationApp['mappings'];
|
||||
mappings: IdentityFederationApp['mappings'];
|
||||
}) {
|
||||
if (!this.opts.oidcPath) {
|
||||
throw new JacksonError('OpenID response handler path (oidcPath) is not set', 400);
|
||||
|
@ -347,7 +353,7 @@ export class SSOHandler {
|
|||
requested: any;
|
||||
oidcCodeVerifier?: string;
|
||||
oidcNonce?: string;
|
||||
mappings: SAMLFederationApp['mappings'];
|
||||
mappings: IdentityFederationApp['mappings'];
|
||||
}) => {
|
||||
const sessionId = crypto.randomBytes(16).toString('hex');
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import saml from '@boxyhq/saml20';
|
|||
import type {
|
||||
Storable,
|
||||
JacksonOption,
|
||||
SAMLFederationApp,
|
||||
IdentityFederationApp,
|
||||
Records,
|
||||
GetByProductParams,
|
||||
AppRequestParams,
|
||||
|
@ -17,7 +17,7 @@ import { IndexNames, validateTenantAndProduct } from '../../controller/utils';
|
|||
import { throwIfInvalidLicense } from '../common/checkLicense';
|
||||
|
||||
type NewAppParams = Pick<
|
||||
SAMLFederationApp,
|
||||
IdentityFederationApp,
|
||||
'name' | 'tenant' | 'product' | 'acsUrl' | 'entityId' | 'tenants' | 'mappings' | 'type' | 'redirectUrl'
|
||||
> & {
|
||||
logoUrl?: string;
|
||||
|
@ -32,7 +32,7 @@ export class App {
|
|||
/**
|
||||
* @swagger
|
||||
* definitions:
|
||||
* SAMLFederationApp:
|
||||
* IdentityFederationApp:
|
||||
* type: object
|
||||
* properties:
|
||||
* id:
|
||||
|
@ -71,7 +71,7 @@ export class App {
|
|||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/federated-saml:
|
||||
* /api/v1/identity-federation:
|
||||
* post:
|
||||
* summary: Create an Identity Federation app
|
||||
* parameters:
|
||||
|
@ -147,7 +147,7 @@ export class App {
|
|||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/definitions/SAMLFederationApp'
|
||||
* $ref: '#/definitions/IdentityFederationApp'
|
||||
*/
|
||||
public async create({
|
||||
name,
|
||||
|
@ -201,7 +201,7 @@ export class App {
|
|||
value: entityId,
|
||||
});
|
||||
|
||||
const apps: SAMLFederationApp[] = result.data;
|
||||
const apps: IdentityFederationApp[] = result.data;
|
||||
|
||||
if (apps && apps.length > 0) {
|
||||
throw new JacksonError(
|
||||
|
@ -219,7 +219,7 @@ export class App {
|
|||
_tenants.push(tenant);
|
||||
}
|
||||
|
||||
const app: SAMLFederationApp = {
|
||||
const app: IdentityFederationApp = {
|
||||
id,
|
||||
type,
|
||||
redirectUrl,
|
||||
|
@ -261,7 +261,7 @@ export class App {
|
|||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/federated-saml:
|
||||
* /api/v1/identity-federation:
|
||||
* get:
|
||||
* summary: Get an Identity Federation app
|
||||
* parameters:
|
||||
|
@ -288,7 +288,7 @@ export class App {
|
|||
* '200':
|
||||
* description: Success
|
||||
* schema:
|
||||
* $ref: '#/definitions/SAMLFederationApp'
|
||||
* $ref: '#/definitions/IdentityFederationApp'
|
||||
*/
|
||||
public async get(params: AppRequestParams) {
|
||||
await throwIfInvalidLicense(this.opts.boxyhqLicenseKey);
|
||||
|
@ -300,7 +300,7 @@ export class App {
|
|||
throw new JacksonError('Identity Federation app not found', 404);
|
||||
}
|
||||
|
||||
return app as SAMLFederationApp;
|
||||
return app as IdentityFederationApp;
|
||||
}
|
||||
|
||||
if ('tenant' in params && 'product' in params) {
|
||||
|
@ -310,7 +310,7 @@ export class App {
|
|||
throw new JacksonError('Identity Federation app not found', 404);
|
||||
}
|
||||
|
||||
return app as SAMLFederationApp;
|
||||
return app as IdentityFederationApp;
|
||||
}
|
||||
|
||||
throw new JacksonError('Provide either the `id` or `tenant` and `product` to get the app', 400);
|
||||
|
@ -318,7 +318,7 @@ export class App {
|
|||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/federated-saml/product:
|
||||
* /api/v1/identity-federation/product:
|
||||
* get:
|
||||
* summary: Get Identity Federation apps by product
|
||||
* parameters:
|
||||
|
@ -345,7 +345,7 @@ export class App {
|
|||
* data:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/definitions/SAMLFederationApp'
|
||||
* $ref: '#/definitions/IdentityFederationApp'
|
||||
* pageToken:
|
||||
* type: string
|
||||
* description: token for pagination
|
||||
|
@ -378,7 +378,7 @@ export class App {
|
|||
throw new JacksonError('Missing required parameters. Required parameters are: entityId', 400);
|
||||
}
|
||||
|
||||
const apps: SAMLFederationApp[] = (
|
||||
const apps: IdentityFederationApp[] = (
|
||||
await this.store.getByIndex({
|
||||
name: IndexNames.EntityID,
|
||||
value: entityId,
|
||||
|
@ -394,7 +394,7 @@ export class App {
|
|||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/federated-saml:
|
||||
* /api/v1/identity-federation:
|
||||
* patch:
|
||||
* summary: Update an Identity Federation app
|
||||
* parameters:
|
||||
|
@ -459,9 +459,9 @@ export class App {
|
|||
* '200':
|
||||
* description: Success
|
||||
* schema:
|
||||
* $ref: '#/definitions/SAMLFederationApp'
|
||||
* $ref: '#/definitions/IdentityFederationApp'
|
||||
*/
|
||||
public async update(params: Partial<SAMLFederationApp>) {
|
||||
public async update(params: Partial<IdentityFederationApp>) {
|
||||
await throwIfInvalidLicense(this.opts.boxyhqLicenseKey);
|
||||
|
||||
const { id, tenant, product, type } = params;
|
||||
|
@ -470,7 +470,7 @@ export class App {
|
|||
throw new JacksonError('Provide either the `id` or `tenant` and `product` to update the app', 400);
|
||||
}
|
||||
|
||||
let app: null | SAMLFederationApp = null;
|
||||
let app: null | IdentityFederationApp = null;
|
||||
|
||||
if (id) {
|
||||
app = await this.get({ id });
|
||||
|
@ -482,7 +482,7 @@ export class App {
|
|||
throw new JacksonError('Identity Federation app not found', 404);
|
||||
}
|
||||
|
||||
const toUpdate: Partial<SAMLFederationApp> = {};
|
||||
const toUpdate: Partial<IdentityFederationApp> = {};
|
||||
|
||||
// Support partial updates
|
||||
|
||||
|
@ -556,14 +556,18 @@ export class App {
|
|||
}) {
|
||||
await throwIfInvalidLicense(this.opts.boxyhqLicenseKey);
|
||||
|
||||
const apps = (await this.store.getAll(pageOffset, pageLimit, pageToken)) as Records<SAMLFederationApp>;
|
||||
const apps = (await this.store.getAll(
|
||||
pageOffset,
|
||||
pageLimit,
|
||||
pageToken
|
||||
)) as Records<IdentityFederationApp>;
|
||||
|
||||
return apps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/v1/federated-saml:
|
||||
* /api/v1/identity-federation:
|
||||
* delete:
|
||||
* summary: Delete an Identity Federation app
|
||||
* parameters:
|
||||
|
@ -590,7 +594,7 @@ export class App {
|
|||
* '200':
|
||||
* description: Success
|
||||
* schema:
|
||||
* $ref: '#/definitions/SAMLFederationApp'
|
||||
* $ref: '#/definitions/IdentityFederationApp'
|
||||
*/
|
||||
public async delete(params: AppRequestParams): Promise<void> {
|
||||
await throwIfInvalidLicense(this.opts.boxyhqLicenseKey);
|
||||
|
@ -613,7 +617,7 @@ export class App {
|
|||
|
||||
const { publicKey } = await getDefaultCertificate();
|
||||
|
||||
const ssoUrl = `${this.opts.externalUrl}/api/federated-saml/sso`;
|
||||
const ssoUrl = `${this.opts.externalUrl}/api/identity-federation/sso`;
|
||||
const entityId = `${this.opts.samlAudience}`;
|
||||
|
||||
const xml = saml.createIdPMetadataXML({
|
|
@ -4,7 +4,7 @@ import type { JacksonOption, SSOTracerInstance } from '../../typings';
|
|||
import { SSOHandler } from '../../controller/sso-handler';
|
||||
|
||||
// This is the main entry point for the Identity Federation module
|
||||
const SAMLFederation = async ({
|
||||
const IdentityFederation = async ({
|
||||
db,
|
||||
opts,
|
||||
ssoTracer,
|
||||
|
@ -34,7 +34,7 @@ const SAMLFederation = async ({
|
|||
return response;
|
||||
};
|
||||
|
||||
export default SAMLFederation;
|
||||
export default IdentityFederation;
|
||||
|
||||
export * from './types';
|
||||
|
|
@ -6,7 +6,7 @@ import { SSOHandler } from '../../controller/sso-handler';
|
|||
import type {
|
||||
JacksonOption,
|
||||
OIDCSSORecord,
|
||||
SAMLFederationApp,
|
||||
IdentityFederationApp,
|
||||
SAMLSSORecord,
|
||||
SSOTracerInstance,
|
||||
} from '../../typings';
|
||||
|
@ -56,7 +56,7 @@ export class SSO {
|
|||
|
||||
const isPostBinding = samlBinding === 'HTTP-POST';
|
||||
let connection: SAMLSSORecord | OIDCSSORecord | undefined;
|
||||
let app: SAMLFederationApp | undefined;
|
||||
let app: IdentityFederationApp | undefined;
|
||||
let id, acsUrl, entityId, publicKey, providerName, decodedRequest;
|
||||
|
||||
try {
|
|
@ -1,13 +1,13 @@
|
|||
import SAMLFederation from '.';
|
||||
import IdentityFederation from '.';
|
||||
|
||||
export type ISAMLFederationController = Awaited<ReturnType<typeof SAMLFederation>>;
|
||||
export type IIdentityFederationController = Awaited<ReturnType<typeof IdentityFederation>>;
|
||||
|
||||
export type AttributeMapping = {
|
||||
key: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type SAMLFederationApp = {
|
||||
export type IdentityFederationApp = {
|
||||
id: string;
|
||||
type?: string;
|
||||
clientID?: string;
|
||||
|
@ -25,7 +25,7 @@ export type SAMLFederationApp = {
|
|||
mappings?: AttributeMapping[] | null;
|
||||
};
|
||||
|
||||
export type SAMLFederationAppWithMetadata = SAMLFederationApp & {
|
||||
export type IdentityFederationAppWithMetadata = IdentityFederationApp & {
|
||||
metadata: {
|
||||
entityId: string;
|
||||
ssoUrl: string;
|
|
@ -13,10 +13,10 @@ import { SPSSOConfig } from './controller/sp-config';
|
|||
import { SetupLinkController } from './controller/setup-link';
|
||||
import { AnalyticsController } from './controller/analytics';
|
||||
import * as x509 from './saml/x509';
|
||||
import initFederatedSAML, { type ISAMLFederationController } from './ee/federated-saml';
|
||||
import initFederatedSAML, { type IIdentityFederationController } from './ee/identity-federation';
|
||||
import checkLicense from './ee/common/checkLicense';
|
||||
import { BrandingController } from './ee/branding';
|
||||
import SSOTracer from './sso-tracer';
|
||||
import SSOTracer from './sso-traces';
|
||||
import EventController from './event';
|
||||
import { ProductController } from './ee/product';
|
||||
import { OryController } from './ee/ory/ory';
|
||||
|
@ -71,7 +71,7 @@ export const controllers = async (
|
|||
directorySyncController: IDirectorySyncController;
|
||||
oidcDiscoveryController: OidcDiscoveryController;
|
||||
spConfig: SPSSOConfig;
|
||||
samlFederatedController: ISAMLFederationController;
|
||||
samlFederatedController: IIdentityFederationController;
|
||||
brandingController: IBrandingController;
|
||||
checkLicense: () => Promise<boolean>;
|
||||
productController: ProductController;
|
||||
|
@ -194,7 +194,7 @@ export const controllers = async (
|
|||
export default controllers;
|
||||
|
||||
export * from './typings';
|
||||
export * from './ee/federated-saml/types';
|
||||
export * from './ee/identity-federation/types';
|
||||
export type SAMLJackson = Awaited<ReturnType<typeof controllers>>;
|
||||
export type ISetupLinkController = InstanceType<typeof SetupLinkController>;
|
||||
export type IBrandingController = InstanceType<typeof BrandingController>;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import type { JWK } from 'jose';
|
||||
import type { CallbackParamsType, IssuerMetadata } from 'openid-client';
|
||||
|
||||
export * from './ee/federated-saml/types';
|
||||
export * from './sso-tracer/types';
|
||||
export * from './ee/identity-federation/types';
|
||||
export * from './sso-traces/types';
|
||||
export * from './directory-sync/types';
|
||||
export * from './event/types';
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="ONELOGIN_082f89d9-a32a-441d-ae49-ab6fc13fe73b" Version="2.0" IssueInstant="2022-11-29T09:04:48Z" ProviderName="Twilio" Destination="http://localhost:5225/api/federated-saml/sso" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="https://twilio.com/saml2/acs"><saml:Issuer>https://twilio.com/saml2/entityId</saml:Issuer><samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true" /><samlp:RequestedAuthnContext Comparison="exact"><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></samlp:RequestedAuthnContext></samlp:AuthnRequest>
|
|
@ -1,11 +1,11 @@
|
|||
import tap from 'tap';
|
||||
|
||||
import { ISAMLFederationController } from '../../src';
|
||||
import { IIdentityFederationController } from '../../src';
|
||||
import { jacksonOptions } from '../utils';
|
||||
import { tenant, product, serviceProvider, appId } from './constants';
|
||||
import { getDefaultCertificate } from '../../src/saml/x509';
|
||||
|
||||
let samlFederatedController: ISAMLFederationController;
|
||||
let samlFederatedController: IIdentityFederationController;
|
||||
|
||||
tap.before(async () => {
|
||||
const jackson = await (await import('../../src/index')).default(jacksonOptions);
|
||||
|
@ -149,7 +149,7 @@ tap.test('Federated SAML App', async () => {
|
|||
|
||||
t.ok(response);
|
||||
t.match(response.entityId, jacksonOptions.samlAudience);
|
||||
t.match(response.ssoUrl, `${jacksonOptions.externalUrl}/api/federated-saml/sso`);
|
||||
t.match(response.ssoUrl, `${jacksonOptions.externalUrl}/api/identity-federation/sso`);
|
||||
t.match(response.x509cert, certs.publicKey);
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="ONELOGIN_082f89d9-a32a-441d-ae49-ab6fc13fe73b" Version="2.0" IssueInstant="2022-11-29T09:04:48Z" ProviderName="Twilio" Destination="http://localhost:5225/api/identity-federation/sso" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="https://twilio.com/saml2/acs"><saml:Issuer>https://twilio.com/saml2/entityId</saml:Issuer><samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true" /><samlp:RequestedAuthnContext Comparison="exact"><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef></samlp:RequestedAuthnContext></samlp:AuthnRequest>
|
|
@ -11,18 +11,18 @@ const deflateRawAsync = promisify(deflateRaw);
|
|||
import { jacksonOptions } from '../utils';
|
||||
import { tenant, product, serviceProvider } from './constants';
|
||||
import type {
|
||||
ISAMLFederationController,
|
||||
IIdentityFederationController,
|
||||
IConnectionAPIController,
|
||||
IOAuthController,
|
||||
SAMLFederationApp,
|
||||
IdentityFederationApp,
|
||||
SAMLSSORecord,
|
||||
} from '../../src';
|
||||
|
||||
let oauthController: IOAuthController;
|
||||
let samlFederatedController: ISAMLFederationController;
|
||||
let samlFederatedController: IIdentityFederationController;
|
||||
let connectionAPIController: IConnectionAPIController;
|
||||
|
||||
let app: SAMLFederationApp;
|
||||
let app: IdentityFederationApp;
|
||||
let connection: SAMLSSORecord;
|
||||
|
||||
tap.before(async () => {
|
|
@ -1,5 +1,5 @@
|
|||
import tap from 'tap';
|
||||
import SSOTracer from '../../src/sso-tracer';
|
||||
import SSOTracer from '../../src/sso-traces';
|
||||
import { jacksonOptions } from '../utils';
|
||||
import DB from '../../src/db/db';
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "jackson",
|
||||
"version": "1.23.6",
|
||||
"version": "1.23.7",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "jackson",
|
||||
"version": "1.23.6",
|
||||
"version": "1.23.7",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
|
@ -304,14 +304,16 @@
|
|||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@aws-sdk/client-cognito-identity": {
|
||||
"version": "3.568.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.568.0.tgz",
|
||||
"integrity": "sha512-qZyPpvtjEj8Tv7Xkp4CfF10SqyjamfzY8VWHKVBYMLRgxlRRKQsuTlsP+MSsUA32mU9Gid021aR8WWl4bdo8OQ==",
|
||||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.569.0.tgz",
|
||||
"integrity": "sha512-cD1HcdJNpUZgrATWCAQs2amQKI69pG+jF4b5ySq9KJkVi6gv2PWsD6QGDG8H12lMWaIKYlOpKbpnYTpcuvqUcg==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "3.0.0",
|
||||
"@aws-crypto/sha256-js": "3.0.0",
|
||||
"@aws-sdk/client-sso-oidc": "3.569.0",
|
||||
"@aws-sdk/client-sts": "3.569.0",
|
||||
"@aws-sdk/core": "3.567.0",
|
||||
"@aws-sdk/credential-provider-node": "3.568.0",
|
||||
"@aws-sdk/credential-provider-node": "3.569.0",
|
||||
"@aws-sdk/middleware-host-header": "3.567.0",
|
||||
"@aws-sdk/middleware-logger": "3.568.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.567.0",
|
||||
|
@ -353,14 +355,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-dynamodb": {
|
||||
"version": "3.568.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.568.0.tgz",
|
||||
"integrity": "sha512-5e22HEIGN5ZUaUe+PQ5HxxddnVClLYEfrxaNK9iWNuH4Fy/RSTZwlrSADr0KRFk7qierb51UMi3LaQovArBNbA==",
|
||||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.569.0.tgz",
|
||||
"integrity": "sha512-o3Nh9826AzYgqGhKdII9ymMRxNJ1doIrvohv3wW1UjquVQLI3aquVRAU9SavVhwgRrv3LcG3nzEtlea5hKuppA==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "3.0.0",
|
||||
"@aws-crypto/sha256-js": "3.0.0",
|
||||
"@aws-sdk/client-sso-oidc": "3.569.0",
|
||||
"@aws-sdk/client-sts": "3.569.0",
|
||||
"@aws-sdk/core": "3.567.0",
|
||||
"@aws-sdk/credential-provider-node": "3.568.0",
|
||||
"@aws-sdk/credential-provider-node": "3.569.0",
|
||||
"@aws-sdk/middleware-endpoint-discovery": "3.568.0",
|
||||
"@aws-sdk/middleware-host-header": "3.567.0",
|
||||
"@aws-sdk/middleware-logger": "3.568.0",
|
||||
|
@ -456,7 +460,6 @@
|
|||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.569.0.tgz",
|
||||
"integrity": "sha512-u5DEjNEvRvlKKh1QLCDuQ8GIrx+OFvJFLfhorsp4oCxDylvORs+KfyKKnJAw4wYEEHyxyz9GzHD7p6a8+HLVHw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "3.0.0",
|
||||
"@aws-crypto/sha256-js": "3.0.0",
|
||||
|
@ -503,34 +506,10 @@
|
|||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sso-oidc/node_modules/@aws-sdk/credential-provider-node": {
|
||||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.569.0.tgz",
|
||||
"integrity": "sha512-7jH4X2qlPU3PszZP1zvHJorhLARbU1tXvp8ngBe8ArXBrkFpl/dQ2Y/IRAICPm/pyC1IEt8L/CvKp+dz7v/eRw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-provider-env": "3.568.0",
|
||||
"@aws-sdk/credential-provider-http": "3.568.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.568.0",
|
||||
"@aws-sdk/credential-provider-process": "3.568.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.568.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.568.0",
|
||||
"@aws-sdk/types": "3.567.0",
|
||||
"@smithy/credential-provider-imds": "^2.3.0",
|
||||
"@smithy/property-provider": "^2.2.0",
|
||||
"@smithy/shared-ini-file-loader": "^2.4.0",
|
||||
"@smithy/types": "^2.12.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sts": {
|
||||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.569.0.tgz",
|
||||
"integrity": "sha512-3AyipQ2zHszkcTr8n1Sp7CiMUi28aMf1vOhEo0KKi0DWGo1Z1qJEpWeRP363KG0n9/8U3p1IkXGz5FRbpXZxIw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "3.0.0",
|
||||
"@aws-crypto/sha256-js": "3.0.0",
|
||||
|
@ -577,29 +556,6 @@
|
|||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/client-sts/node_modules/@aws-sdk/credential-provider-node": {
|
||||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.569.0.tgz",
|
||||
"integrity": "sha512-7jH4X2qlPU3PszZP1zvHJorhLARbU1tXvp8ngBe8ArXBrkFpl/dQ2Y/IRAICPm/pyC1IEt8L/CvKp+dz7v/eRw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-provider-env": "3.568.0",
|
||||
"@aws-sdk/credential-provider-http": "3.568.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.568.0",
|
||||
"@aws-sdk/credential-provider-process": "3.568.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.568.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.568.0",
|
||||
"@aws-sdk/types": "3.567.0",
|
||||
"@smithy/credential-provider-imds": "^2.3.0",
|
||||
"@smithy/property-provider": "^2.2.0",
|
||||
"@smithy/shared-ini-file-loader": "^2.4.0",
|
||||
"@smithy/types": "^2.12.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/core": {
|
||||
"version": "3.567.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.567.0.tgz",
|
||||
|
@ -618,11 +574,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-cognito-identity": {
|
||||
"version": "3.568.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.568.0.tgz",
|
||||
"integrity": "sha512-FoQZVeRDvM7s2dpsiXaU7zIukY1ojwofqRU4k7VXU4cpsDZV29JscrAkmKMCbQqujIWA/EwxhiYNgdbo1CiRLQ==",
|
||||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.569.0.tgz",
|
||||
"integrity": "sha512-CHS0Zyuazh5cYLaJr2/I9up0xAu8Y+um/h0o4xNf00cKGT0Sdhoby5vyelHjVTeZt+OeOMTBt6IdqGwVbVG9gQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cognito-identity": "3.568.0",
|
||||
"@aws-sdk/client-cognito-identity": "3.569.0",
|
||||
"@aws-sdk/types": "3.567.0",
|
||||
"@smithy/property-provider": "^2.2.0",
|
||||
"@smithy/types": "^2.12.0",
|
||||
|
@ -689,9 +645,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-node": {
|
||||
"version": "3.568.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.568.0.tgz",
|
||||
"integrity": "sha512-gGvBHzVAwDPMwgiAOkigm6eKg0EHIStpwDW4z4XRoSJCcSTyBQ8qqUkoJY7b5Hoju25zBsrB8PvQnZgJU/NYmA==",
|
||||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.569.0.tgz",
|
||||
"integrity": "sha512-7jH4X2qlPU3PszZP1zvHJorhLARbU1tXvp8ngBe8ArXBrkFpl/dQ2Y/IRAICPm/pyC1IEt8L/CvKp+dz7v/eRw==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-provider-env": "3.568.0",
|
||||
"@aws-sdk/credential-provider-http": "3.568.0",
|
||||
|
@ -760,18 +716,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers": {
|
||||
"version": "3.568.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.568.0.tgz",
|
||||
"integrity": "sha512-V2x+35XzRphs9bpussynNu1Eme/4qFjF9KoSOvFvSqBHRt8hf7+C21pzYeHgrbsXowv5plON0sldyqOqpMhPmg==",
|
||||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.569.0.tgz",
|
||||
"integrity": "sha512-UL7EewaM1Xk6e4XLsxrCBv/owVSDI6Katnok6uMfqA8dA0x3ELjO7W35DW4wpWejQHErN5Gp1zloV9y3t34FMQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-cognito-identity": "3.568.0",
|
||||
"@aws-sdk/client-cognito-identity": "3.569.0",
|
||||
"@aws-sdk/client-sso": "3.568.0",
|
||||
"@aws-sdk/client-sts": "3.568.0",
|
||||
"@aws-sdk/credential-provider-cognito-identity": "3.568.0",
|
||||
"@aws-sdk/client-sts": "3.569.0",
|
||||
"@aws-sdk/credential-provider-cognito-identity": "3.569.0",
|
||||
"@aws-sdk/credential-provider-env": "3.568.0",
|
||||
"@aws-sdk/credential-provider-http": "3.568.0",
|
||||
"@aws-sdk/credential-provider-ini": "3.568.0",
|
||||
"@aws-sdk/credential-provider-node": "3.568.0",
|
||||
"@aws-sdk/credential-provider-node": "3.569.0",
|
||||
"@aws-sdk/credential-provider-process": "3.568.0",
|
||||
"@aws-sdk/credential-provider-sso": "3.568.0",
|
||||
"@aws-sdk/credential-provider-web-identity": "3.568.0",
|
||||
|
@ -785,55 +741,6 @@
|
|||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-providers/node_modules/@aws-sdk/client-sts": {
|
||||
"version": "3.568.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.568.0.tgz",
|
||||
"integrity": "sha512-eDO0S1YYi8eCDcwH5TvJuzJ+Irsx/W6bsQ8fL7rF3aPmsoYQvZh2arpysTUWa4SHpSOkiQFHnii0FqFpw34wyA==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha256-browser": "3.0.0",
|
||||
"@aws-crypto/sha256-js": "3.0.0",
|
||||
"@aws-sdk/core": "3.567.0",
|
||||
"@aws-sdk/credential-provider-node": "3.568.0",
|
||||
"@aws-sdk/middleware-host-header": "3.567.0",
|
||||
"@aws-sdk/middleware-logger": "3.568.0",
|
||||
"@aws-sdk/middleware-recursion-detection": "3.567.0",
|
||||
"@aws-sdk/middleware-user-agent": "3.567.0",
|
||||
"@aws-sdk/region-config-resolver": "3.567.0",
|
||||
"@aws-sdk/types": "3.567.0",
|
||||
"@aws-sdk/util-endpoints": "3.567.0",
|
||||
"@aws-sdk/util-user-agent-browser": "3.567.0",
|
||||
"@aws-sdk/util-user-agent-node": "3.568.0",
|
||||
"@smithy/config-resolver": "^2.2.0",
|
||||
"@smithy/core": "^1.4.2",
|
||||
"@smithy/fetch-http-handler": "^2.5.0",
|
||||
"@smithy/hash-node": "^2.2.0",
|
||||
"@smithy/invalid-dependency": "^2.2.0",
|
||||
"@smithy/middleware-content-length": "^2.2.0",
|
||||
"@smithy/middleware-endpoint": "^2.5.1",
|
||||
"@smithy/middleware-retry": "^2.3.1",
|
||||
"@smithy/middleware-serde": "^2.3.0",
|
||||
"@smithy/middleware-stack": "^2.2.0",
|
||||
"@smithy/node-config-provider": "^2.3.0",
|
||||
"@smithy/node-http-handler": "^2.5.0",
|
||||
"@smithy/protocol-http": "^3.3.0",
|
||||
"@smithy/smithy-client": "^2.5.1",
|
||||
"@smithy/types": "^2.12.0",
|
||||
"@smithy/url-parser": "^2.2.0",
|
||||
"@smithy/util-base64": "^2.3.0",
|
||||
"@smithy/util-body-length-browser": "^2.2.0",
|
||||
"@smithy/util-body-length-node": "^2.3.0",
|
||||
"@smithy/util-defaults-mode-browser": "^2.2.1",
|
||||
"@smithy/util-defaults-mode-node": "^2.3.1",
|
||||
"@smithy/util-endpoints": "^1.2.0",
|
||||
"@smithy/util-middleware": "^2.2.0",
|
||||
"@smithy/util-retry": "^2.2.0",
|
||||
"@smithy/util-utf8": "^2.3.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/endpoint-cache": {
|
||||
"version": "3.568.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.568.0.tgz",
|
||||
|
@ -965,9 +872,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/util-dynamodb": {
|
||||
"version": "3.568.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.568.0.tgz",
|
||||
"integrity": "sha512-bCLjvMzKrAyt3/YZ85eO02RpgRcajaK1v40Jy3MxkLFJ2LUg7MNaMdCdBSOGfe+4v/SepOtwUMLDddPr/mFEQA==",
|
||||
"version": "3.569.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.569.0.tgz",
|
||||
"integrity": "sha512-cTNwY1eSycZJhetaj0Xl0E65lHl65mwfe9bsq6cSRuMxUXYpuo5yEwiT5OMQiAC8QtlwpCHokFHI12TqqlZbFQ==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
|
@ -975,7 +882,7 @@
|
|||
"node": ">=16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@aws-sdk/client-dynamodb": "^3.568.0"
|
||||
"@aws-sdk/client-dynamodb": "^3.569.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/util-endpoints": {
|
||||
|
@ -1797,9 +1704,9 @@
|
|||
"link": true
|
||||
},
|
||||
"node_modules/@boxyhq/saml20": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@boxyhq/saml20/-/saml20-1.5.0.tgz",
|
||||
"integrity": "sha512-4/Nj4DjyYrIZXerp+VkiNwvsvFn5rLftk9idAgfbXSEHz4TtXrRZofsl80s73fipS5LUENk453uE3uLVeN+BMQ==",
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@boxyhq/saml20/-/saml20-1.5.1.tgz",
|
||||
"integrity": "sha512-SpM/i7s11v05akleLCpcYqNoQdlykVy51TEOt6i186KJ2ZqMX5FsPSNxjjluM3v3FpfvAqiy3Vf9eCw0B0JtYQ==",
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "0.8.10",
|
||||
"xml-crypto": "6.0.0",
|
||||
|
@ -2387,9 +2294,9 @@
|
|||
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
|
||||
},
|
||||
"node_modules/@googleapis/admin": {
|
||||
"version": "17.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@googleapis/admin/-/admin-17.1.0.tgz",
|
||||
"integrity": "sha512-rJcUkz+vFYQTvnkXhqC9LAtRUGmUth2yuTVtp9ih6fETVjzsWyjZtD0g2IPxBTC5shyLQXVBYbysmcO+WS/4Uw==",
|
||||
"version": "18.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@googleapis/admin/-/admin-18.0.0.tgz",
|
||||
"integrity": "sha512-HFm2xlRrQpx6YySA51QfcBcMsoUVlGkXIuaCakyflCyIiQFMD8AMt4iIEQvwU+zn91cHE4i1rj8BX7C3kaqz3A==",
|
||||
"dependencies": {
|
||||
"googleapis-common": "^7.0.0"
|
||||
},
|
||||
|
@ -23580,13 +23487,13 @@
|
|||
"version": "0.0.0",
|
||||
"license": "Apache 2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-dynamodb": "3.568.0",
|
||||
"@aws-sdk/credential-providers": "3.568.0",
|
||||
"@aws-sdk/util-dynamodb": "3.568.0",
|
||||
"@aws-sdk/client-dynamodb": "3.569.0",
|
||||
"@aws-sdk/credential-providers": "3.569.0",
|
||||
"@aws-sdk/util-dynamodb": "3.569.0",
|
||||
"@boxyhq/error-code-mnemonic": "0.1.1",
|
||||
"@boxyhq/metrics": "0.2.6",
|
||||
"@boxyhq/saml20": "1.5.0",
|
||||
"@googleapis/admin": "17.1.0",
|
||||
"@boxyhq/metrics": "0.2.7",
|
||||
"@boxyhq/saml20": "1.5.1",
|
||||
"@googleapis/admin": "18.0.0",
|
||||
"axios": "1.6.8",
|
||||
"encoding": "0.1.13",
|
||||
"jose": "5.2.4",
|
||||
|
@ -23623,6 +23530,211 @@
|
|||
"npm": ">=8"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@boxyhq/metrics": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@boxyhq/metrics/-/metrics-0.2.7.tgz",
|
||||
"integrity": "sha512-2J5mzX8eooTSAuNKUHJhZzhYTq2cFIWSvng1hB+HywC4xO3ERAhLTahgdVky3e5lbEqxcNviLbDpI2Yehxx/NA==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/api": "1.8.0",
|
||||
"@opentelemetry/exporter-metrics-otlp-grpc": "0.51.0",
|
||||
"@opentelemetry/exporter-metrics-otlp-http": "0.51.0",
|
||||
"@opentelemetry/resources": "1.24.0",
|
||||
"@opentelemetry/sdk-metrics": "1.24.0",
|
||||
"@opentelemetry/semantic-conventions": "1.24.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/api": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.8.0.tgz",
|
||||
"integrity": "sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==",
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/api-logs": {
|
||||
"version": "0.51.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.51.0.tgz",
|
||||
"integrity": "sha512-m/jtfBPEIXS1asltl8fPQtO3Sb1qMpuL61unQajUmM8zIxeMF1AlqzWXM3QedcYgTTFiJCew5uJjyhpmqhc0+g==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/api": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/core": {
|
||||
"version": "1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.24.0.tgz",
|
||||
"integrity": "sha512-FP2oN7mVPqcdxJDTTnKExj4mi91EH+DNuArKfHTjPuJWe2K1JfMIVXNfahw1h3onJxQnxS8K0stKkogX05s+Aw==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/semantic-conventions": "1.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": ">=1.0.0 <1.9.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/exporter-metrics-otlp-grpc": {
|
||||
"version": "0.51.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.51.0.tgz",
|
||||
"integrity": "sha512-Ezps36AN5ukLlH3k3Or+im7MiJDq7Sm2rqOggSfCB4NY94RAHlL0VI9vgUlBmaq1Kn+pGEZwb39FC6vv0S0mzw==",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.7.1",
|
||||
"@opentelemetry/core": "1.24.0",
|
||||
"@opentelemetry/exporter-metrics-otlp-http": "0.51.0",
|
||||
"@opentelemetry/otlp-grpc-exporter-base": "0.51.0",
|
||||
"@opentelemetry/otlp-transformer": "0.51.0",
|
||||
"@opentelemetry/resources": "1.24.0",
|
||||
"@opentelemetry/sdk-metrics": "1.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/exporter-metrics-otlp-http": {
|
||||
"version": "0.51.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.51.0.tgz",
|
||||
"integrity": "sha512-e4x0Ybb4qrk7Ux3fTFdU6OBv9qbbp4413zddbjTJlcyoXu8S6Twc0waX3wfkEBbAotut9JtoZG1kp4RQ435yTQ==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/core": "1.24.0",
|
||||
"@opentelemetry/otlp-exporter-base": "0.51.0",
|
||||
"@opentelemetry/otlp-transformer": "0.51.0",
|
||||
"@opentelemetry/resources": "1.24.0",
|
||||
"@opentelemetry/sdk-metrics": "1.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/otlp-exporter-base": {
|
||||
"version": "0.51.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.51.0.tgz",
|
||||
"integrity": "sha512-hR4c9vWVz1QgzCBSyy9zSDkvfTgaK96E6/tfVP6O4dzdZW9HqWimA3lXV/KXadEGqShvM4GToz9EHp2A5RU5bQ==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/core": "1.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/otlp-grpc-exporter-base": {
|
||||
"version": "0.51.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.51.0.tgz",
|
||||
"integrity": "sha512-oTRtDvvB0bTRTBVrvKA/oM1gIAqQ6DVQS07pvqiL1cZS8wBrGgpw+2iTd0nV661Y/MhDn/kNWp8lRhMEIKN9bw==",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.7.1",
|
||||
"@opentelemetry/core": "1.24.0",
|
||||
"@opentelemetry/otlp-exporter-base": "0.51.0",
|
||||
"protobufjs": "^7.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/otlp-transformer": {
|
||||
"version": "0.51.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.51.0.tgz",
|
||||
"integrity": "sha512-ylLgx2xumVoSefDHP9GMAU/LG+TU3+8eacVDXV5o1RqWxsdVOaQmCTY0XyDgeRTn6hIOVAq/HHQbRq3iWOrt2A==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/api-logs": "0.51.0",
|
||||
"@opentelemetry/core": "1.24.0",
|
||||
"@opentelemetry/resources": "1.24.0",
|
||||
"@opentelemetry/sdk-logs": "0.51.0",
|
||||
"@opentelemetry/sdk-metrics": "1.24.0",
|
||||
"@opentelemetry/sdk-trace-base": "1.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": ">=1.3.0 <1.9.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/resources": {
|
||||
"version": "1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.24.0.tgz",
|
||||
"integrity": "sha512-mxC7E7ocUS1tLzepnA7O9/G8G6ZTdjCH2pXme1DDDuCuk6n2/53GADX+GWBuyX0dfIxeMInIbJAdjlfN9GNr6A==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/core": "1.24.0",
|
||||
"@opentelemetry/semantic-conventions": "1.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": ">=1.0.0 <1.9.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/sdk-logs": {
|
||||
"version": "0.51.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.51.0.tgz",
|
||||
"integrity": "sha512-K4fMBRFD8hQ6khk0rvYFuo6L9ymeGgByir6BcuFIgQuQ00OhYwBi9AruZz5V733Ejq7P8ObR3YyubkOUIbeVAw==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/core": "1.24.0",
|
||||
"@opentelemetry/resources": "1.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": ">=1.4.0 <1.9.0",
|
||||
"@opentelemetry/api-logs": ">=0.39.1"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/sdk-metrics": {
|
||||
"version": "1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.24.0.tgz",
|
||||
"integrity": "sha512-4tJ+E6N019OZVB/nUW/LoK9xHxfeh88TCoaTqHeLBE9wLYfi6irWW6J9cphMav7J8Qk0D5b7/RM4VEY4dArWOA==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/core": "1.24.0",
|
||||
"@opentelemetry/resources": "1.24.0",
|
||||
"lodash.merge": "^4.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": ">=1.3.0 <1.9.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/sdk-trace-base": {
|
||||
"version": "1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.24.0.tgz",
|
||||
"integrity": "sha512-H9sLETZ4jw9UJ3totV8oM5R0m4CW0ZIOLfp4NV3g0CM8HD5zGZcaW88xqzWDgiYRpctFxd+WmHtGX/Upoa2vRg==",
|
||||
"dependencies": {
|
||||
"@opentelemetry/core": "1.24.0",
|
||||
"@opentelemetry/resources": "1.24.0",
|
||||
"@opentelemetry/semantic-conventions": "1.24.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": ">=1.0.0 <1.9.0"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@opentelemetry/semantic-conventions": {
|
||||
"version": "1.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.24.0.tgz",
|
||||
"integrity": "sha512-yL0jI6Ltuz8R+Opj7jClGrul6pOoYrdfVmzQS4SITXRPH7I5IRZbrwe/6/v8v4WYMa6MYZG480S1+uc/IGfqsA==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"npm/node_modules/@types/node": {
|
||||
"version": "20.12.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.8.tgz",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "jackson",
|
||||
"version": "1.23.6",
|
||||
"version": "1.23.7",
|
||||
"private": true,
|
||||
"description": "SAML 2.0 service",
|
||||
"keywords": [
|
||||
|
|
|
@ -2,7 +2,7 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
|||
|
||||
import jackson from '@lib/jackson';
|
||||
|
||||
export { default } from 'ee/federated-saml/pages/edit';
|
||||
export { default } from '@ee/identity-federation/pages/edit';
|
||||
|
||||
export async function getServerSideProps({ locale }) {
|
||||
const { checkLicense } = await jackson();
|
|
@ -2,7 +2,7 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
|||
|
||||
import jackson from '@lib/jackson';
|
||||
|
||||
export { default } from 'ee/federated-saml/pages/index';
|
||||
export { default } from '@ee/identity-federation/pages/index';
|
||||
|
||||
export async function getServerSideProps({ locale }) {
|
||||
const { checkLicense } = await jackson();
|
|
@ -3,7 +3,7 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
|||
import jackson from '@lib/jackson';
|
||||
import { jacksonOptions } from '@lib/env';
|
||||
|
||||
export { default } from 'ee/federated-saml/pages/new';
|
||||
export { default } from '@ee/identity-federation/pages/new';
|
||||
|
||||
export async function getServerSideProps({ locale }) {
|
||||
const { checkLicense } = await jackson();
|
|
@ -10,8 +10,8 @@ const SSOTraceInspector: NextPage = () => {
|
|||
|
||||
return (
|
||||
<div className='space-y-4'>
|
||||
<LinkBack href='/admin/sso-tracer' />
|
||||
<SSOTracerInfo urls={{ getTracer: `/api/admin/sso-tracer/${traceId}` }} />
|
||||
<LinkBack href='/admin/sso-traces' />
|
||||
<SSOTracerInfo urls={{ getTracer: `/api/admin/sso-traces/${traceId}` }} />
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -8,8 +8,8 @@ const SSOTraceViewer: NextPage = () => {
|
|||
|
||||
return (
|
||||
<SSOTracers
|
||||
urls={{ getTracers: '/api/admin/sso-tracer' }}
|
||||
onView={(trace) => router.push(`/admin/sso-tracer/${trace.traceId}/inspect`)}
|
||||
urls={{ getTracers: '/api/admin/sso-traces' }}
|
||||
onView={(trace) => router.push(`/admin/sso-traces/${trace.traceId}/inspect`)}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
export { default } from 'ee/federated-saml/api/admin/[id]/index';
|
|
@ -1 +0,0 @@
|
|||
export { default } from 'ee/federated-saml/api/admin/index';
|
|
@ -0,0 +1 @@
|
|||
export { default } from '@ee/identity-federation/api/admin/[id]/index';
|
|
@ -0,0 +1 @@
|
|||
export { default } from '@ee/identity-federation/api/admin/index';
|
|
@ -1 +1 @@
|
|||
export { default } from 'ee/federated-saml/api/sso';
|
||||
export { default } from '@ee/identity-federation/api/sso';
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export { default } from '@ee/identity-federation/api/sso';
|
|
@ -1 +0,0 @@
|
|||
export { default } from 'ee/federated-saml/api/v1/index';
|
|
@ -1 +0,0 @@
|
|||
export { default } from 'ee/federated-saml/api/v1/product';
|
|
@ -0,0 +1 @@
|
|||
export { default } from '@ee/identity-federation/api/v1/index';
|
|
@ -0,0 +1 @@
|
|||
export { default } from '@ee/identity-federation/api/v1/product';
|
|
@ -20,15 +20,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||
}
|
||||
|
||||
const handleGET = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { connectionAPIController, directorySyncController } = await jackson();
|
||||
const { connectionAPIController, directorySyncController, samlFederatedController } = await jackson();
|
||||
|
||||
const sso_connections_count = await connectionAPIController.getCount();
|
||||
const dsync_connections_count = await directorySyncController.directories.getCount();
|
||||
const identity_federation_count = await samlFederatedController.app.getCount();
|
||||
|
||||
return res.json({
|
||||
data: {
|
||||
sso_connections: sso_connections_count,
|
||||
dsync_connections: dsync_connections_count,
|
||||
identity_federation_apps: identity_federation_count,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
|
@ -38,7 +38,7 @@ const handlePOST = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
// Get counts for product
|
||||
let sso_connections_count = 0;
|
||||
let dsync_connections_count = 0;
|
||||
let saml_federation_count = 0;
|
||||
let identity_federation_count = 0;
|
||||
|
||||
for (const product of products) {
|
||||
if (product) {
|
||||
|
@ -60,7 +60,7 @@ const handlePOST = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
name: IndexNames.Product,
|
||||
value: product,
|
||||
});
|
||||
saml_federation_count += count || 0;
|
||||
identity_federation_count += count || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ const handlePOST = async (req: NextApiRequest, res: NextApiResponse) => {
|
|||
data: {
|
||||
sso_connections: sso_connections_count,
|
||||
dsync_connections: dsync_connections_count,
|
||||
saml_federation: saml_federation_count,
|
||||
identity_federation_apps: identity_federation_count,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
export { default } from 'ee/federated-saml/api/metadata';
|
||||
export { default } from '@ee/identity-federation/api/metadata';
|
||||
|
|
|
@ -203,7 +203,7 @@ export const getServerSideProps = async ({ query, locale, req }) => {
|
|||
const params = new URLSearchParams(paramsToRelay);
|
||||
const destination =
|
||||
samlFedAppId && fedType !== 'oidc'
|
||||
? `/api/federated-saml/sso?${params}`
|
||||
? `/api/identity-federation/sso?${params}`
|
||||
: `/api/oauth/authorize?${params}`;
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||
import jackson from '@lib/jackson';
|
||||
|
||||
export { default } from 'ee/federated-saml/pages/metadata';
|
||||
export { default } from '@ee/identity-federation/pages/metadata';
|
||||
|
||||
export async function getServerSideProps({ locale }) {
|
||||
const { samlFederatedController, checkLicense } = await jackson();
|
||||
|
|
|
@ -22,7 +22,8 @@ const config: PlaywrightTestConfig = {
|
|||
timeout: 60 * 1000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
env: {
|
||||
NODE_ENV: 'test',
|
||||
DEBUG: 'pw:webserver',
|
||||
NEXTAUTH_ADMIN_CREDENTIALS: 'super@boxyhq.com:999login',
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"openapi": "3.0.3",
|
||||
"info": {
|
||||
"title": "Enterprise SSO & Directory Sync",
|
||||
"version": "1.20.6",
|
||||
"version": "1.23.5",
|
||||
"description": "This is the API documentation for SAML Jackson service.",
|
||||
"termsOfService": "https://boxyhq.com/terms.html",
|
||||
"contact": {
|
||||
|
@ -1354,7 +1354,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/federated-saml": {
|
||||
"/api/v1/identity-federation": {
|
||||
"post": {
|
||||
"summary": "Create an Identity Federation app",
|
||||
"parameters": [
|
||||
|
@ -1459,7 +1459,7 @@
|
|||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SAMLFederationApp"
|
||||
"$ref": "#/definitions/IdentityFederationApp"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1500,7 +1500,7 @@
|
|||
"200": {
|
||||
"description": "Success",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/SAMLFederationApp"
|
||||
"$ref": "#/definitions/IdentityFederationApp"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1593,7 +1593,7 @@
|
|||
"200": {
|
||||
"description": "Success",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/SAMLFederationApp"
|
||||
"$ref": "#/definitions/IdentityFederationApp"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1633,13 +1633,13 @@
|
|||
"200": {
|
||||
"description": "Success",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/SAMLFederationApp"
|
||||
"$ref": "#/definitions/IdentityFederationApp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/federated-saml/product": {
|
||||
"/api/v1/identity-federation/product": {
|
||||
"get": {
|
||||
"summary": "Get Identity Federation apps by product",
|
||||
"parameters": [
|
||||
|
@ -1677,7 +1677,7 @@
|
|||
"data": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SAMLFederationApp"
|
||||
"$ref": "#/definitions/IdentityFederationApp"
|
||||
}
|
||||
},
|
||||
"pageToken": {
|
||||
|
@ -2034,7 +2034,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"SAMLFederationApp": {
|
||||
"IdentityFederationApp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
|
|
Loading…
Reference in New Issue