Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ To learn how to use an example, open its `README.md` file. You'll find the detai
| [Meilisearch Integration](./meilisearch-integration/README.md) | Integration | Integrate Meilisearch into Medusa to allow searching through products. |
| [Memcached Caching Module Provider](./memcached-caching/README.md) | Integration | Integrate Memcached as a Caching Module Provider. |
| [Migrate from Magento](./migrate-from-magento/README.md) | Custom Feature | Migrate products and categories from Magento |
| [Okta Authentication](./okta-integration/) | Integration | Allow admin users to authenticate with Okta. |
| [Add Gift Messages to Line Items](./order-gift-message/README.md) | Custom Feature | Customize the Next.js Starter Storefront and Medusa Admin to support gift options for line items. |
| [Payload Integration](./payload-integration/README.md) | Integration | Integrate Payload CMS with Medusa |
| [Personalized Products](./personalized-products/README.md) | Custom Feature | Allow customers to personalize products with custom values and prices. |
Expand Down
15 changes: 15 additions & 0 deletions okta-integration/.env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
STORE_CORS=http://localhost:8000,https://docs.medusajs.com
ADMIN_CORS=http://localhost:5173,http://localhost:9000,https://docs.medusajs.com
AUTH_CORS=http://localhost:5173,http://localhost:9000,https://docs.medusajs.com
REDIS_URL=redis://localhost:6379
JWT_SECRET=supersecret
COOKIE_SECRET=supersecret
DATABASE_URL=postgres://postgres@localhost/$DB_NAME # change user and password if necessary
DB_NAME=medusa-okta-integration
POSTGRES_URL=
ADMIN_AUTH_TYPE=jwt

OKTA_DOMAIN=
OKTA_CLIENT_ID=
OKTA_CLIENT_SECRET=
OKTA_REDIRECT_URI=
26 changes: 26 additions & 0 deletions okta-integration/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/dist
.env
.DS_Store
/uploads
/node_modules
yarn-error.log

.idea

coverage

!src/**

./tsconfig.tsbuildinfo
medusa-db.sql
build
.cache

.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

.medusa
1 change: 1 addition & 0 deletions okta-integration/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
146 changes: 146 additions & 0 deletions okta-integration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Medusa v2 Example: Okta Integration

This directory holds the code for the [Okta Integration Tutorial](https://docs.medusajs.com/resources/integrations/guides/okta).

You can either:

- [install and use it as a Medusa application](#installation);
- or [copy its source files into an existing Medusa application](#copy-into-existing-medusa-application).

## Prerequisites

- [Node.js v20+](https://nodejs.org/en/download)
- [Git CLI](https://git-scm.com/downaloads)
- [PostgreSQL](https://www.postgresql.org/download/)
- [Okta](https://www.okta.com/) account with an application. Can be a developer account.

## Installation

1. Clone the repository and change to the `okta-integration` directory:

```bash
git clone https://github.com/medusajs/examples.git
cd examples/okta-integration
```

2\. Rename the `.env.template` file to `.env`.

3\. If necessary, change the PostgreSQL username, password, and host in the `DATABASE_URL` environment variable.

4\. Set the Okta environment variables:

```bash
OKTA_DOMAIN=
OKTA_CLIENT_ID=
OKTA_CLIENT_SECRET=
OKTA_REDIRECT_URI=
```

Where:

- `OKTA_DOMAIN`: The Okta domain of your organization. You can find it by going to Security -> API -> Authorization Servers in your Okta dashboard. It's the URL before `/oauth2/default`.
- `OKTA_CLIENT_ID`: The Client ID of your Okta application.
- `OKTA_CLIENT_SECRET`: The Client Secret of your Okta application.
- `OKTA_REDIRECT_URI`: The URL where Okta will redirect users after authentication. It's the same URL you set in the application's Sign-in redirect URIs.

Learn more about retrieving these variables in the [tutorial](https://docs.medusajs.com/resources/integrations/guides/okta#f-set-up-environment-variables)

5\. Install dependencies:

```bash
yarn # or npm install
```

6\. Setup and seed the database:

```bash
createdb medusa-okta-integration
npx medusa db:setup
yarn seed # or npm run seed
```

7\. Start the Medusa application:

```bash
yarn dev # or npm run dev
```

Open `http://localhost:9000/app`. You'll find a new "Login with Okta" button on the homepage where you can authenticate with Okta.

## Copy into Existing Medusa Application

If you have an existing Medusa application, copy the following directories and files into your project:

- `src/admin`
- `src/api`
- `src/modules/okta`
- `src/workflows`

Then, add the Okta Auth Module Provider to `medusa-config.ts`:

```ts
module.exports = defineConfig({
// ...
modules: [
{
resolve: "@medusajs/medusa/auth",
dependencies: [
Modules.CACHE,
ContainerRegistrationKeys.LOGGER,
],
options: {
providers: [
// Default email/password provider
{
resolve: "@medusajs/medusa/auth-emailpass",
id: "emailpass",
},
// other providers...
// Okta auth provider
{
resolve: "./src/modules/okta",
id: "okta",
options: {
oktaDomain: process.env.OKTA_DOMAIN!,
clientId: process.env.OKTA_CLIENT_ID!,
clientSecret: process.env.OKTA_CLIENT_SECRET!,
redirectUri: process.env.OKTA_REDIRECT_URI!,
},
},
],
},
},
],
})
```

Next, add the following environment variables:

```bash
OKTA_DOMAIN=
OKTA_CLIENT_ID=
OKTA_CLIENT_SECRET=
OKTA_REDIRECT_URI=
```

Where:

- `OKTA_DOMAIN`: The Okta domain of your organization. You can find it by going to Security -> API -> Authorization Servers in your Okta dashboard. It's the URL before `/oauth2/default`.
- `OKTA_CLIENT_ID`: The Client ID of your Okta application.
- `OKTA_CLIENT_SECRET`: The Client Secret of your Okta application.
- `OKTA_REDIRECT_URI`: The URL where Okta will redirect users after authentication. It's the same URL you set in the application's Sign-in redirect URIs.

Learn more about retrieving these variables in the [tutorial](https://docs.medusajs.com/resources/integrations/guides/okta#f-set-up-environment-variables)

Finally, start the Medusa application:

```bash
yarn dev # or npm run dev
```

Open `http://localhost:9000/app`. You'll find a new "Login with Okta" button on the homepage where you can authenticate with Okta.

## More Resources

- [Medusa Documentatin](https://docs.medusajs.com)
- [Okta Developer Documentation](https://developer.okta.com/)
24 changes: 24 additions & 0 deletions okta-integration/instrumentation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Uncomment this file to enable instrumentation and observability using OpenTelemetry
// Refer to the docs for installation instructions: https://docs.medusajs.com/learn/debugging-and-testing/instrumentation

// import { registerOtel } from "@medusajs/medusa"
// // If using an exporter other than Zipkin, require it here.
// import { ZipkinExporter } from "@opentelemetry/exporter-zipkin"

// // If using an exporter other than Zipkin, initialize it here.
// const exporter = new ZipkinExporter({
// serviceName: 'my-medusa-project',
// })

// export function register() {
// registerOtel({
// serviceName: 'medusajs',
// // pass exporter
// exporter,
// instrument: {
// http: true,
// workflows: true,
// query: true
// },
// })
// }
29 changes: 29 additions & 0 deletions okta-integration/integration-tests/http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Integration Tests

The `medusa-test-utils` package provides utility functions to create integration tests for your API routes and workflows.

For example:

```ts
import { medusaIntegrationTestRunner } from "medusa-test-utils"

medusaIntegrationTestRunner({
testSuite: ({ api, getContainer }) => {
describe("Custom endpoints", () => {
describe("GET /store/custom", () => {
it("returns correct message", async () => {
const response = await api.get(
`/store/custom`
)

expect(response.status).toEqual(200)
expect(response.data).toHaveProperty("message")
expect(response.data.message).toEqual("Hello, World!")
})
})
})
}
})
```

Learn more in [this documentation](https://docs.medusajs.com/learn/debugging-and-testing/testing-tools/integration-tests).
15 changes: 15 additions & 0 deletions okta-integration/integration-tests/http/health.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { medusaIntegrationTestRunner } from "@medusajs/test-utils"
jest.setTimeout(60 * 1000)

medusaIntegrationTestRunner({
inApp: true,
env: {},
testSuite: ({ api }) => {
describe("Ping", () => {
it("ping the server health endpoint", async () => {
const response = await api.get('/health')
expect(response.status).toEqual(200)
})
})
},
})
3 changes: 3 additions & 0 deletions okta-integration/integration-tests/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { MetadataStorage } = require("@medusajs/framework/mikro-orm/core")

MetadataStorage.clear()
27 changes: 27 additions & 0 deletions okta-integration/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { loadEnv } = require("@medusajs/utils");
loadEnv("test", process.cwd());

module.exports = {
transform: {
"^.+\\.[jt]s$": [
"@swc/jest",
{
jsc: {
parser: { syntax: "typescript", decorators: true },
},
},
],
},
testEnvironment: "node",
moduleFileExtensions: ["js", "ts", "json"],
modulePathIgnorePatterns: ["dist/", "<rootDir>/.medusa/"],
setupFiles: ["./integration-tests/setup.js"],
};

if (process.env.TEST_TYPE === "integration:http") {
module.exports.testMatch = ["**/integration-tests/http/*.spec.[jt]s"];
} else if (process.env.TEST_TYPE === "integration:modules") {
module.exports.testMatch = ["**/src/modules/*/__tests__/**/*.[jt]s"];
} else if (process.env.TEST_TYPE === "unit") {
module.exports.testMatch = ["**/src/**/__tests__/**/*.unit.spec.[jt]s"];
}
50 changes: 50 additions & 0 deletions okta-integration/medusa-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { loadEnv, defineConfig } from '@medusajs/framework/utils'
import { Modules, ContainerRegistrationKeys } from '@medusajs/framework/utils'

loadEnv(process.env.NODE_ENV || 'development', process.cwd())

module.exports = defineConfig({
projectConfig: {
databaseUrl: process.env.DATABASE_URL,
http: {
storeCors: process.env.STORE_CORS!,
adminCors: process.env.ADMIN_CORS!,
authCors: process.env.AUTH_CORS!,
jwtSecret: process.env.JWT_SECRET || "supersecret",
cookieSecret: process.env.COOKIE_SECRET || "supersecret",
authMethodsPerActor: {
user: ["emailpass", "okta"],
customer: ["emailpass"],
},
}
},
modules: [
{
resolve: "@medusajs/medusa/auth",
dependencies: [
Modules.CACHE,
ContainerRegistrationKeys.LOGGER,
],
options: {
providers: [
// Default email/password provider
{
resolve: "@medusajs/medusa/auth-emailpass",
id: "emailpass",
},
// Okta auth provider
{
resolve: "./src/modules/okta",
id: "okta",
options: {
oktaDomain: process.env.OKTA_DOMAIN!,
clientId: process.env.OKTA_CLIENT_ID!,
clientSecret: process.env.OKTA_CLIENT_SECRET!,
redirectUri: process.env.OKTA_REDIRECT_URI!,
},
},
],
},
},
],
})
Loading