New OpenID and OAuth2 drivers (#8660)

* Moved over oauth impl to new interface

* Fixed most build issues and started addind schema to auth drivers

* Finished up OAuth2 and OpenID drivers

* Removed unused migration and utils

* Fixed minor todos

* Removed old oauth flow

* Changed oauth flow to re-use refresh token

* Added new oauth frontend

* Added font awesome social icons

* Updated authentication documentation

* Update api/src/auth/drivers/oauth2.ts

* Tested implementation and fixed incorrect validation

* Updated docs

* Improved OAuth error handling and re-enabled creating users with provider/identifier

* Removed Session config from docs

* Update app/src/components/v-icon/v-icon.vue

* Removed oauth need to define default roleID

* Added FormatTitle to SSO links

* Prevent local auth without password

* Store OAuth access token in session data

* Update docs/guides/api-config.md

* Fixed copy and removed fontawesome-vue dependency

* More docs fixes

* Crucialy importend type fiks

* Update package-lock

* Remove is-email-allowed check

In favor of more advanced version based on filtering coming later

* Fix JSON type casting

* Delete unused util

* Update type signature to include name

* Add warning when code isn't found in oauth url

and remove obsolete imports

* Auto-continue on successful SSO login

* Tweak type signature

* More type casting shenanigans

* Please the TS gods

* Check for missing token before crashing

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
Aiden Foxx
2021-10-21 23:45:01 +02:00
committed by GitHub
parent 1b64b4472a
commit fa3b1171e8
36 changed files with 1747 additions and 822 deletions

View File

@@ -2,10 +2,12 @@ import getDatabase from './database';
import env from './env';
import logger from './logger';
import { AuthDriver } from './auth/auth';
import { LocalAuthDriver } from './auth/drivers/';
import { LocalAuthDriver, OAuth2AuthDriver, OpenIDAuthDriver } from './auth/drivers';
import { DEFAULT_AUTH_PROVIDER } from './constants';
import { InvalidConfigException } from './exceptions';
import { AuthDriverOptions } from './types';
import { getConfigFromEnv } from './utils/get-config-from-env';
import { getSchema } from './utils/get-schema';
import { toArray } from '@directus/shared/utils';
const providerNames = toArray(env.AUTH_PROVIDERS);
@@ -13,11 +15,6 @@ const providerNames = toArray(env.AUTH_PROVIDERS);
const providers: Map<string, AuthDriver> = new Map();
export function getAuthProvider(provider: string): AuthDriver {
// When providers haven't been registered yet
if (providerNames.length !== providers.size) {
registerProviders();
}
if (!providers.has(provider)) {
throw new InvalidConfigException('Auth provider not configured', { provider });
}
@@ -25,16 +22,12 @@ export function getAuthProvider(provider: string): AuthDriver {
return providers.get(provider)!;
}
function getProviderInstance(driver: string, config: Record<string, any>): AuthDriver | undefined {
switch (driver) {
case 'local':
return new LocalAuthDriver(getDatabase(), config);
}
}
export async function registerAuthProviders(): Promise<void> {
const options = { knex: getDatabase(), schema: await getSchema() };
const defaultProvider = getProviderInstance('local', options)!;
function registerProviders() {
// Register default provider
providers.set(DEFAULT_AUTH_PROVIDER, getProviderInstance('local', {}) as AuthDriver);
providers.set(DEFAULT_AUTH_PROVIDER, defaultProvider);
if (!env.AUTH_PROVIDERS) {
return;
@@ -56,7 +49,7 @@ function registerProviders() {
return;
}
const provider = getProviderInstance(driver, { provider: name, ...config });
const provider = getProviderInstance(driver, options, { provider: name, ...config });
if (!provider) {
logger.warn(`Invalid "${driver}" auth driver.`);
@@ -66,3 +59,20 @@ function registerProviders() {
providers.set(name, provider);
});
}
function getProviderInstance(
driver: string,
options: AuthDriverOptions,
config: Record<string, any> = {}
): AuthDriver | undefined {
switch (driver) {
case 'local':
return new LocalAuthDriver(options, config);
case 'oauth2':
return new OAuth2AuthDriver(options, config);
case 'openid':
return new OpenIDAuthDriver(options, config);
}
}