feat: add Medusa Cloud OAuth provider (#14395)
* feat: add Medusa Cloud OAuth provider * add Cloud login button * fetch whether cloud auth is enabled through api * allow unregistered to get session * handle existing users * address PR comments * prevent double execution * a few more fixes * fix callback url * fix spelling * refresh session * 200 instead of 201 * only allow cloud identities to create user * fix condition
This commit is contained in:
@@ -2013,18 +2013,23 @@ describe("defineConfig", function () {
|
||||
|
||||
it("should add cloud options to the project config and relevant modules if the environment variables are set", function () {
|
||||
const originalEnv = { ...process.env }
|
||||
process.env.MEDUSA_BACKEND_URL = "test-backend-url"
|
||||
process.env.MEDUSA_CLOUD_ENVIRONMENT_HANDLE = "test-environment"
|
||||
process.env.MEDUSA_CLOUD_API_KEY = "test-api-key"
|
||||
process.env.MEDUSA_CLOUD_EMAILS_ENDPOINT = "test-emails-endpoint"
|
||||
process.env.MEDUSA_CLOUD_PAYMENTS_ENDPOINT = "test-payments-endpoint"
|
||||
process.env.MEDUSA_CLOUD_WEBHOOK_SECRET = "test-webhook-secret"
|
||||
process.env.MEDUSA_CLOUD_OAUTH_AUTHORIZE_ENDPOINT =
|
||||
"test-oauth-authorize-endpoint"
|
||||
process.env.MEDUSA_CLOUD_OAUTH_TOKEN_ENDPOINT = "test-oauth-token-endpoint"
|
||||
process.env.MEDUSA_CLOUD_OAUTH_DISABLED = "true"
|
||||
const config = defineConfig()
|
||||
process.env = { ...originalEnv }
|
||||
|
||||
expect(config).toMatchInlineSnapshot(`
|
||||
{
|
||||
"admin": {
|
||||
"backendUrl": "/",
|
||||
"backendUrl": "test-backend-url",
|
||||
"path": "/app",
|
||||
},
|
||||
"featureFlags": {},
|
||||
@@ -2035,6 +2040,15 @@ describe("defineConfig", function () {
|
||||
},
|
||||
"auth": {
|
||||
"options": {
|
||||
"cloud": {
|
||||
"api_key": "test-api-key",
|
||||
"callback_url": "test-backend-url/app/login?auth_provider=cloud",
|
||||
"disabled": true,
|
||||
"environment_handle": "test-environment",
|
||||
"oauth_authorize_endpoint": "test-oauth-authorize-endpoint",
|
||||
"oauth_token_endpoint": "test-oauth-token-endpoint",
|
||||
"sandbox_handle": undefined,
|
||||
},
|
||||
"providers": [
|
||||
{
|
||||
"id": "emailpass",
|
||||
@@ -2176,6 +2190,10 @@ describe("defineConfig", function () {
|
||||
"apiKey": "test-api-key",
|
||||
"emailsEndpoint": "test-emails-endpoint",
|
||||
"environmentHandle": "test-environment",
|
||||
"oauthAuthorizeEndpoint": "test-oauth-authorize-endpoint",
|
||||
"oauthCallbackUrl": undefined,
|
||||
"oauthDisabled": true,
|
||||
"oauthTokenEndpoint": "test-oauth-token-endpoint",
|
||||
"paymentsEndpoint": "test-payments-endpoint",
|
||||
"sandboxHandle": undefined,
|
||||
"webhookSecret": "test-webhook-secret",
|
||||
@@ -2205,20 +2223,25 @@ describe("defineConfig", function () {
|
||||
`)
|
||||
})
|
||||
|
||||
it("should add cloud options to the project config and relevant modules if the environment varianbles is set for a sandbox", function () {
|
||||
it("should add cloud options to the project config and relevant modules if the environment variable is set for a sandbox", function () {
|
||||
const originalEnv = { ...process.env }
|
||||
process.env.MEDUSA_BACKEND_URL = "test-backend-url"
|
||||
process.env.MEDUSA_CLOUD_SANDBOX_HANDLE = "test-sandbox"
|
||||
process.env.MEDUSA_CLOUD_API_KEY = "test-api-key"
|
||||
process.env.MEDUSA_CLOUD_EMAILS_ENDPOINT = "test-emails-endpoint"
|
||||
process.env.MEDUSA_CLOUD_PAYMENTS_ENDPOINT = "test-payments-endpoint"
|
||||
process.env.MEDUSA_CLOUD_WEBHOOK_SECRET = "test-webhook-secret"
|
||||
process.env.MEDUSA_CLOUD_OAUTH_AUTHORIZE_ENDPOINT =
|
||||
"test-oauth-authorize-endpoint"
|
||||
process.env.MEDUSA_CLOUD_OAUTH_TOKEN_ENDPOINT = "test-oauth-token-endpoint"
|
||||
process.env.MEDUSA_CLOUD_OAUTH_DISABLED = "true"
|
||||
const config = defineConfig()
|
||||
process.env = { ...originalEnv }
|
||||
|
||||
expect(config).toMatchInlineSnapshot(`
|
||||
{
|
||||
"admin": {
|
||||
"backendUrl": "/",
|
||||
"backendUrl": "test-backend-url",
|
||||
"path": "/app",
|
||||
},
|
||||
"featureFlags": {},
|
||||
@@ -2229,6 +2252,15 @@ describe("defineConfig", function () {
|
||||
},
|
||||
"auth": {
|
||||
"options": {
|
||||
"cloud": {
|
||||
"api_key": "test-api-key",
|
||||
"callback_url": "test-backend-url/app/login?auth_provider=cloud",
|
||||
"disabled": true,
|
||||
"environment_handle": undefined,
|
||||
"oauth_authorize_endpoint": "test-oauth-authorize-endpoint",
|
||||
"oauth_token_endpoint": "test-oauth-token-endpoint",
|
||||
"sandbox_handle": "test-sandbox",
|
||||
},
|
||||
"providers": [
|
||||
{
|
||||
"id": "emailpass",
|
||||
@@ -2370,6 +2402,10 @@ describe("defineConfig", function () {
|
||||
"apiKey": "test-api-key",
|
||||
"emailsEndpoint": "test-emails-endpoint",
|
||||
"environmentHandle": undefined,
|
||||
"oauthAuthorizeEndpoint": "test-oauth-authorize-endpoint",
|
||||
"oauthCallbackUrl": undefined,
|
||||
"oauthDisabled": true,
|
||||
"oauthTokenEndpoint": "test-oauth-token-endpoint",
|
||||
"paymentsEndpoint": "test-payments-endpoint",
|
||||
"sandboxHandle": "test-sandbox",
|
||||
"webhookSecret": "test-webhook-secret",
|
||||
@@ -2415,6 +2451,9 @@ describe("defineConfig", function () {
|
||||
webhookSecret: "overriden-webhook-secret",
|
||||
emailsEndpoint: "overriden-emails-endpoint",
|
||||
paymentsEndpoint: "overriden-payments-endpoint",
|
||||
oauthAuthorizeEndpoint: "overriden-oauth-authorize-endpoint",
|
||||
oauthTokenEndpoint: "overriden-oauth-token-endpoint",
|
||||
oauthDisabled: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -2434,6 +2473,15 @@ describe("defineConfig", function () {
|
||||
},
|
||||
"auth": {
|
||||
"options": {
|
||||
"cloud": {
|
||||
"api_key": "overriden-api-key",
|
||||
"callback_url": "//app/login?auth_provider=cloud",
|
||||
"disabled": true,
|
||||
"environment_handle": "overriden-environment",
|
||||
"oauth_authorize_endpoint": "overriden-oauth-authorize-endpoint",
|
||||
"oauth_token_endpoint": "overriden-oauth-token-endpoint",
|
||||
"sandbox_handle": undefined,
|
||||
},
|
||||
"providers": [
|
||||
{
|
||||
"id": "emailpass",
|
||||
@@ -2575,6 +2623,10 @@ describe("defineConfig", function () {
|
||||
"apiKey": "overriden-api-key",
|
||||
"emailsEndpoint": "overriden-emails-endpoint",
|
||||
"environmentHandle": "overriden-environment",
|
||||
"oauthAuthorizeEndpoint": "overriden-oauth-authorize-endpoint",
|
||||
"oauthCallbackUrl": undefined,
|
||||
"oauthDisabled": true,
|
||||
"oauthTokenEndpoint": "overriden-oauth-token-endpoint",
|
||||
"paymentsEndpoint": "overriden-payments-endpoint",
|
||||
"sandboxHandle": undefined,
|
||||
"webhookSecret": "overriden-webhook-secret",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
AdminOptions,
|
||||
ConfigModule,
|
||||
InputConfig,
|
||||
InputConfigModules,
|
||||
@@ -50,7 +51,7 @@ export function defineConfig(config: InputConfig = {}): ConfigModule {
|
||||
const projectConfig = normalizeProjectConfig(config.projectConfig, options)
|
||||
const adminConfig = normalizeAdminConfig(config.admin)
|
||||
const modules = resolveModules(config.modules, options, config.projectConfig)
|
||||
applyCloudOptionsToModules(modules, projectConfig?.cloud)
|
||||
applyCloudOptionsToModules(modules, projectConfig?.cloud, adminConfig)
|
||||
const plugins = resolvePlugins(config.plugins, options)
|
||||
|
||||
return {
|
||||
@@ -378,6 +379,11 @@ function normalizeProjectConfig(
|
||||
webhookSecret: process.env.MEDUSA_CLOUD_WEBHOOK_SECRET,
|
||||
emailsEndpoint: process.env.MEDUSA_CLOUD_EMAILS_ENDPOINT,
|
||||
paymentsEndpoint: process.env.MEDUSA_CLOUD_PAYMENTS_ENDPOINT,
|
||||
oauthAuthorizeEndpoint: process.env.MEDUSA_CLOUD_OAUTH_AUTHORIZE_ENDPOINT,
|
||||
oauthTokenEndpoint: process.env.MEDUSA_CLOUD_OAUTH_TOKEN_ENDPOINT,
|
||||
oauthCallbackUrl: process.env.MEDUSA_CLOUD_OAUTH_CALLBACK_URL,
|
||||
oauthDisabled:
|
||||
process.env.MEDUSA_CLOUD_OAUTH_DISABLED === "true" ? true : undefined,
|
||||
...cloud,
|
||||
}
|
||||
const hasCloudOptions = Object.values(mergedCloudOptions).some(
|
||||
@@ -449,6 +455,21 @@ function normalizeProjectConfig(
|
||||
...restOfProjectConfig,
|
||||
} satisfies ConfigModule["projectConfig"]
|
||||
|
||||
if (
|
||||
isCloud &&
|
||||
!mergedCloudOptions.oauthDisabled &&
|
||||
mergedCloudOptions.oauthAuthorizeEndpoint &&
|
||||
mergedCloudOptions.oauthTokenEndpoint
|
||||
) {
|
||||
const userAuthMethods = config.http.authMethodsPerActor?.user ?? [
|
||||
"emailpass",
|
||||
]
|
||||
config.http.authMethodsPerActor = {
|
||||
...config.http.authMethodsPerActor,
|
||||
user: userAuthMethods.concat("cloud"),
|
||||
}
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -468,7 +489,8 @@ function normalizeAdminConfig(
|
||||
|
||||
function applyCloudOptionsToModules(
|
||||
modules: Exclude<ConfigModule["modules"], undefined>,
|
||||
config?: MedusaCloudOptions
|
||||
config?: MedusaCloudOptions,
|
||||
adminConfig?: AdminOptions
|
||||
) {
|
||||
if (!config) {
|
||||
return
|
||||
@@ -504,6 +526,24 @@ function applyCloudOptionsToModules(
|
||||
...(module.options ?? {}),
|
||||
}
|
||||
break
|
||||
case Modules.AUTH:
|
||||
let callbackUrl = config.oauthCallbackUrl
|
||||
if (!callbackUrl && adminConfig?.backendUrl) {
|
||||
callbackUrl = `${adminConfig?.backendUrl}${adminConfig?.path}/login?auth_provider=cloud`
|
||||
}
|
||||
module.options = {
|
||||
cloud: {
|
||||
oauth_authorize_endpoint: config.oauthAuthorizeEndpoint,
|
||||
oauth_token_endpoint: config.oauthTokenEndpoint,
|
||||
environment_handle: config.environmentHandle,
|
||||
sandbox_handle: config.sandboxHandle,
|
||||
api_key: config.apiKey,
|
||||
callback_url: callbackUrl,
|
||||
disabled: config.oauthDisabled,
|
||||
},
|
||||
...(module.options ?? {}),
|
||||
}
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user