feat(authentication): Google authentication provider (#6104)
* init * add entity_id and update provider * initial implementation * update lockfile * fix conflicts * add config variables * update types * refactor google provider * re-order methods * fix pr feedback p. 1 * add initial type and update callback authorization * add google provider to integration test * fix feedback * initial implementation (#6171) * initial implementation * remove oauth lib * move abstract authentication provider * shuffle files around * Update packages/authentication/src/migrations/Migration20240122041959.ts Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com> * call verify with token --------- Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
This commit is contained in:
co-authored by
Carlos R. L. Rodrigues
parent
c37c82c5b5
commit
b3d013940f
+17
-12
@@ -1,11 +1,10 @@
|
|||||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
|
||||||
|
|
||||||
import { MikroOrmWrapper } from "../../../utils"
|
|
||||||
import { initialize } from "../../../../src"
|
|
||||||
import { DB_URL } from "@medusajs/pricing/integration-tests/utils"
|
import { DB_URL } from "@medusajs/pricing/integration-tests/utils"
|
||||||
import { MedusaModule } from "@medusajs/modules-sdk"
|
|
||||||
import { IAuthenticationModuleService } from "@medusajs/types"
|
import { IAuthenticationModuleService } from "@medusajs/types"
|
||||||
|
import { MedusaModule } from "@medusajs/modules-sdk"
|
||||||
|
import { MikroOrmWrapper } from "../../../utils"
|
||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
|
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
|
||||||
|
import { initialize } from "../../../../src"
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@ describe("AuthenticationModuleService - AuthProvider", () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if(service.__hooks?.onApplicationStart) {
|
if (service.__hooks?.onApplicationStart) {
|
||||||
await service.__hooks.onApplicationStart()
|
await service.__hooks.onApplicationStart()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -39,12 +38,18 @@ describe("AuthenticationModuleService - AuthProvider", () => {
|
|||||||
const authProviders = await service.listAuthProviders()
|
const authProviders = await service.listAuthProviders()
|
||||||
const serialized = JSON.parse(JSON.stringify(authProviders))
|
const serialized = JSON.parse(JSON.stringify(authProviders))
|
||||||
|
|
||||||
expect(serialized).toEqual([
|
expect(serialized).toEqual(
|
||||||
expect.objectContaining({
|
expect.arrayContaining([
|
||||||
provider: "usernamePassword",
|
expect.objectContaining({
|
||||||
name: "Username/Password Authentication",
|
provider: "usernamePassword",
|
||||||
}),
|
name: "Username/Password Authentication",
|
||||||
])
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
provider: "google",
|
||||||
|
name: "Google Authentication",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
+6
-7
@@ -1,13 +1,12 @@
|
|||||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
|
||||||
import Scrypt from "scrypt-kdf"
|
|
||||||
|
|
||||||
import { MikroOrmWrapper } from "../../../utils"
|
|
||||||
import { initialize } from "../../../../src"
|
|
||||||
import { DB_URL } from "@medusajs/pricing/integration-tests/utils"
|
import { DB_URL } from "@medusajs/pricing/integration-tests/utils"
|
||||||
import { MedusaModule } from "@medusajs/modules-sdk"
|
|
||||||
import { IAuthenticationModuleService } from "@medusajs/types"
|
import { IAuthenticationModuleService } from "@medusajs/types"
|
||||||
import { createAuthUsers } from "../../../__fixtures__/auth-user"
|
import { MedusaModule } from "@medusajs/modules-sdk"
|
||||||
|
import { MikroOrmWrapper } from "../../../utils"
|
||||||
|
import Scrypt from "scrypt-kdf"
|
||||||
|
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||||
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
|
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
|
||||||
|
import { createAuthUsers } from "../../../__fixtures__/auth-user"
|
||||||
|
import { initialize } from "../../../../src"
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
const seedDefaultData = async (testManager) => {
|
const seedDefaultData = async (testManager) => {
|
||||||
|
|||||||
@@ -56,7 +56,9 @@
|
|||||||
"@mikro-orm/postgresql": "5.9.7",
|
"@mikro-orm/postgresql": "5.9.7",
|
||||||
"awilix": "^8.0.0",
|
"awilix": "^8.0.0",
|
||||||
"dotenv": "^16.1.4",
|
"dotenv": "^16.1.4",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"knex": "2.4.2",
|
"knex": "2.4.2",
|
||||||
"scrypt-kdf": "^2.0.1"
|
"scrypt-kdf": "^2.0.1",
|
||||||
|
"simple-oauth2": "^5.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
import * as defaultProviders from "@providers"
|
import * as defaultProviders from "@providers"
|
||||||
|
|
||||||
|
import {
|
||||||
|
AwilixContainer,
|
||||||
|
ClassOrFunctionReturning,
|
||||||
|
Constructor,
|
||||||
|
Resolver,
|
||||||
|
asClass,
|
||||||
|
} from "awilix"
|
||||||
import { LoaderOptions, ModulesSdkTypes } from "@medusajs/types"
|
import { LoaderOptions, ModulesSdkTypes } from "@medusajs/types"
|
||||||
|
|
||||||
import { AwilixContainer, ClassOrFunctionReturning, Resolver, asClass, asFunction, asValue } from "awilix"
|
|
||||||
|
|
||||||
export default async ({
|
export default async ({
|
||||||
container,
|
container,
|
||||||
}: LoaderOptions<
|
}: LoaderOptions<
|
||||||
@@ -18,7 +23,9 @@ export default async ({
|
|||||||
|
|
||||||
for (const provider of providersToLoad) {
|
for (const provider of providersToLoad) {
|
||||||
container.register({
|
container.register({
|
||||||
[`auth_provider_${provider.PROVIDER}`]: asClass(provider).singleton(),
|
[`auth_provider_${provider.PROVIDER}`]: asClass(
|
||||||
|
provider as Constructor<any>
|
||||||
|
).singleton(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,15 @@
|
|||||||
],
|
],
|
||||||
"mappedType": "enum"
|
"mappedType": "enum"
|
||||||
},
|
},
|
||||||
|
"config": {
|
||||||
|
"name": "config",
|
||||||
|
"type": "jsonb",
|
||||||
|
"unsigned": false,
|
||||||
|
"autoincrement": false,
|
||||||
|
"primary": false,
|
||||||
|
"nullable": true,
|
||||||
|
"mappedType": "json"
|
||||||
|
},
|
||||||
"is_active": {
|
"is_active": {
|
||||||
"name": "is_active",
|
"name": "is_active",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
import { Migration } from '@mikro-orm/migrations';
|
|
||||||
|
|
||||||
export class Migration20240104154451 extends Migration {
|
|
||||||
|
|
||||||
async up(): Promise<void> {
|
|
||||||
this.addSql('create table "auth_provider" ("provider" text not null, "name" text not null, "domain" text check ("domain" in (\'all\', \'store\', \'admin\')) not null default \'all\', "is_active" boolean not null default false, constraint "auth_provider_pkey" primary key ("provider"));');
|
|
||||||
|
|
||||||
this.addSql('create table "auth_user" ("id" text not null, "provider_id" text null, "user_metadata" jsonb null, "app_metadata" jsonb null, "provider_metadata" jsonb null, constraint "auth_user_pkey" primary key ("id"));');
|
|
||||||
|
|
||||||
this.addSql('alter table "auth_user" add constraint "auth_user_provider_id_foreign" foreign key ("provider_id") references "auth_provider" ("provider") on delete cascade;');
|
|
||||||
}
|
|
||||||
|
|
||||||
async down(): Promise<void> {
|
|
||||||
this.addSql('alter table "auth_user" drop constraint "auth_user_provider_id_foreign";');
|
|
||||||
|
|
||||||
this.addSql('drop table if exists "auth_provider" cascade;');
|
|
||||||
|
|
||||||
this.addSql('drop table if exists "auth_user" cascade;');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { Migration } from '@mikro-orm/migrations';
|
|
||||||
|
|
||||||
export class Migration20240115092929 extends Migration {
|
|
||||||
|
|
||||||
async up(): Promise<void> {
|
|
||||||
this.addSql('alter table "auth_user" add column "entity_id" text not null;');
|
|
||||||
this.addSql('alter table "auth_user" add constraint "IDX_auth_user_provider_entity_id" unique ("provider_id", "entity_id");');
|
|
||||||
}
|
|
||||||
|
|
||||||
async down(): Promise<void> {
|
|
||||||
this.addSql('alter table "auth_user" drop constraint "IDX_auth_user_provider_entity_id";');
|
|
||||||
this.addSql('alter table "auth_user" drop column "entity_id";');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { Migration } from '@mikro-orm/migrations';
|
||||||
|
|
||||||
|
export class Migration20240122041959 extends Migration {
|
||||||
|
|
||||||
|
async up(): Promise<void> {
|
||||||
|
this.addSql('create table if not exists "auth_provider" ("provider" text not null, "name" text not null, "domain" text check ("domain" in (\'all\', \'store\', \'admin\')) not null default \'all\', "config" jsonb null, "is_active" boolean not null default false, constraint "auth_provider_pkey" primary key ("provider"));');
|
||||||
|
|
||||||
|
this.addSql('create table if not exists "auth_user" ("id" text not null, "entity_id" text not null, "provider_id" text null, "user_metadata" jsonb null, "app_metadata" jsonb null, "provider_metadata" jsonb null, constraint "auth_user_pkey" primary key ("id"));');
|
||||||
|
this.addSql('alter table "auth_user" add constraint "IDX_auth_user_provider_entity_id" unique ("provider_id", "entity_id");');
|
||||||
|
|
||||||
|
this.addSql('alter table "auth_user" add constraint if not exists "auth_user_provider_id_foreign" foreign key ("provider_id") references "auth_provider" ("provider") on delete cascade;');
|
||||||
|
}
|
||||||
|
|
||||||
|
async down(): Promise<void> {
|
||||||
|
this.addSql('alter table "auth_user" drop constraint if exists "auth_user_provider_id_foreign";');
|
||||||
|
|
||||||
|
this.addSql('drop table if exists "auth_provider" cascade;');
|
||||||
|
|
||||||
|
this.addSql('drop table if exists "auth_user" cascade;');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,9 +5,10 @@ import {
|
|||||||
PrimaryKey,
|
PrimaryKey,
|
||||||
Property,
|
Property,
|
||||||
} from "@mikro-orm/core"
|
} from "@mikro-orm/core"
|
||||||
|
|
||||||
import { ProviderDomain } from "../types/repositories/auth-provider"
|
import { ProviderDomain } from "../types/repositories/auth-provider"
|
||||||
|
|
||||||
type OptionalFields = "domain" | "is_active"
|
type OptionalFields = "domain" | "is_active" | "config"
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export default class AuthProvider {
|
export default class AuthProvider {
|
||||||
@@ -22,6 +23,9 @@ export default class AuthProvider {
|
|||||||
@Enum({ items: () => ProviderDomain, default: ProviderDomain.ALL })
|
@Enum({ items: () => ProviderDomain, default: ProviderDomain.ALL })
|
||||||
domain: ProviderDomain = ProviderDomain.ALL
|
domain: ProviderDomain = ProviderDomain.ALL
|
||||||
|
|
||||||
|
@Property({ columnType: "jsonb", nullable: true })
|
||||||
|
config: Record<string, unknown> | null = null
|
||||||
|
|
||||||
@Property({ columnType: "boolean", default: false })
|
@Property({ columnType: "boolean", default: false })
|
||||||
is_active = false
|
is_active = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
import {
|
||||||
|
AbstractAuthenticationModuleProvider,
|
||||||
|
MedusaError,
|
||||||
|
} from "@medusajs/utils"
|
||||||
|
import { AuthProviderService, AuthUserService } from "@services"
|
||||||
|
import jwt, { JwtPayload } from "jsonwebtoken"
|
||||||
|
|
||||||
|
import { AuthProvider } from "@models"
|
||||||
|
import { AuthenticationResponse } from "@medusajs/types"
|
||||||
|
import { AuthorizationCode } from "simple-oauth2"
|
||||||
|
import url from "url"
|
||||||
|
|
||||||
|
type InjectedDependencies = {
|
||||||
|
authUserService: AuthUserService
|
||||||
|
authProviderService: AuthProviderService
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthenticationInput = {
|
||||||
|
connection: { encrypted: boolean }
|
||||||
|
url: string
|
||||||
|
headers: { host: string }
|
||||||
|
query: Record<string, string>
|
||||||
|
body: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProviderConfig = {
|
||||||
|
clientID: string
|
||||||
|
clientSecret: string
|
||||||
|
callbackURL: string
|
||||||
|
}
|
||||||
|
|
||||||
|
class GoogleProvider extends AbstractAuthenticationModuleProvider {
|
||||||
|
public static PROVIDER = "google"
|
||||||
|
public static DISPLAY_NAME = "Google Authentication"
|
||||||
|
|
||||||
|
protected readonly authUserSerivce_: AuthUserService
|
||||||
|
protected readonly authProviderService_: AuthProviderService
|
||||||
|
|
||||||
|
constructor({ authUserService, authProviderService }: InjectedDependencies) {
|
||||||
|
super()
|
||||||
|
|
||||||
|
this.authUserSerivce_ = authUserService
|
||||||
|
this.authProviderService_ = authProviderService
|
||||||
|
}
|
||||||
|
|
||||||
|
private async validateConfig(config: Partial<ProviderConfig>) {
|
||||||
|
if (!config.clientID) {
|
||||||
|
throw new Error("Google clientID is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.clientSecret) {
|
||||||
|
throw new Error("Google clientSecret is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.callbackURL) {
|
||||||
|
throw new Error("Google callbackUrl is required")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private originalURL(req: AuthenticationInput) {
|
||||||
|
const tls = req.connection.encrypted,
|
||||||
|
host = req.headers.host,
|
||||||
|
protocol = tls ? "https" : "http",
|
||||||
|
path = req.url || ""
|
||||||
|
return protocol + "://" + host + path
|
||||||
|
}
|
||||||
|
|
||||||
|
async getProviderConfig(req: AuthenticationInput): Promise<ProviderConfig> {
|
||||||
|
const { config } = (await this.authProviderService_.retrieve(
|
||||||
|
GoogleProvider.PROVIDER
|
||||||
|
)) as AuthProvider & { config: ProviderConfig }
|
||||||
|
|
||||||
|
this.validateConfig(config || {})
|
||||||
|
|
||||||
|
const { callbackURL } = config
|
||||||
|
|
||||||
|
const parsedCallbackUrl = !url.parse(callbackURL).protocol
|
||||||
|
? url.resolve(this.originalURL(req), callbackURL)
|
||||||
|
: callbackURL
|
||||||
|
|
||||||
|
return { ...config, callbackURL: parsedCallbackUrl }
|
||||||
|
}
|
||||||
|
|
||||||
|
async authenticate(
|
||||||
|
req: AuthenticationInput
|
||||||
|
): Promise<AuthenticationResponse> {
|
||||||
|
if (req.query && req.query.error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: `${req.query.error_description}, read more at: ${req.query.error_uri}`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let config
|
||||||
|
|
||||||
|
try {
|
||||||
|
config = await this.getProviderConfig(req)
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
}
|
||||||
|
|
||||||
|
let { callbackURL, clientID, clientSecret } = config
|
||||||
|
|
||||||
|
const meta: ProviderConfig = {
|
||||||
|
clientID,
|
||||||
|
callbackURL,
|
||||||
|
clientSecret,
|
||||||
|
}
|
||||||
|
|
||||||
|
const code = (req.query && req.query.code) || (req.body && req.body.code)
|
||||||
|
|
||||||
|
// Redirect to google
|
||||||
|
if (!code) {
|
||||||
|
return this.getRedirect(meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.validateCallback(code, meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
// abstractable
|
||||||
|
private async validateCallback(
|
||||||
|
code: string,
|
||||||
|
{ clientID, callbackURL, clientSecret }: ProviderConfig
|
||||||
|
) {
|
||||||
|
const client = this.getAuthorizationCodeHandler({ clientID, clientSecret })
|
||||||
|
|
||||||
|
const tokenParams = {
|
||||||
|
code,
|
||||||
|
redirect_uri: callbackURL,
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const accessToken = await client.getToken(tokenParams)
|
||||||
|
|
||||||
|
return await this.verify_(accessToken.token.id_token)
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// abstractable
|
||||||
|
async verify_(refreshToken: string) {
|
||||||
|
const jwtData = (await jwt.decode(refreshToken, {
|
||||||
|
complete: true,
|
||||||
|
})) as JwtPayload
|
||||||
|
const entity_id = jwtData.payload.email
|
||||||
|
|
||||||
|
let authUser
|
||||||
|
|
||||||
|
try {
|
||||||
|
authUser = await this.authUserSerivce_.retrieveByProviderAndEntityId(
|
||||||
|
entity_id,
|
||||||
|
GoogleProvider.PROVIDER
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
if (error.type === MedusaError.Types.NOT_FOUND) {
|
||||||
|
authUser = await this.authUserSerivce_.create([
|
||||||
|
{
|
||||||
|
entity_id,
|
||||||
|
provider_id: GoogleProvider.PROVIDER,
|
||||||
|
user_metadata: jwtData!.payload,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
return { success: false, error: error.message }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { success: true, authUser }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abstractable
|
||||||
|
private getRedirect({ clientID, callbackURL, clientSecret }: ProviderConfig) {
|
||||||
|
const client = this.getAuthorizationCodeHandler({ clientID, clientSecret })
|
||||||
|
|
||||||
|
const location = client.authorizeURL({
|
||||||
|
redirect_uri: callbackURL,
|
||||||
|
scope: "email profile",
|
||||||
|
})
|
||||||
|
|
||||||
|
return { success: true, location }
|
||||||
|
}
|
||||||
|
|
||||||
|
private getAuthorizationCodeHandler({
|
||||||
|
clientID,
|
||||||
|
clientSecret,
|
||||||
|
}: {
|
||||||
|
clientID: string
|
||||||
|
clientSecret: string
|
||||||
|
}) {
|
||||||
|
const config = {
|
||||||
|
client: {
|
||||||
|
id: clientID,
|
||||||
|
secret: clientSecret,
|
||||||
|
},
|
||||||
|
auth: {
|
||||||
|
// TODO: abstract to not be google specific
|
||||||
|
authorizeHost: "https://accounts.google.com",
|
||||||
|
authorizePath: "/o/oauth2/v2/auth",
|
||||||
|
tokenHost: "https://www.googleapis.com",
|
||||||
|
tokenPath: "/oauth2/v4/token",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AuthorizationCode(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GoogleProvider
|
||||||
@@ -1 +1,2 @@
|
|||||||
export { default as UsernamePasswordProvider } from "./username-password"
|
export { default as UsernamePasswordProvider } from "./username-password"
|
||||||
|
export { default as GoogleProvider } from "./google"
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
import {
|
import { AuthenticationResponse } from "@medusajs/types"
|
||||||
AbstractAuthenticationModuleProvider,
|
|
||||||
AuthenticationResponse,
|
|
||||||
} from "@medusajs/types"
|
|
||||||
|
|
||||||
import { AuthUserService } from "@services"
|
import { AuthUserService } from "@services"
|
||||||
import Scrypt from "scrypt-kdf"
|
import Scrypt from "scrypt-kdf"
|
||||||
import { isString } from "@medusajs/utils"
|
import { AbstractAuthenticationModuleProvider, isString } from "@medusajs/utils"
|
||||||
|
|
||||||
class UsernamePasswordProvider extends AbstractAuthenticationModuleProvider {
|
class UsernamePasswordProvider extends AbstractAuthenticationModuleProvider {
|
||||||
public static PROVIDER = "usernamePassword"
|
public static PROVIDER = "usernamePassword"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
AbstractAuthenticationModuleProvider,
|
|
||||||
AuthenticationResponse,
|
AuthenticationResponse,
|
||||||
AuthenticationTypes,
|
AuthenticationTypes,
|
||||||
Context,
|
Context,
|
||||||
@@ -16,6 +15,7 @@ import { joinerConfig } from "../joiner-config"
|
|||||||
import { AuthProviderService, AuthUserService } from "@services"
|
import { AuthProviderService, AuthUserService } from "@services"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
AbstractAuthenticationModuleProvider,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
@@ -158,7 +158,7 @@ export default class AuthenticationModuleService<
|
|||||||
protected async createAuthProviders_(
|
protected async createAuthProviders_(
|
||||||
data: any[],
|
data: any[],
|
||||||
@MedusaContext() sharedContext: Context
|
@MedusaContext() sharedContext: Context
|
||||||
): Promise<AuthenticationTypes.AuthProviderDTO[]> {
|
): Promise<TAuthProvider[]> {
|
||||||
return await this.authProviderService_.create(data, sharedContext)
|
return await this.authProviderService_.create(data, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ export default class AuthenticationModuleService<
|
|||||||
async updateAuthProvider_(
|
async updateAuthProvider_(
|
||||||
data: AuthenticationTypes.UpdateAuthProviderDTO[],
|
data: AuthenticationTypes.UpdateAuthProviderDTO[],
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
): Promise<AuthProviderDTO[]> {
|
): Promise<TAuthProvider[]> {
|
||||||
return await this.authProviderService_.update(data, sharedContext)
|
return await this.authProviderService_.update(data, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +387,6 @@ export default class AuthenticationModuleService<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async createProvidersOnLoad() {
|
private async createProvidersOnLoad() {
|
||||||
const providersToLoad = this.__container__["auth_providers"]
|
const providersToLoad = this.__container__["auth_providers"]
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export type CreateAuthProviderDTO = {
|
|||||||
name: string
|
name: string
|
||||||
domain?: ProviderDomain
|
domain?: ProviderDomain
|
||||||
is_active?: boolean
|
is_active?: boolean
|
||||||
|
config?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UpdateAuthProviderDTO = {
|
export type UpdateAuthProviderDTO = {
|
||||||
@@ -13,6 +14,7 @@ export type UpdateAuthProviderDTO = {
|
|||||||
name?: string
|
name?: string
|
||||||
domain?: ProviderDomain
|
domain?: ProviderDomain
|
||||||
is_active?: boolean
|
is_active?: boolean
|
||||||
|
config?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
provider: AuthProvider
|
provider: AuthProvider
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export type AuthProviderDTO = {
|
|||||||
name: string
|
name: string
|
||||||
domain: ProviderDomain
|
domain: ProviderDomain
|
||||||
is_active: boolean
|
is_active: boolean
|
||||||
|
config: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CreateAuthProviderDTO = {
|
export type CreateAuthProviderDTO = {
|
||||||
@@ -10,6 +11,7 @@ export type CreateAuthProviderDTO = {
|
|||||||
name: string
|
name: string
|
||||||
domain?: ProviderDomain
|
domain?: ProviderDomain
|
||||||
is_active?: boolean
|
is_active?: boolean
|
||||||
|
config?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UpdateAuthProviderDTO = {
|
export type UpdateAuthProviderDTO = {
|
||||||
@@ -17,6 +19,7 @@ export type UpdateAuthProviderDTO = {
|
|||||||
name?: string
|
name?: string
|
||||||
domain?: ProviderDomain
|
domain?: ProviderDomain
|
||||||
is_active?: boolean
|
is_active?: boolean
|
||||||
|
config?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ProviderDomain {
|
export enum ProviderDomain {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export type AuthProviderDTO = {
|
|||||||
name: string
|
name: string
|
||||||
domain: ProviderDomain
|
domain: ProviderDomain
|
||||||
is_active: boolean
|
is_active: boolean
|
||||||
|
config: Record<string, unknown> | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CreateAuthProviderDTO = {
|
export type CreateAuthProviderDTO = {
|
||||||
@@ -12,6 +13,7 @@ export type CreateAuthProviderDTO = {
|
|||||||
name: string
|
name: string
|
||||||
domain?: ProviderDomain
|
domain?: ProviderDomain
|
||||||
is_active?: boolean
|
is_active?: boolean
|
||||||
|
config?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UpdateAuthProviderDTO = {
|
export type UpdateAuthProviderDTO = {
|
||||||
@@ -19,6 +21,7 @@ export type UpdateAuthProviderDTO = {
|
|||||||
name?: string
|
name?: string
|
||||||
domain?: ProviderDomain
|
domain?: ProviderDomain
|
||||||
is_active?: boolean
|
is_active?: boolean
|
||||||
|
config?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ProviderDomain {
|
export enum ProviderDomain {
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
export * from "./auth-user"
|
export * from "./auth-user"
|
||||||
export * from "./auth-provider"
|
export * from "./auth-provider"
|
||||||
|
export * from "./provider"
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export type AuthenticationResponse = {
|
||||||
|
success: boolean
|
||||||
|
authUser?: any
|
||||||
|
error?: string
|
||||||
|
}
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
export * from "./service"
|
export * from "./service"
|
||||||
export * from "./common"
|
export * from "./common"
|
||||||
export * from "./provider"
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { IModuleService } from "../modules-sdk"
|
|
||||||
import {
|
import {
|
||||||
|
AuthenticationResponse,
|
||||||
AuthProviderDTO,
|
AuthProviderDTO,
|
||||||
AuthUserDTO,
|
AuthUserDTO,
|
||||||
CreateAuthProviderDTO,
|
CreateAuthProviderDTO,
|
||||||
@@ -9,9 +9,10 @@ import {
|
|||||||
UpdateAuthProviderDTO,
|
UpdateAuthProviderDTO,
|
||||||
UpdateAuthUserDTO,
|
UpdateAuthUserDTO,
|
||||||
} from "./common"
|
} from "./common"
|
||||||
import { FindConfig } from "../common"
|
|
||||||
import { Context } from "../shared-context"
|
import { Context } from "../shared-context"
|
||||||
import { AuthenticationResponse } from "./provider"
|
import { FindConfig } from "../common"
|
||||||
|
import { IModuleService } from "../modules-sdk"
|
||||||
|
|
||||||
export interface IAuthenticationModuleService extends IModuleService {
|
export interface IAuthenticationModuleService extends IModuleService {
|
||||||
authenticate(
|
authenticate(
|
||||||
|
|||||||
+4
-9
@@ -1,24 +1,19 @@
|
|||||||
import { AuthUserDTO } from "./common"
|
import { AuthenticationResponse } from "@medusajs/types";
|
||||||
|
|
||||||
export abstract class AbstractAuthenticationModuleProvider {
|
export abstract class AbstractAuthenticationModuleProvider {
|
||||||
public static PROVIDER: string
|
public static PROVIDER: string
|
||||||
public static DISPLAY_NAME: string
|
public static DISPLAY_NAME: string
|
||||||
|
|
||||||
public get provider() {
|
public get provider() {
|
||||||
return (this.constructor as Function & { PROVIDER: string}).PROVIDER
|
return (this.constructor as Function & { PROVIDER: string }).PROVIDER
|
||||||
}
|
}
|
||||||
|
|
||||||
public get displayName() {
|
public get displayName() {
|
||||||
return (this.constructor as Function & { DISPLAY_NAME: string}).DISPLAY_NAME
|
return (this.constructor as Function & { DISPLAY_NAME: string })
|
||||||
|
.DISPLAY_NAME
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract authenticate(
|
abstract authenticate(
|
||||||
data: Record<string, unknown>
|
data: Record<string, unknown>
|
||||||
): Promise<AuthenticationResponse>
|
): Promise<AuthenticationResponse>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AuthenticationResponse = {
|
|
||||||
success: boolean
|
|
||||||
authUser?: AuthUserDTO
|
|
||||||
error?: string
|
|
||||||
}
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from "./abstract-authentication-provider"
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export * from "./authentication"
|
||||||
export * from "./bundles"
|
export * from "./bundles"
|
||||||
export * from "./common"
|
export * from "./common"
|
||||||
export * from "./dal"
|
export * from "./dal"
|
||||||
|
|||||||
@@ -6060,14 +6060,44 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@hapi/hoek@npm:^9.0.0":
|
"@hapi/boom@npm:^10.0.1":
|
||||||
|
version: 10.0.1
|
||||||
|
resolution: "@hapi/boom@npm:10.0.1"
|
||||||
|
dependencies:
|
||||||
|
"@hapi/hoek": ^11.0.2
|
||||||
|
checksum: e4ae8a69bb67c5687320d320a0706ac66e797a659c19fb1c9b909eaefe3b41780e4ecd4382de1297b10c33e9db81f79667324576b9153f57b0cf701293b908d0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@hapi/bourne@npm:^3.0.0":
|
||||||
|
version: 3.0.0
|
||||||
|
resolution: "@hapi/bourne@npm:3.0.0"
|
||||||
|
checksum: 2e2df62f6bc6f32b980ba5bbdc09200c93c55c8306399ec0f2781da088a82aab699498c89fe94fec4acf770210f9aee28c75bfc2f04044849ac01b034134e717
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@hapi/hoek@npm:^10.0.1":
|
||||||
|
version: 10.0.1
|
||||||
|
resolution: "@hapi/hoek@npm:10.0.1"
|
||||||
|
checksum: 320d5dc7a4070fa29e6344a3af9e44854980c6606848f7b7f59715174880cc09a1fe1e8adf44cf887100bd8d6a8664e9dc415986b30dc91df13455f7114de549
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@hapi/hoek@npm:^11.0.2":
|
||||||
|
version: 11.0.4
|
||||||
|
resolution: "@hapi/hoek@npm:11.0.4"
|
||||||
|
checksum: 3c0e487824daaf3af4c29e46fd57b0c5801ce9164fef2417c70e271cd970e13cc542b196f70ba1cfc9ef944eed825fcac261085ab5e2928c6017428bf576b363
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@hapi/hoek@npm:^9.0.0, @hapi/hoek@npm:^9.3.0":
|
||||||
version: 9.3.0
|
version: 9.3.0
|
||||||
resolution: "@hapi/hoek@npm:9.3.0"
|
resolution: "@hapi/hoek@npm:9.3.0"
|
||||||
checksum: a096063805051fb8bba4c947e293c664b05a32b47e13bc654c0dd43813a1cec993bdd8f29ceb838020299e1d0f89f68dc0d62a603c13c9cc8541963f0beca055
|
checksum: a096063805051fb8bba4c947e293c664b05a32b47e13bc654c0dd43813a1cec993bdd8f29ceb838020299e1d0f89f68dc0d62a603c13c9cc8541963f0beca055
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@hapi/topo@npm:^5.0.0":
|
"@hapi/topo@npm:^5.0.0, @hapi/topo@npm:^5.1.0":
|
||||||
version: 5.1.0
|
version: 5.1.0
|
||||||
resolution: "@hapi/topo@npm:5.1.0"
|
resolution: "@hapi/topo@npm:5.1.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6076,6 +6106,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@hapi/wreck@npm:^18.0.0":
|
||||||
|
version: 18.0.1
|
||||||
|
resolution: "@hapi/wreck@npm:18.0.1"
|
||||||
|
dependencies:
|
||||||
|
"@hapi/boom": ^10.0.1
|
||||||
|
"@hapi/bourne": ^3.0.0
|
||||||
|
"@hapi/hoek": ^11.0.2
|
||||||
|
checksum: 46b1b1f750a66c4724964eb6d9192d1d19cfa45e602386aae76f52e3b423c9ae14a03a0f0e9f962e7d973708e1b0b6ab42d2ae77539a691fa77a18c78ccf285c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@headlessui/react@npm:^1.7.18":
|
"@headlessui/react@npm:^1.7.18":
|
||||||
version: 1.7.18
|
version: 1.7.18
|
||||||
resolution: "@headlessui/react@npm:1.7.18"
|
resolution: "@headlessui/react@npm:1.7.18"
|
||||||
@@ -7854,10 +7895,12 @@ __metadata:
|
|||||||
cross-env: ^5.2.1
|
cross-env: ^5.2.1
|
||||||
dotenv: ^16.1.4
|
dotenv: ^16.1.4
|
||||||
jest: ^29.6.3
|
jest: ^29.6.3
|
||||||
|
jsonwebtoken: ^9.0.2
|
||||||
knex: 2.4.2
|
knex: 2.4.2
|
||||||
medusa-test-utils: ^1.1.40
|
medusa-test-utils: ^1.1.40
|
||||||
rimraf: ^3.0.2
|
rimraf: ^3.0.2
|
||||||
scrypt-kdf: ^2.0.1
|
scrypt-kdf: ^2.0.1
|
||||||
|
simple-oauth2: ^5.0.0
|
||||||
ts-jest: ^29.1.1
|
ts-jest: ^29.1.1
|
||||||
ts-node: ^10.9.1
|
ts-node: ^10.9.1
|
||||||
tsc-alias: ^1.8.6
|
tsc-alias: ^1.8.6
|
||||||
@@ -12192,7 +12235,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@sideway/address@npm:^4.1.3":
|
"@sideway/address@npm:^4.1.3, @sideway/address@npm:^4.1.4":
|
||||||
version: 4.1.4
|
version: 4.1.4
|
||||||
resolution: "@sideway/address@npm:4.1.4"
|
resolution: "@sideway/address@npm:4.1.4"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -35009,6 +35052,19 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"joi@npm:^17.6.4":
|
||||||
|
version: 17.12.0
|
||||||
|
resolution: "joi@npm:17.12.0"
|
||||||
|
dependencies:
|
||||||
|
"@hapi/hoek": ^9.3.0
|
||||||
|
"@hapi/topo": ^5.1.0
|
||||||
|
"@sideway/address": ^4.1.4
|
||||||
|
"@sideway/formula": ^3.0.1
|
||||||
|
"@sideway/pinpoint": ^2.0.0
|
||||||
|
checksum: 2378f4ec8de2bc12674ce3e6faac509f52ff4f734c67bf68c288816b20336d4e59433ea1c1e187f1009075c81ec5fa8b5061094feb37a855d6e3ee0cfcd79dd8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"join-component@npm:^1.1.0":
|
"join-component@npm:^1.1.0":
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
resolution: "join-component@npm:1.1.0"
|
resolution: "join-component@npm:1.1.0"
|
||||||
@@ -35478,6 +35534,24 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"jsonwebtoken@npm:^9.0.2":
|
||||||
|
version: 9.0.2
|
||||||
|
resolution: "jsonwebtoken@npm:9.0.2"
|
||||||
|
dependencies:
|
||||||
|
jws: ^3.2.2
|
||||||
|
lodash.includes: ^4.3.0
|
||||||
|
lodash.isboolean: ^3.0.3
|
||||||
|
lodash.isinteger: ^4.0.4
|
||||||
|
lodash.isnumber: ^3.0.3
|
||||||
|
lodash.isplainobject: ^4.0.6
|
||||||
|
lodash.isstring: ^4.0.1
|
||||||
|
lodash.once: ^4.0.0
|
||||||
|
ms: ^2.1.1
|
||||||
|
semver: ^7.5.4
|
||||||
|
checksum: d287a29814895e866db2e5a0209ce730cbc158441a0e5a70d5e940eb0d28ab7498c6bf45029cc8b479639bca94056e9a7f254e2cdb92a2f5750c7f358657a131
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"jsprim@npm:^1.2.2":
|
"jsprim@npm:^1.2.2":
|
||||||
version: 1.4.2
|
version: 1.4.2
|
||||||
resolution: "jsprim@npm:1.4.2"
|
resolution: "jsprim@npm:1.4.2"
|
||||||
@@ -46081,6 +46155,18 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"simple-oauth2@npm:^5.0.0":
|
||||||
|
version: 5.0.0
|
||||||
|
resolution: "simple-oauth2@npm:5.0.0"
|
||||||
|
dependencies:
|
||||||
|
"@hapi/hoek": ^10.0.1
|
||||||
|
"@hapi/wreck": ^18.0.0
|
||||||
|
debug: ^4.3.4
|
||||||
|
joi: ^17.6.4
|
||||||
|
checksum: 1cb5a4eb9022f656e1bb9a1f43d771dd058d4a4fa181b42d0e1e7ca7b5cfc42e35fad1c722be9bb6fa218398b3b0499010554a7367d2bd85eb9d7634f92546c1
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"simple-string-table@npm:^1.0.0":
|
"simple-string-table@npm:^1.0.0":
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
resolution: "simple-string-table@npm:1.0.0"
|
resolution: "simple-string-table@npm:1.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user