Google SCIM Authorize tweaks (#2421)

* Update google SCIM authz options

* Sync lock file

* Remove the old option support, should reflect in typings

* Fix failing test

* Sync lock file

* Include google_authorization_url in directory response

* Update internal-ui to use url from directory config

* Update component usage in Jackson UI

* Cleanup example env

---------

Co-authored-by: Deepak Prabhakara <deepak@boxyhq.com>
This commit is contained in:
Aswin V 2024-03-13 00:52:11 +05:30 committed by GitHub
parent 034affeb7a
commit 73b9d8a65d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 20 additions and 17 deletions

View File

@ -95,7 +95,6 @@ DSYNC_WEBHOOK_BATCH_SIZE=
# Google workspace directory sync
DSYNC_GOOGLE_CLIENT_ID=
DSYNC_GOOGLE_CLIENT_SECRET=
DSYNC_GOOGLE_REDIRECT_URI=
# Only applicable for BoxyHQ SaaS deployments
BOXYHQ_HOSTED=0

View File

@ -14,7 +14,7 @@ export const DirectoryInfo = ({
hideTabs = false,
displayGoogleAuthButton = false,
}: {
urls: { getDirectory: string; tabBase: string; googleAuth: string };
urls: { getDirectory: string; tabBase: string };
excludeFields?: ExcludeFields[];
hideTabs?: boolean;
displayGoogleAuthButton?: boolean;
@ -48,7 +48,7 @@ export const DirectoryInfo = ({
<div className='space-y-3'>
<p className='text-sm text-gray-600'>{t('bui-dsync-authorization-google-desc')}</p>
<LinkPrimary
href={`${urls.googleAuth}?directoryId=${directory.id}`}
href={`${directory.google_authorization_url}?directoryId=${directory.id}`}
target='_blank'
className='btn-md'
Icon={ArrowTopRightOnSquareIcon}
@ -135,7 +135,7 @@ export const DirectoryInfo = ({
{directory.type === 'google' && (
<div className='form-control mt-6'>
<InputWithCopyButton
text={`${urls.googleAuth}?directoryId=${directory.id}`}
text={`${directory.google_authorization_url}?directoryId=${directory.id}`}
label={t('bui-dsync-google-auth-url')}
/>
</div>

View File

@ -58,6 +58,7 @@ export type Directory = {
google_domain?: string;
google_access_token?: string;
google_refresh_token?: string;
google_authorization_url?: string;
};
export type User = {

View File

@ -3,6 +3,8 @@ import type { DatabaseEngine, DatabaseOption, DatabaseType, JacksonOption } from
const samlPath = '/api/oauth/saml';
const oidcPath = '/api/oauth/oidc';
const idpDiscoveryPath = '/idp/select';
const googleDSyncAuthorizePath = '/api/scim/oauth/authorize';
const googleDSyncCallbackPath = '/api/scim/oauth/callback';
const hostUrl = process.env.HOST_URL || 'localhost';
const hostPort = Number(process.env.PORT || '5225');
@ -95,7 +97,8 @@ const jacksonOptions: JacksonOption = {
google: {
clientId: process.env.DSYNC_GOOGLE_CLIENT_ID || process.env.GOOGLE_CLIENT_ID || '',
clientSecret: process.env.DSYNC_GOOGLE_CLIENT_SECRET || process.env.GOOGLE_CLIENT_SECRET || '',
callbackUrl: process.env.DSYNC_GOOGLE_REDIRECT_URI || process.env.GOOGLE_REDIRECT_URI || '',
authorizePath: googleDSyncAuthorizePath,
callbackPath: googleDSyncCallbackPath,
},
},
},
@ -119,5 +122,3 @@ export { retraced as retracedOptions };
export { terminus as terminusOptions };
export { apiKeys };
export { jacksonOptions };
export const dsyncGoogleAuthURL = externalUrl + '/api/scim/oauth/authorize';

View File

@ -33,7 +33,7 @@ export class GoogleProvider implements IDirectoryProvider {
const authClient = new OAuth2Client(
googleProvider?.clientId,
googleProvider?.clientSecret,
googleProvider?.callbackUrl
`${this.opts.externalUrl}${googleProvider?.callbackPath}`
);
authClient.setCredentials({

View File

@ -29,7 +29,7 @@ export class GoogleAuth {
const authClient = new OAuth2Client(
googleProvider?.clientId,
googleProvider?.clientSecret,
googleProvider?.callbackUrl
`${this.opts.externalUrl}${googleProvider?.callbackPath}`
);
authClient.setCredentials({

View File

@ -606,6 +606,10 @@ export class DirectoryConfig {
directory.scim.endpoint = `${this.opts.externalUrl}${directory.scim.path}`;
}
if (directory.type === 'google') {
directory.google_authorization_url = `${this.opts.externalUrl}${this.opts.dsync?.providers?.google.authorizePath}`;
}
if (!('deactivated' in directory)) {
directory.deactivated = false;
}

View File

@ -62,6 +62,7 @@ export type Directory = {
google_domain?: string;
google_access_token?: string;
google_refresh_token?: string;
google_authorization_url?: string;
};
export type DirectorySyncGroupMember = { value: string; email?: string };

View File

@ -460,7 +460,8 @@ export interface JacksonOption {
google: {
clientId: string;
clientSecret: string;
callbackUrl: string;
authorizePath: string;
callbackPath: string;
};
};
};

View File

@ -60,7 +60,7 @@ tap.test('generate the Google API authorization URL', async (t) => {
prompt: 'consent',
response_type: 'code',
client_id: 'GOOGLE_CLIENT_ID',
redirect_uri: `GOOGLE_REDIRECT_URI`,
redirect_uri: `${jacksonOptions.externalUrl}${jacksonOptions.dsync?.providers?.google.callbackPath}`,
state: JSON.stringify({ directoryId: directory.id }),
scope:
'https://www.googleapis.com/auth/admin.directory.user.readonly https://www.googleapis.com/auth/admin.directory.group.readonly https://www.googleapis.com/auth/admin.directory.group.member.readonly',

View File

@ -41,7 +41,8 @@ const jacksonOptions = <JacksonOption>{
google: {
clientId: 'GOOGLE_CLIENT_ID',
clientSecret: 'GOOGLE_CLIENT_SECRET',
callbackUrl: 'GOOGLE_REDIRECT_URI',
authorizePath: '/GOOGLE_AUTHORIZE_PATH',
callbackPath: '/GOOGLE_CALLBACK_PATH',
},
},
},

View File

@ -2,7 +2,6 @@ import { useRouter } from 'next/router';
import type { NextPage, GetServerSidePropsContext } from 'next';
import { DirectoryInfo, LinkBack } from '@boxyhq/internal-ui';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { dsyncGoogleAuthURL } from '@lib/env';
const DirectoryInfoPage: NextPage = () => {
const router = useRouter();
@ -16,7 +15,6 @@ const DirectoryInfoPage: NextPage = () => {
urls={{
getDirectory: `/api/admin/directory-sync/${directoryId}`,
tabBase: `/admin/directory-sync/${directoryId}`,
googleAuth: dsyncGoogleAuthURL,
}}
/>
</>

View File

@ -4,8 +4,6 @@ import { useRouter } from 'next/router';
import { DirectoryInfo, LinkBack } from '@boxyhq/internal-ui';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { dsyncGoogleAuthURL } from '@lib/env';
const DirectoryDetailsPage: NextPage = () => {
const router = useRouter();
const { token, directoryId } = router.query as { token: string; directoryId: string };
@ -20,7 +18,6 @@ const DirectoryDetailsPage: NextPage = () => {
urls={{
getDirectory: `/api/setup/${token}/directory-sync/${directoryId}`,
tabBase: '',
googleAuth: dsyncGoogleAuthURL,
}}
hideTabs={true}
displayGoogleAuthButton={true}