console/integration-tests/testkit/auth.ts

171 lines
4.3 KiB
TypeScript
Raw Normal View History

import { z } from 'zod';
import type { InternalApi } from '@hive/server';
2022-12-28 19:22:54 +00:00
import { createTRPCProxyClient, httpLink } from '@trpc/client';
2022-05-18 07:26:57 +00:00
import { ensureEnv } from './env';
import { getServiceHost } from './utils';
const SignUpSignInUserResponseModel = z
.object({
status: z.literal('OK'),
user: z.object({
emails: z.array(z.string()),
id: z.string(),
timeJoined: z.number(),
}),
})
.refine(response => response.user.emails.length === 1)
.transform(response => ({
...response,
user: {
id: response.user.id,
email: response.user.emails[0],
timeJoined: response.user.timeJoined,
},
}));
2022-05-18 07:26:57 +00:00
feat: replace auth0 with supertokens (#303) * add supertoken container to docker-compose file * yeah I am sorry this one big commit and I am ashamed of it * use logOut function * feat: show header on 404 page * feat: better handling for organization cookie when not authenticated * wrap it * check session within server side props * add is_admin flag user migration * simplify and annotate the config * fix: handle status codes + fix email/password sign up with import from auth0 * no hardcoded env pls * decode process.env * secure update user id mapping via a key * fix: login form * lol we don't need to hit the API * fix: do graphql api authorization via authorization header instead of cookie * implement isAdmin flag * fix: types :) * skipit * yo we can run this * set env variables * disable because it annoys the hell out of me * use the right host * add not about token length * refactor: decode environment variables * feat: store external user id from guthub/google provider in the database * workaround supertokens omitting null values from the token * re-enable check * i have no time for this shit * add missing env variable * fix: email test; missing domain extension * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> * fix: env names * fix: link google account to the correct db record * feat: email confirmation emails * ? * bump ts-node * fix types * omit package form the bundle * remove it from dependencies... * add emails apckage to dev deps * resolve eslint issues * remove comments * update dev info + change env variable (no need to expose it on the frontend) * use correct user id lol Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com>
2022-09-06 07:38:31 +00:00
const signUpUserViaEmail = async (
email: string,
password: string,
): Promise<z.TypeOf<typeof SignUpSignInUserResponseModel>> => {
try {
2023-07-20 08:44:27 +00:00
const response = await fetch(
`${ensureEnv('SUPERTOKENS_CONNECTION_URI')}/appid-public/public/recipe/signup`,
{
method: 'POST',
headers: {
'content-type': 'application/json; charset=UTF-8',
'api-key': ensureEnv('SUPERTOKENS_API_KEY'),
'cdi-version': '4.0',
2023-07-20 08:44:27 +00:00
},
body: JSON.stringify({
email,
password,
}),
},
2023-07-20 08:44:27 +00:00
);
const body = await response.text();
if (response.status !== 200) {
throw new Error(`Signup failed. ${response.status}.\n ${body}`);
}
return SignUpSignInUserResponseModel.parse(JSON.parse(body));
} catch (e) {
console.warn(`Failed to sign up:`, e);
throw e;
feat: replace auth0 with supertokens (#303) * add supertoken container to docker-compose file * yeah I am sorry this one big commit and I am ashamed of it * use logOut function * feat: show header on 404 page * feat: better handling for organization cookie when not authenticated * wrap it * check session within server side props * add is_admin flag user migration * simplify and annotate the config * fix: handle status codes + fix email/password sign up with import from auth0 * no hardcoded env pls * decode process.env * secure update user id mapping via a key * fix: login form * lol we don't need to hit the API * fix: do graphql api authorization via authorization header instead of cookie * implement isAdmin flag * fix: types :) * skipit * yo we can run this * set env variables * disable because it annoys the hell out of me * use the right host * add not about token length * refactor: decode environment variables * feat: store external user id from guthub/google provider in the database * workaround supertokens omitting null values from the token * re-enable check * i have no time for this shit * add missing env variable * fix: email test; missing domain extension * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> * fix: env names * fix: link google account to the correct db record * feat: email confirmation emails * ? * bump ts-node * fix types * omit package form the bundle * remove it from dependencies... * add emails apckage to dev deps * resolve eslint issues * remove comments * update dev info + change env variable (no need to expose it on the frontend) * use correct user id lol Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com>
2022-09-06 07:38:31 +00:00
}
};
const createSessionPayload = (superTokensUserId: string, email: string) => ({
version: '1',
superTokensUserId,
email,
});
const CreateSessionModel = z.object({
accessToken: z.object({
token: z.string(),
feat: replace auth0 with supertokens (#303) * add supertoken container to docker-compose file * yeah I am sorry this one big commit and I am ashamed of it * use logOut function * feat: show header on 404 page * feat: better handling for organization cookie when not authenticated * wrap it * check session within server side props * add is_admin flag user migration * simplify and annotate the config * fix: handle status codes + fix email/password sign up with import from auth0 * no hardcoded env pls * decode process.env * secure update user id mapping via a key * fix: login form * lol we don't need to hit the API * fix: do graphql api authorization via authorization header instead of cookie * implement isAdmin flag * fix: types :) * skipit * yo we can run this * set env variables * disable because it annoys the hell out of me * use the right host * add not about token length * refactor: decode environment variables * feat: store external user id from guthub/google provider in the database * workaround supertokens omitting null values from the token * re-enable check * i have no time for this shit * add missing env variable * fix: email test; missing domain extension * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> * fix: env names * fix: link google account to the correct db record * feat: email confirmation emails * ? * bump ts-node * fix types * omit package form the bundle * remove it from dependencies... * add emails apckage to dev deps * resolve eslint issues * remove comments * update dev info + change env variable (no need to expose it on the frontend) * use correct user id lol Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com>
2022-09-06 07:38:31 +00:00
}),
refreshToken: z.object({
token: z.string(),
feat: replace auth0 with supertokens (#303) * add supertoken container to docker-compose file * yeah I am sorry this one big commit and I am ashamed of it * use logOut function * feat: show header on 404 page * feat: better handling for organization cookie when not authenticated * wrap it * check session within server side props * add is_admin flag user migration * simplify and annotate the config * fix: handle status codes + fix email/password sign up with import from auth0 * no hardcoded env pls * decode process.env * secure update user id mapping via a key * fix: login form * lol we don't need to hit the API * fix: do graphql api authorization via authorization header instead of cookie * implement isAdmin flag * fix: types :) * skipit * yo we can run this * set env variables * disable because it annoys the hell out of me * use the right host * add not about token length * refactor: decode environment variables * feat: store external user id from guthub/google provider in the database * workaround supertokens omitting null values from the token * re-enable check * i have no time for this shit * add missing env variable * fix: email test; missing domain extension * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> * fix: env names * fix: link google account to the correct db record * feat: email confirmation emails * ? * bump ts-node * fix types * omit package form the bundle * remove it from dependencies... * add emails apckage to dev deps * resolve eslint issues * remove comments * update dev info + change env variable (no need to expose it on the frontend) * use correct user id lol Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com>
2022-09-06 07:38:31 +00:00
}),
});
const createSession = async (
superTokensUserId: string,
email: string,
oidcIntegrationId: string | null,
) => {
try {
const graphqlAddress = await getServiceHost('server', 8082);
const internalApi = createTRPCProxyClient<InternalApi>({
links: [
httpLink({
url: `http://${graphqlAddress}/trpc`,
fetch,
}),
],
});
await internalApi.ensureUser.mutate({
superTokensUserId,
email,
oidcIntegrationId,
firstName: null,
lastName: null,
});
const sessionData = createSessionPayload(superTokensUserId, email);
const payload = {
enableAntiCsrf: false,
userId: superTokensUserId,
userDataInDatabase: sessionData,
userDataInJWT: sessionData,
};
2023-07-20 08:44:27 +00:00
const response = await fetch(
`${ensureEnv('SUPERTOKENS_CONNECTION_URI')}/appid-public/public/recipe/session`,
{
method: 'POST',
headers: {
'content-type': 'application/json; charset=UTF-8',
'api-key': ensureEnv('SUPERTOKENS_API_KEY'),
rid: 'session',
'cdi-version': '4.0',
2023-07-20 08:44:27 +00:00
},
body: JSON.stringify(payload),
},
2023-07-20 08:44:27 +00:00
);
const body = await response.text();
if (response.status !== 200) {
throw new Error(`Create session failed. ${response.status}.\n ${body}`);
}
const data = CreateSessionModel.parse(JSON.parse(body));
/**
* These are the required cookies that need to be set.
*/
return {
access_token: data.accessToken.token,
refresh_token: data.refreshToken.token,
};
} catch (e) {
console.warn(`Failed to create session:`, e);
throw e;
feat: replace auth0 with supertokens (#303) * add supertoken container to docker-compose file * yeah I am sorry this one big commit and I am ashamed of it * use logOut function * feat: show header on 404 page * feat: better handling for organization cookie when not authenticated * wrap it * check session within server side props * add is_admin flag user migration * simplify and annotate the config * fix: handle status codes + fix email/password sign up with import from auth0 * no hardcoded env pls * decode process.env * secure update user id mapping via a key * fix: login form * lol we don't need to hit the API * fix: do graphql api authorization via authorization header instead of cookie * implement isAdmin flag * fix: types :) * skipit * yo we can run this * set env variables * disable because it annoys the hell out of me * use the right host * add not about token length * refactor: decode environment variables * feat: store external user id from guthub/google provider in the database * workaround supertokens omitting null values from the token * re-enable check * i have no time for this shit * add missing env variable * fix: email test; missing domain extension * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com> * configure pulumi deployment Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> * fix: env names * fix: link google account to the correct db record * feat: email confirmation emails * ? * bump ts-node * fix types * omit package form the bundle * remove it from dependencies... * add emails apckage to dev deps * resolve eslint issues * remove comments * update dev info + change env variable (no need to expose it on the frontend) * use correct user id lol Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com> Co-authored-by: Dotan Simha <dotansimha@gmail.com>
2022-09-06 07:38:31 +00:00
}
};
const password = 'ilikebigturtlesandicannotlie47';
2022-05-18 07:26:57 +00:00
export function userEmail(userId: string) {
return `${userId}-${Date.now()}@localhost.localhost`;
}
2022-05-18 07:26:57 +00:00
const tokenResponsePromise: {
[key: string]: Promise<z.TypeOf<typeof SignUpSignInUserResponseModel>> | null;
} = {};
2022-05-18 07:26:57 +00:00
export function authenticate(
email: string,
): Promise<{ access_token: string; refresh_token: string }>;
export function authenticate(
email: string,
oidcIntegrationId?: string,
): Promise<{ access_token: string; refresh_token: string }>;
export function authenticate(
email: string | string,
oidcIntegrationId?: string,
): Promise<{ access_token: string; refresh_token: string }> {
if (!tokenResponsePromise[email]) {
tokenResponsePromise[email] = signUpUserViaEmail(email, password);
2022-05-18 07:26:57 +00:00
}
return tokenResponsePromise[email]!.then(data =>
createSession(data.user.id, data.user.email, oidcIntegrationId ?? null),
feat: OIDC organisation integration (#524) * feat: support login via okta * add deployment config * feat: automatically start okta login when visiting /auth with okta provider query parameter * remove trailing slash from base url * laurin pls * ... * adjust deployment url * we dont need this * docs: document how to enabled Google and GitHub social login (#511) * docs: document how to enabled Google and GitHub social login * Apply suggestions from code review * Apply suggestions from code review * docs: add Okta instructions * fix typo * add database migration * feat: env decoding * auto generate id * add generates types for the postgres table * implement crud graphql fields for the oidc integration entites * add unique constraint for the oidc domain column * use correct sql query for updating an oidc integration * return organization from deleteOIDCIntegration ok result * add crud forms to the settings page * update integration test fixture value * drop unique constraint for oidc_integrations.domain as this would allow a malicous user to block another account from using a domain * move notice to isolated component * apply url normalization in a central place * implement supertokens provider and overrides for dynamic oidc provider integrations * relocate code to correct files * prettify oidc crud forms * replace Query.isOIDCIntegrationFeatureEnabled with the Organization.viewerCanManageOIDCIntegration field * do not show oidc integrations for personal organizations + disable crud endpoints if the feature is disabled * load oidc integration for the supertokens flow via trpc from the server * prepare encryption secret within constructor * add user to organization upon oidc login * login via oidc does not create a personal organization * redirect oidc user to oidc organization * disallow oidc users to create an organization * disallow oidc accounts joining another organization * add test for updating an oidc integration * enhance ui * add documentation for OIDC SSO * add more tests * import Callout component * update snapshots * rename field User.isLinkedToOIDCIntegration to User.canSwitchOrganization to be more decriptive * add traling new line * gracefully handle unique constraint * upgrade supertokens-auth-react and adjust the code in order to remove the global preApiHook * sync image versions with tests * remove obsolete comment * rename database column * bruv * add test for oidc user deletion
2022-11-03 15:45:17 +00:00
);
2022-05-18 07:26:57 +00:00
}