feat: Validate Google, Azure, OIDC SSO access (#3590)
* chore: Store expiresAt on UserAuthentications. This represents the time that the accessToken is no longer valid and should be exchanged using the refreshToken * feat: Check and expire Google SSO * fix: Better handling of multiple auth methods Added more docs * fix: Retry access validation with network errors * Small refactor, add Azure token validation support * doc * test * lint * OIDC refresh support * CheckSSOAccessTask -> ValidateSSOAccessTask Added lastValidatedAt column Skip checks if validated within 5min Some edge cases around encrypted columns
This commit is contained in:
@@ -39,7 +39,7 @@ if (env.AZURE_CLIENT_ID && env.AZURE_CLIENT_SECRET) {
|
||||
req: Request,
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
params: { id_token: string },
|
||||
params: { expires_in: number; id_token: string },
|
||||
_profile: Profile,
|
||||
done: (
|
||||
err: Error | null,
|
||||
@@ -105,6 +105,7 @@ if (env.AZURE_CLIENT_ID && env.AZURE_CLIENT_SECRET) {
|
||||
providerId: profile.oid,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresIn: params.expires_in,
|
||||
scopes,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -49,6 +49,7 @@ if (env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) {
|
||||
req: Request,
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
params: { expires_in: number },
|
||||
profile: GoogleProfile,
|
||||
done: (
|
||||
err: Error | null,
|
||||
@@ -85,6 +86,7 @@ if (env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) {
|
||||
providerId: profile.id,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresIn: params.expires_in,
|
||||
scopes,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { sortBy } from "lodash";
|
||||
import { signin } from "@shared/utils/urlHelpers";
|
||||
import { requireDirectory } from "@server/utils/fs";
|
||||
|
||||
interface AuthenicationProvider {
|
||||
interface AuthenticationProviderConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
enabled: boolean;
|
||||
@@ -11,7 +11,7 @@ interface AuthenicationProvider {
|
||||
router: Router;
|
||||
}
|
||||
|
||||
const providers: AuthenicationProvider[] = [];
|
||||
const providers: AuthenticationProviderConfig[] = [];
|
||||
|
||||
requireDirectory(__dirname).forEach(([module, id]) => {
|
||||
// @ts-expect-error ts-migrate(2339) FIXME: Property 'config' does not exist on type 'unknown'... Remove this comment to see the full error message
|
||||
|
||||
@@ -3,13 +3,16 @@ import { Request } from "koa";
|
||||
import Router from "koa-router";
|
||||
import { get } from "lodash";
|
||||
import { Strategy } from "passport-oauth2";
|
||||
import accountProvisioner from "@server/commands/accountProvisioner";
|
||||
import accountProvisioner, {
|
||||
AccountProvisionerResult,
|
||||
} from "@server/commands/accountProvisioner";
|
||||
import env from "@server/env";
|
||||
import {
|
||||
OIDCMalformedUserInfoError,
|
||||
AuthenticationError,
|
||||
} from "@server/errors";
|
||||
import passportMiddleware from "@server/middlewares/passport";
|
||||
import { User } from "@server/models";
|
||||
import { StateStore, request } from "@server/utils/passport";
|
||||
|
||||
const router = new Router();
|
||||
@@ -60,8 +63,13 @@ if (env.OIDC_CLIENT_ID && env.OIDC_CLIENT_SECRET) {
|
||||
req: Request,
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
params: { expires_in: number },
|
||||
profile: Record<string, string>,
|
||||
done: any
|
||||
done: (
|
||||
err: Error | null,
|
||||
user: User | null,
|
||||
result?: AccountProvisionerResult
|
||||
) => void
|
||||
) {
|
||||
try {
|
||||
if (!profile.email) {
|
||||
@@ -102,6 +110,7 @@ if (env.OIDC_CLIENT_ID && env.OIDC_CLIENT_SECRET) {
|
||||
providerId: profile.sub,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresIn: params.expires_in,
|
||||
scopes,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -66,6 +66,7 @@ if (env.SLACK_CLIENT_ID && env.SLACK_CLIENT_SECRET) {
|
||||
req: Request,
|
||||
accessToken: string,
|
||||
refreshToken: string,
|
||||
params: { expires_in: number },
|
||||
profile: SlackProfile,
|
||||
done: (
|
||||
err: Error | null,
|
||||
@@ -94,6 +95,7 @@ if (env.SLACK_CLIENT_ID && env.SLACK_CLIENT_SECRET) {
|
||||
providerId: profile.user.id,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresIn: params.expires_in,
|
||||
scopes,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user