Skip to content

Commit

Permalink
Package Pizzly auth server to share with Nango (#288)
Browse files Browse the repository at this point in the history
* Package auth server to share with Nango

* Small fixes

Co-authored-by: Bastien Beurier <[email protected]>
  • Loading branch information
bastienbeurier and Bastien Beurier authored Dec 15, 2022
1 parent f426b57 commit 990243a
Show file tree
Hide file tree
Showing 40 changed files with 276 additions and 173 deletions.
45 changes: 28 additions & 17 deletions .env
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
###############################################################################
#
# Secure your instance
# Configuration
#
# 1. Secure requests to the API by generating 2 API keys (e.g. using https://codepen.io/corenominal/pen/rxOmMJ)
# The PIZZLY_SECRET_KEY should never be shared and authenticates endpoints related to provider configs and fetching credentials.
# The PIZZLY_PUBLISHABLE_KEY is not secret, is visible in your frontend code, and authenticates endpoints related to the OAuth flow.
# - Secure requests to the API by generating 2 API keys (e.g. using https://codepen.io/corenominal/pen/rxOmMJ)
# The PIZZLY_SECRET_KEY should never be shared and authenticates endpoints related to provider configs and credentials.
# The PIZZLY_PUBLISHABLE_KEY is not secret, is visible in your frontend code, and authenticates endpoints related to triggering the OAuth dance (less sensitive).
#
# PIZZLY_SECRET_KEY=""
# PIZZLY_PUBLISHABLE_KEY=""
#
###############################################################################
#
# Database connection
# - Customize the OAuth callback URL
#
# 1. Provide specific database attributes
# (current values are defaults for running Pizzly locally with Docker)
# AUTH_CALLBACK_URL=""
#
# PIZZLY_DB_USER="nango"
# PIZZLY_DB_PASSWORD="nango"
# PIZZLY_DB_HOST="nango-db"
# PIZZLY_DB_PORT=5432
# PIZZLY_DB_NAME="nango"
# PIZZLY_DB_SSL=FALSE
#
###############################################################################
# - Customize database to store provider configurations and credentials.
# (running 'docker compose up' creates a local Postgres database with the following credentials)
#
# - Set the log level (debug: most verbose, info: recommended for production, error: least verbose)
NANGO_DB_USER=nango
NANGO_DB_PASSWORD=nango
NANGO_DB_HOST=nango-db
NANGO_DB_PORT=5432
NANGO_DB_NAME=nango
NANGO_DB_SSL=FALSE
#
#
# - Configure server port (current value is the default for running Pizzly locally).
#
SERVER_PORT=3003
#
# LOG_LEVEL=info
#
# - Configure server host (current value is the default for running Pizzly locally).
#
SERVER_HOST="http://localhost"
#
#
# - Set the log level (debug: most verbose, info: recommended for production, error: least verbose)
#
LOG_LEVEL=info
#
###############################################################################
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Pizzly takes care of the OAuth dance for you and makes sure your access tokens a
<br />

<br/>
<a href="https://github.com/NangoHQ/Pizzly/blob/master/packages/server/templates.yaml">All supported APIs</a>
<a href="nango.dev/oauth-providers">All supported APIs</a>
·
<a href="https://docs.nango.dev/pizzly/contribute-api">Contribute an API</a>
·
Expand All @@ -45,7 +45,7 @@ Pizzly is easy to try in 5 minutes and can be deployed in 15.
Start a **new OAuth flow with 2 lines of code in your frontend**:

```ts
var pizzly = new Pizzly('https://localhost:3004')
var pizzly = new Pizzly('https://localhost:3003')

// Trigger an OAuth flow for the user to authenticate with Slack
let result = await pizzly.auth('slack', '<user-id>')
Expand All @@ -67,9 +67,9 @@ More than 50 APIs are preconfigured to work out-of-the-box. Including:
- **Communication**: Gmail, Microsoft Teams, Slack, Zoom etc.
- **Productivity**: Asana, Airtable, Google Drive, Google Calendar, Trello, Google sheets, ClickUp etc.
- **Social**: Twitter, LinkedIn, Reddit, Facebook etc.
- [and more...](https://github.com/NangoHQ/Pizzly/blob/master/packages/server/templates.yaml)
- [and more...](nango.dev/oauth-providers)

If your favorite API is missing [open a GitHub issue](https://github.com/NangoHQ/Pizzly/issues/new) or [contribute it right away](https://docs.nango.dev/pizzly/contribute-api): The API configurations are just simple [entries in a YAML file](https://github.com/NangoHQ/Pizzly/blob/master/packages/server/templates.yaml).
If your favorite API is missing [open a GitHub issue](https://github.com/NangoHQ/Pizzly/issues/new) or [contribute it right away](https://docs.nango.dev/pizzly/contribute-api): The API configurations are just simple [entries in a YAML file](nango.dev/oauth-providers).

## 🛡️ Small, self-contained & ready for production

Expand All @@ -94,7 +94,7 @@ cd Pizzly
docker compose up
```

Make sure you have a client ID & secret ready for the API you want to use, e.g. for GitHub [register it here](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app). Use `http://localhost:3004/oauth/callback` as the callback URL.
Make sure you have a client ID & secret ready for the API you want to use, e.g. for GitHub [register it here](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app). Use `http://localhost:3003/oauth/callback` as the callback URL.

Enable the GitHub API and add your OAuth client id & secret with the CLI:

Expand All @@ -114,7 +114,7 @@ Open the demo page in your browser at [http://localhost:8080/bin/sample.html](ht
Once the flow is finished you can use our SDKs or REST API to get access tokens in the backend (automatically refreshed) and make API calls:
```ts
import { Pizzly } from '@nangohq/pizzly-node'
let pizzly = new Pizzly('http://localhost:3004');
let pizzly = new Pizzly('http://localhost:3003');
var githubAccessToken = await pizzly.accessToken('github', '1') // Always fresh & ready to use
```

Expand All @@ -136,7 +136,7 @@ Nango make syncing data from APIs to your database fast & flexible: It takes car

⭐  Follow our development by starring us here on GitHub ⭐

- Explore [the full list of supported APIs](https://github.com/NangoHQ/Pizzly/blob/master/packages/server/templates.yaml)
- Explore [the full list of supported APIs](nango.dev/oauth-providers)
- Easily sync data from any API with [`Nango.sync`](https://github.com/NangoHQ/nango)
- [Contribute a new API](https://docs.nango.dev/pizzly/contribute-api)
- Share feedback or ask questions on the [Slack community](https://nango.dev/slack)
Expand Down
5 changes: 1 addition & 4 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,10 @@ services:
image: nangohq/pizzly-server
container_name: pizzly-server
restart: always
environment:
- SERVER_HOST=http://localhost
- SERVER_PORT=3004
env_file:
- .env
ports:
- '3004:3004'
- '3003:3003'
depends_on:
- pizzly-db
networks:
Expand Down
92 changes: 57 additions & 35 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/auth/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tsconfig.tsbuildinfo
dist/*
36 changes: 36 additions & 0 deletions packages/auth/lib/auth.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2022 Nango, all rights reserved.
*/

import type { Express } from 'express';
import db from './db/database.js';
import oauthController from './controllers/oauth.contoller.js';
import configController from './controllers/config.controller.js';
import connectionController from './controllers/connection.controller.js';
import accessMiddleware from './controllers/access.middleware.js';
import path from 'path';
import { dirname } from './utils/utils.js';

class AuthServer {
async setup(app: Express) {
await db.knex.raw(`CREATE SCHEMA IF NOT EXISTS ${db.schema()}`);
await db.migrate(path.join(dirname(), '../../lib/db/migrations'));

app.route('/oauth/connect/:providerConfigKey').get(accessMiddleware.checkPkey.bind(accessMiddleware), oauthController.oauthRequest.bind(oauthController));
app.route('/oauth/callback').get(oauthController.oauthCallback.bind(oauthController));
app.route('/config').get(accessMiddleware.checkSecret.bind(accessMiddleware), configController.listProviderConfigs.bind(configController));
app.route('/config/:providerConfigKey').get(accessMiddleware.checkSecret.bind(accessMiddleware), configController.getProviderConfig.bind(configController));
app.route('/config').post(accessMiddleware.checkSecret.bind(accessMiddleware), configController.createProviderConfig.bind(configController));
app.route('/config').put(accessMiddleware.checkSecret.bind(accessMiddleware), configController.editProviderConfig.bind(configController));
app.route('/config/:providerConfigKey').delete(
accessMiddleware.checkSecret.bind(accessMiddleware),
configController.deleteProviderConfig.bind(configController)
);
app.route('/connection/:connectionId').get(
accessMiddleware.checkSecret.bind(accessMiddleware),
connectionController.getConnectionCreds.bind(connectionController)
);
}
}

export default new AuthServer();
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class OAuthController {
return html(logger, res, providerConfigKey, connectionId, 'provider_config_err', this.errDesc['provider_config_err'](providerConfigKey));
}

logger.info(`OAuth request - mode: ${template.auth_mode}, provider: ${config.provider}, key: ${config.unique_key}, connection ID: ${connectionId}, auth URL: ${template.authorization_url}, callback URL: ${this.callbackUrl}`);

if (template.auth_mode === ProviderAuthModes.OAuth2) {
return this.oauth2Request(template, config, session, res);
} else if (template.auth_mode === ProviderAuthModes.OAuth1) {
Expand Down Expand Up @@ -172,12 +174,14 @@ class OAuthController {
logger.debug(`Received callback for ${session.providerConfigKey} (connection: ${session.connectionId}) - full callback URI: ${req.originalUrl}"`);

const template = this.templates[session.provider]!;
const config = await configService.getProviderConfig(session.providerConfigKey);
const config = (await configService.getProviderConfig(session.providerConfigKey))!;

logger.info(`OAuth callback - mode: ${template.auth_mode}, provider: ${config.provider}, key: ${config.unique_key}, connection ID: ${session.connectionId}`);

if (session.authMode === ProviderAuthModes.OAuth2) {
return this.oauth2Callback(template, config!, session, req, res);
return this.oauth2Callback(template, config, session, req, res);
} else if (session.authMode === ProviderAuthModes.OAuth1) {
return this.oauth1Callback(template, config!, session, req, res);
return this.oauth1Callback(template, config, session, req, res);
}

return html(logger, res, session.providerConfigKey, session.connectionId, 'auth_mode_err', this.errDesc['auth_mode_err'](session.authMode));
Expand Down
23 changes: 23 additions & 0 deletions packages/auth/lib/db/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { Knex } from 'knex';

let config: { development: Knex.Config<any>; production: Knex.Config<any> } = {
development: {
client: 'pg',
connection: {
host: process.env['NANGO_DB_HOST'] || (process.env['SERVER_RUN_MODE'] === 'DOCKERIZED' ? 'nango-db' : 'localhost'),
port: +(process.env['NANGO_DB_PORT'] || 5432),
user: process.env['NANGO_DB_USER'] || 'nango',
database: process.env['NANGO_DB_NAME'] || 'nango',
password: process.env['NANGO_DB_PASSWORD'] || 'nango',
ssl: process.env['NANGO_DB_SSL'] != null && process.env['NANGO_DB_SSL'].toLowerCase() === 'true' ? { rejectUnauthorized: false } : undefined
},
migrations: {
directory: './migrations',
extension: 'ts'
}
},

production: {}
};

export { config };
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class KnexDatabase {
}

schema() {
return process.env['PIZZLY_DB_SCHEMA'] || 'pizzly';
return 'pizzly';
}
}

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
exports.up = function (knex, _) {
var schema = process.env['PIZZLY_DB_SCHEMA'] || 'pizzly';
var schema = 'pizzly';
return knex.schema.withSchema(schema).createTable('_pizzly_connections', function (table) {
table.increments('id').primary();
table.timestamps(true, true);
Expand All @@ -11,6 +11,6 @@ exports.up = function (knex, _) {
};

exports.down = function (knex, _) {
var schema = process.env['PIZZLY_DB_SCHEMA'] || 'pizzly';
var schema = 'pizzly';
return knex.schema.withSchema(schema).dropTable('_pizzly_connections');
};
Loading

0 comments on commit 990243a

Please sign in to comment.