Skip to content

Commit

Permalink
feat(auth): add authentication endpoints (#6265)
Browse files Browse the repository at this point in the history
**What**
- Add authentication endpoints: 
  - `/auth/[scope]/[provider]` 
  - `/auth/[scope]/[provider]/callback`
- update authenticate-middleware handler
- Add scope field to user
- Add unique constraint on scope and entity_id

note: there's still some remaining work related to jwt auth to be handled, this is mainly focussed on session auth with endpoints



Co-authored-by: Sebastian Rindom <7554214+srindom@users.noreply.github.com>
  • Loading branch information
pKorsholm and srindom authored Feb 2, 2024
1 parent 061c449 commit 9fda6a6
Show file tree
Hide file tree
Showing 31 changed files with 303 additions and 147 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { IAuthModuleService, ICustomerModuleService } from "@medusajs/types"
import { initDb, useDb } from "../../../../environment-helpers/use-db"

import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { ICustomerModuleService, IAuthModuleService } from "@medusajs/types"
import adminSeeder from "../../../../helpers/admin-seeder"
import { getContainer } from "../../../../environment-helpers/use-container"
import path from "path"
import { startBootstrapApp } from "../../../../environment-helpers/bootstrap-app"
import { useApi } from "../../../../environment-helpers/use-api"
import { getContainer } from "../../../../environment-helpers/use-container"
import { initDb, useDb } from "../../../../environment-helpers/use-db"
import adminSeeder from "../../../../helpers/admin-seeder"

jest.setTimeout(50000)

Expand Down Expand Up @@ -49,6 +50,7 @@ describe("POST /store/customers", () => {
const authUser = await authService.createAuthUser({
entity_id: "store_user",
provider_id: "test",
scope: "store",
})
const jwt = await authService.generateJwtToken(authUser.id, "store")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const createAuthenticatedCustomer = async (
const authUser = await authService.createAuthUser({
entity_id: "store_user",
provider_id: "test",
scope: "store",
app_metadata: { customer_id: customer.id },
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthUser } from "@models"
import { SqlEntityManager } from "@mikro-orm/postgresql"

export async function createAuthUsers(
manager: SqlEntityManager,
Expand All @@ -8,15 +8,18 @@ export async function createAuthUsers(
id: "test-id",
entity_id: "test-id",
provider: "manual",
scope: "store",
},
{
id: "test-id-1",
entity_id: "test-id-1",
provider: "manual",
scope: "store",
},
{
entity_id: "test-id-2",
provider: "store",
scope: "store",
},
]
): Promise<AuthUser[]> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthUserService } from "@services"

import ContainerLoader from "../../../../src/loaders/container"
import { MikroOrmWrapper } from "../../../utils"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { asValue } from "awilix"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
import { createAuthUsers } from "../../../__fixtures__/auth-user"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"

jest.setTimeout(30000)

Expand Down Expand Up @@ -229,7 +228,8 @@ describe("AuthUser Service", () => {
{
id: "test",
provider_id: "manual",
entity_id: "test"
entity_id: "test",
scope: "store"
},
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ describe("AuthModuleService - AuthUser", () => {
id: "test",
provider_id: "manual",
entity_id: "test",
scope: "store",
},
])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ describe("AuthModuleService - AuthProvider", () => {
const { success, error } = await service.authenticate(
"emailpass",
{
scope: "non-existing",
authScope: "non-existing",
} as any
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { AuthenticationInput, IAuthModuleService } from "@medusajs/types"
import { MedusaModule, Modules } from "@medusajs/modules-sdk"

import { IAuthModuleService } from "@medusajs/types"
import { MikroOrmWrapper } from "../../../utils"
import Scrypt from "scrypt-kdf"
import { SqlEntityManager } from "@mikro-orm/postgresql"
Expand Down Expand Up @@ -62,6 +62,7 @@ describe("AuthModuleService - AuthProvider", () => {
{
provider: "emailpass",
entity_id: email,
scope: "store",
provider_metadata: {
password: passwordHash,
},
Expand All @@ -73,8 +74,8 @@ describe("AuthModuleService - AuthProvider", () => {
email: "test@test.com",
password: password,
},
scope: "store",
})
authScope: "store",
} as any)

expect(res).toEqual({
success: true,
Expand All @@ -92,8 +93,8 @@ describe("AuthModuleService - AuthProvider", () => {

const res = await service.authenticate("emailpass", {
body: { email: "test@test.com" },
scope: "store",
})
authScope: "store",
} as any)

expect(res).toEqual({
success: false,
Expand All @@ -106,8 +107,8 @@ describe("AuthModuleService - AuthProvider", () => {

const res = await service.authenticate("emailpass", {
body: { password: "supersecret" },
scope: "store",
})
authScope: "store",
} as any)

expect(res).toEqual({
success: false,
Expand All @@ -127,6 +128,7 @@ describe("AuthModuleService - AuthProvider", () => {
// Add authenticated user
{
provider: "emailpass",
scope: "store",
entity_id: email,
provider_metadata: {
password_hash: passwordHash,
Expand All @@ -139,8 +141,8 @@ describe("AuthModuleService - AuthProvider", () => {
email: "test@test.com",
password: "password",
},
scope: "store",
})
authScope: "store",
} as any)

expect(res).toEqual({
success: false,
Expand Down
2 changes: 1 addition & 1 deletion packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"@mikro-orm/migrations": "5.9.7",
"@mikro-orm/postgresql": "5.9.7",
"awilix": "^8.0.0",
"dotenv": "^16.1.4",
"dotenv": "16.3.1",
"jsonwebtoken": "^9.0.2",
"knex": "2.4.2",
"scrypt-kdf": "^2.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,14 @@
"nullable": false,
"mappedType": "text"
},
"domain": {
"name": "domain",
"scope": {
"name": "scope",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"default": "'all'",
"enumItems": [
"all",
"store",
"admin"
],
"mappedType": "enum"
"nullable": true,
"mappedType": "text"
},
"config": {
"name": "config",
Expand Down Expand Up @@ -104,6 +98,15 @@
"nullable": true,
"mappedType": "text"
},
"scope": {
"name": "scope",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "text"
},
"user_metadata": {
"name": "user_metadata",
"type": "jsonb",
Expand All @@ -119,7 +122,7 @@
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"nullable": false,
"mappedType": "json"
},
"provider_metadata": {
Expand All @@ -136,9 +139,10 @@
"schema": "public",
"indexes": [
{
"keyName": "IDX_auth_user_provider_entity_id",
"keyName": "IDX_auth_user_provider_scope_entity_id",
"columnNames": [
"provider_id",
"scope",
"entity_id"
],
"composite": true,
Expand Down
30 changes: 0 additions & 30 deletions packages/auth/src/migrations/Migration20240122041959.ts

This file was deleted.

22 changes: 22 additions & 0 deletions packages/auth/src/migrations/Migration20240201100135.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20240201100135 extends Migration {

async up(): Promise<void> {
this.addSql('create table "auth_provider" ("provider" text not null, "name" text not null, "scope" text null, "config" jsonb null, "is_active" boolean not null default false, constraint "auth_provider_pkey" primary key ("provider"));');

this.addSql('create table "auth_user" ("id" text not null, "entity_id" text not null, "provider_id" text null, "scope" text not null, "user_metadata" jsonb null, "app_metadata" jsonb not null, "provider_metadata" jsonb null, constraint "auth_user_pkey" primary key ("id"));');
this.addSql('alter table "auth_user" add constraint "IDX_auth_user_provider_scope_entity_id" unique ("provider_id", "scope", "entity_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;');
}

}
4 changes: 2 additions & 2 deletions packages/auth/src/models/auth-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export default class AuthProvider {
@Property({ columnType: "text" })
name: string

@Enum({ items: () => ProviderDomain, default: ProviderDomain.ALL })
domain: ProviderDomain = ProviderDomain.ALL
@Property({ columnType: "text", nullable: true })
scope: string

@Property({ columnType: "jsonb", nullable: true })
config: Record<string, unknown> | null = null
Expand Down
14 changes: 10 additions & 4 deletions packages/auth/src/models/auth-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import { generateEntityId } from "@medusajs/utils"
type OptionalFields = "provider_metadata" | "app_metadata" | "user_metadata"

@Entity()
@Unique({ properties: ["provider","entity_id" ], name: "IDX_auth_user_provider_entity_id" })
@Unique({
properties: ["provider", "scope", "entity_id"],
name: "IDX_auth_user_provider_scope_entity_id",
})
export default class AuthUser {
[OptionalProps]: OptionalFields

Expand All @@ -34,14 +37,17 @@ export default class AuthUser {
})
provider: AuthProvider

@Property({ columnType: "text" })
scope: string

@Property({ columnType: "jsonb", nullable: true })
user_metadata: Record<string, unknown> | null

@Property({ columnType: "jsonb", nullable: true })
app_metadata: Record<string, unknown> | null
@Property({ columnType: "jsonb" })
app_metadata: Record<string, unknown> = {}

@Property({ columnType: "jsonb", nullable: true })
provider_metadata: Record<string, unknown> | null
provider_metadata: Record<string, unknown> | null = null

@BeforeCreate()
onCreate() {
Expand Down
Loading

0 comments on commit 9fda6a6

Please sign in to comment.