Skip to content

Commit efe9741

Browse files
committed
db/account: refactor checkRequiredSSO and use it to check, if modifying the email_address is allowed or if update_on_login is set, additionally prohibit changing first or last name
1 parent c85f74a commit efe9741

File tree

12 files changed

+75
-20
lines changed

12 files changed

+75
-20
lines changed

src/packages/database/postgres-server-queries.coffee

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ read = require('read')
6161
{pii_expire} = require("./postgres/pii")
6262
passwordHash = require("@cocalc/backend/auth/password-hash").default;
6363
registrationTokens = require('./postgres/registration-tokens').default;
64+
getStrategiesSSO = require("@cocalc/database/settings/get-sso-strategies").default;
6465

6566
stripe_name = require('@cocalc/util/stripe/name').default;
6667

@@ -2647,6 +2648,19 @@ exports.extend_PostgreSQL = (ext) -> class PostgreSQL extends ext
26472648
return result.rows[0].organization_id
26482649
return undefined
26492650

2651+
getStrategiesSSO: () =>
2652+
return await getStrategiesSSO()
2653+
2654+
get_email_address_for_account_id: (account_id) =>
2655+
result = await @async_query
2656+
query : 'SELECT email_address FROM accounts'
2657+
where : [ 'account_id :: UUID = $1' ]
2658+
params : [ account_id ]
2659+
if result.rows.length > 0
2660+
result.rows[0].email_address
2661+
else
2662+
return undefined
2663+
26502664
# async
26512665
registrationTokens: (options, query) =>
26522666
return await registrationTokens(@, options, query)

src/packages/database/postgres/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
QueryRows,
1515
UntypedQueryResult,
1616
} from "@cocalc/util/types/database";
17+
import type { Strategy } from "@cocalc/util/types/sso";
1718
import { Changes } from "./changefeed";
1819

1920
export type { QueryResult };
@@ -317,6 +318,8 @@ export interface PostgreSQL extends EventEmitter {
317318
email_address: string;
318319
}>;
319320
}): Promise<void>;
321+
322+
getStrategiesSSO(): Promise<Strategy[]>;
320323
}
321324

322325
export interface SetAccountFields {

src/packages/database/settings/get-sso-strategies.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ export default async function getStrategies(): Promise<Strategy[]> {
1919
COALESCE(info -> 'display', conf -> 'display') as display,
2020
COALESCE(info -> 'public', conf -> 'public') as public,
2121
COALESCE(info -> 'exclusive_domains', conf -> 'exclusive_domains') as exclusive_domains,
22-
COALESCE(info -> 'do_not_hide', 'false'::JSONB) as do_not_hide
22+
COALESCE(info -> 'do_not_hide', 'false'::JSONB) as do_not_hide,
23+
COALESCE(info -> 'update_on_login', 'false'::JSONB) as update_on_login
2324
2425
FROM passport_settings
2526
WHERE strategy != 'site_conf'
@@ -39,6 +40,7 @@ export default async function getStrategies(): Promise<Strategy[]> {
3940
public: row.public ?? true,
4041
exclusiveDomains: row.exclusive_domains ?? [],
4142
doNotHide: row.do_not_hide ?? false,
43+
updateOnLogin: row.update_on_login ?? false,
4244
};
4345
});
4446
}

src/packages/next/components/auth/sso.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { join } from "path";
99
import { CSSProperties, ReactNode, useMemo } from "react";
1010

1111
import { Icon } from "@cocalc/frontend/components/icon";
12-
import { checkRequiredSSO } from "@cocalc/server/auth/sso/check-required-sso";
12+
import { checkRequiredSSO } from "@cocalc/util/auth-check-required-sso";
1313
import { PRIMARY_SSO } from "@cocalc/util/types/passport-types";
1414
import { Strategy } from "@cocalc/util/types/sso";
1515
import Loading from "components/share/loading";
@@ -67,6 +67,7 @@ export default function SSO(props: SSOProps) {
6767
public: true,
6868
exclusiveDomains: [],
6969
doNotHide: true,
70+
updateOnLogin: false,
7071
};
7172

7273
return (

src/packages/server/accounts/set-email-address.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import passwordHash, {
2121
verifyPassword,
2222
} from "@cocalc/backend/auth/password-hash";
2323
import getPool from "@cocalc/database/pool";
24-
import { checkRequiredSSO } from "@cocalc/server/auth/sso/check-required-sso";
24+
import { checkRequiredSSO } from "@cocalc/util/auth-check-required-sso";
2525
import getStrategies from "@cocalc/database/settings/get-sso-strategies";
2626
import {
2727
isValidUUID,

src/packages/server/auth/check-email-exclusive-sso.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { PostgreSQL } from "@cocalc/database/postgres/types";
77
import getStrategies from "@cocalc/database/settings/get-sso-strategies";
8-
import { checkRequiredSSO } from "@cocalc/server/auth/sso/check-required-sso";
8+
import { checkRequiredSSO } from "@cocalc/util/auth-check-required-sso";
99

1010
export async function checkEmailExclusiveSSO(
1111
db: PostgreSQL,

src/packages/server/auth/sso/passport-login.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ import { sanitizeProfile } from "@cocalc/server/auth/sso/sanitize-profile";
4545
import { callback2 as cb2 } from "@cocalc/util/async-utils";
4646
import { is_valid_email_address } from "@cocalc/util/misc";
4747
import { HELP_EMAIL } from "@cocalc/util/theme";
48-
import { emailBelongsToDomain, getEmailDomain } from "./check-required-sso";
48+
import { emailBelongsToDomain } from "@cocalc/util/auth-check-required-sso";
4949
import { SSO_API_KEY_COOKIE_NAME } from "./consts";
50+
import { getEmailDomain } from "@cocalc/util/auth-check-required-sso";
5051

5152
const logger = getLogger("server:auth:sso:passport-login");
5253

@@ -240,7 +241,7 @@ export class PassportLogin {
240241
const exclusiveDomains = strategy.info?.exclusive_domains ?? [];
241242
if (!isEmpty(exclusiveDomains)) {
242243
for (const email of opts.emails ?? []) {
243-
const emailDomain = getEmailDomain(email.toLocaleLowerCase());
244+
const emailDomain = getEmailDomain(email.toLowerCase());
244245
for (const ssoDomain of exclusiveDomains) {
245246
if (emailBelongsToDomain(emailDomain, ssoDomain)) {
246247
return true;
@@ -253,7 +254,7 @@ export class PassportLogin {
253254

254255
// similar to the above, for a specific email address
255256
private checkEmailExclusiveSSO(email_address: string): boolean {
256-
const emailDomain = getEmailDomain(email_address.toLocaleLowerCase());
257+
const emailDomain = getEmailDomain(email_address.toLowerCase());
257258
for (const strategyName in this.opts.passports) {
258259
const strategy = this.opts.passports[strategyName];
259260
for (const ssoDomain of strategy.info?.exclusive_domains ?? []) {
@@ -510,7 +511,7 @@ export class PassportLogin {
510511
}
511512

512513
// We update the email address, if it does not belong to another account.
513-
514+
514515
if (is_valid_email_address(locals.email_address)) {
515516
upd.email_address = locals.email_address;
516517
}

src/packages/server/auth/sso/unlink-strategy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ upstream SSO provider.
1212
import getPool from "@cocalc/database/pool";
1313
import getStrategies from "@cocalc/database/settings/get-sso-strategies";
1414
import { is_valid_uuid_string } from "@cocalc/util/misc";
15-
import { checkRequiredSSO } from "./check-required-sso";
15+
import { checkRequiredSSO } from "@cocalc/util/auth-check-required-sso";
1616

1717
// The name should be something like "google-9999601658192", i.e., a key
1818
// of the passports field.

src/packages/server/auth/throttle.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ the database.
77
import LRU from "lru-cache";
88

99
import getStrategies from "@cocalc/database/settings/get-sso-strategies";
10-
import { checkRequiredSSO } from "./sso/check-required-sso";
10+
import { checkRequiredSSO } from "@cocalc/util/auth-check-required-sso";
1111

1212
const emailShortCache = new LRU<string, number>({
1313
max: 10000, // avoid memory issues

src/packages/server/auth/sso/check-required-sso.ts renamed to src/packages/util/auth-check-required-sso.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,19 @@
55

66
import { Strategy } from "@cocalc/util/types/sso";
77

8-
/**
9-
* If the domain of a given email address belongs to an SSO strategy,
10-
* which is configured to be an "exclusive" domain, then return the Strategy.
11-
* This also matches subdomains, i.e. "foo@bar.baz.edu" is goverend by "baz.edu".
12-
*/
13-
148
interface Opts {
159
email: string | undefined;
1610
strategies: Strategy[] | undefined;
1711
specificStrategy?: string;
1812
}
1913

14+
/**
15+
* If the domain of a given email address belongs to an SSO strategy,
16+
* which is configured to be an "exclusive" domain, then return the Strategy.
17+
* This also matches subdomains, i.e. "foo@bar.baz.edu" is goverend by "baz.edu".
18+
*
19+
* Optionally, if @specificStrategy is set, only that strategy is checked!
20+
*/
2021
export function checkRequiredSSO(opts: Opts): Strategy | undefined {
2122
const { email, strategies, specificStrategy } = opts;
2223
// if the domain of email is contained in any of the strategie's exclusiveDomain array, return that strategy's name

0 commit comments

Comments
 (0)