-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit edcb5c9
Showing
19 changed files
with
2,054 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.env.example | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
NODE_ENV=production | ||
OAUTH_CLIENT_ID="" # GitHub or GitLab OAuth application client ID | ||
OAUTH_CLIENT_SECRET="" # GitHub or GitLab OAuth application client secret | ||
ORIGINS=example.com,*.example.com # Domain patterns for CMS installations using the IDRC CMS Authenticator | ||
PORT=3000 | ||
REDIRECT_URL=https://auth.example.com/callback # A full URL to the /callback route of your deployed IDRC CMS Authenticator. This will also be configured as the callback URL in your GitHub or GitLab OAuth application. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: Lint and format files | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
pull_request: | ||
branches: [main] | ||
|
||
jobs: | ||
lint-format: | ||
name: Lint and format files | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Cache node modules | ||
uses: actions/cache@v4 | ||
with: | ||
path: node_modules | ||
key: ${{ runner.OS }}-build-${{ hashFiles('**/package-lock.json') }} | ||
- name: Install dependencies and lint files | ||
run: | | ||
npm ci | ||
npm run lint | ||
npm run format |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
name: Publish release | ||
|
||
on: | ||
push: | ||
branches: [main] | ||
|
||
jobs: | ||
release-please: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: google-github-actions/release-please-action@v4 | ||
id: release | ||
with: | ||
token: ${{ secrets.GITHUB_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.env | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
lint-staged |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
FROM node:20-alpine | ||
|
||
WORKDIR /usr/src/app | ||
|
||
COPY package*.json ./ | ||
|
||
RUN npm i --only=production | ||
|
||
COPY . . | ||
|
||
EXPOSE 3000 | ||
CMD [ "npm", "start" ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# IDRC CMS Authenticator | ||
|
||
A simple [Express](https://expressjs.com/) application which allows [Sveltia CMS](https://github.com/sveltia/sveltia-cms) or [Decap CMS](https://decapcms.org) to authenticate with [GitHub](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps) or [GitLab](https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow). | ||
|
||
Based on [netlify-cms-github-oauth-provider](https://github.com/vencax/netlify-cms-github-oauth-provider). | ||
|
||
## Usage | ||
|
||
## Configuration | ||
|
||
1. Create an OAuth application on [GitHub](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) or [GitLab](https://docs.gitlab.com/ee/integration/oauth_provider.html). Make sure to set the **authorization callback URL** to the `callback` route of the deployed application. For example, if you were going to deploy the IDRC CMS Authenticator to `https://auth.example.com`, the **authorization callback URL** would be `https://auth.example.com/callback`. | ||
2. Configure environment variables for the application in a `.env` file: | ||
|
||
```bash | ||
AUTH_TARGET=_self | ||
NODE_ENV=production | ||
# GitHub or GitLab OAuth application client ID | ||
OAUTH_CLIENT_ID="" | ||
# GitHub or GitLab OAuth application client secret | ||
OAUTH_CLIENT_SECRET="" | ||
# Domain patterns for CMS installations using the IDRC CMS Authenticator | ||
ORIGINS=example.com,*.example.com | ||
PORT=3000 | ||
# A full URL to the /callback route of your deployed IDRC CMS Authenticator. | ||
# This will also be configured as the authorization callback URL in your GitHub or GitLab OAuth application. | ||
REDIRECT_URL=https://auth.example.com/callback | ||
``` | ||
|
||
GitLab requires additional information as follows: | ||
|
||
```bash | ||
OAUTH_PROVIDER=gitlab | ||
SCOPES=api | ||
OAUTH_AUTHORIZE_PATH=/oauth/authorize | ||
OAUTH_TOKEN_PATH=/oauth/token | ||
``` | ||
|
||
## Serving locally | ||
|
||
1. Install the required packages: `npm install` | ||
2. Run the application: `npm start` | ||
|
||
The application will be available at <http://localhost:3000>. | ||
|
||
**Note:** that the authorization callback cannot redirect to a `localhost` URL, but you will be able to test the authorization flow. | ||
|
||
## Serving locally using Docker | ||
|
||
You can also build and serve the application locally from a [Docker](https://docs.docker.com/get-docker) container. | ||
|
||
With Docker installed, run the following commands to build a Docker image and start a container: | ||
|
||
1. Build the image: `docker build -t idrc-cms-authenticator .` | ||
2. Run the container: `docker run --name idrc-cms-authenticator -p 3000:3000 idrc-cms-authenticator` | ||
|
||
The server will be available at <http://localhost:3000>. | ||
|
||
**Note:** the authorization callback cannot redirect to a `localhost` URL, but you will be able to test the authorization flow. | ||
|
||
## Deployment using Docker Compose | ||
|
||
TODO. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
require("dotenv").config({ silent: true }); | ||
|
||
const express = require("express"); | ||
const middleware = require("./middleware/index.js"); | ||
const port = process.env.PORT || 3000; | ||
|
||
const app = express(); | ||
|
||
app.get("/auth", middleware.auth); | ||
app.get("/callback", middleware.callback); | ||
app.get("/success", middleware.success); | ||
app.get("/", middleware.index); | ||
|
||
app.listen(port, () => { | ||
console.log(`IDRC CMS Authenticator listening on port ${port}.`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"$schema": "https://biomejs.dev/schemas/1.8.1/schema.json", | ||
"organizeImports": { | ||
"enabled": true | ||
}, | ||
"linter": { | ||
"enabled": true, | ||
"rules": { | ||
"recommended": true | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
const randomstring = require("randomstring"); | ||
|
||
module.exports = (oauth2) => { | ||
// Authorization uri definition | ||
const authorizationUri = oauth2.authorizeURL({ | ||
redirectURI: process.env.REDIRECT_URL, | ||
scope: process.env.SCOPES || "repo,user", | ||
state: randomstring.generate(32), | ||
}); | ||
|
||
return (req, res, next) => { | ||
res.redirect(authorizationUri); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
const generateScript = require("./login.js"); | ||
|
||
module.exports = (oauth2, oauthProvider) => { | ||
function callbackMiddleWare(req, res, next) { | ||
const code = req.query.code; | ||
const options = { | ||
code: code, | ||
}; | ||
|
||
if (oauthProvider === "gitlab") { | ||
options.client_id = process.env.OAUTH_CLIENT_ID; | ||
options.client_secret = process.env.OAUTH_CLIENT_SECRET; | ||
options.grant_type = "authorization_code"; | ||
options.redirect_uri = process.env.REDIRECT_URL; | ||
} | ||
|
||
oauth2 | ||
.getToken(options) | ||
.then((result) => { | ||
const token = oauth2.createToken(result); | ||
content = { | ||
token: token.token.token.access_token, | ||
provider: oauthProvider, | ||
}; | ||
return { message: "success", content }; | ||
}) | ||
.catch((error) => { | ||
console.error("Access Token Error", error.message); | ||
return { message: "error", content: JSON.stringify(error) }; | ||
}) | ||
.then((result) => { | ||
const script = generateScript( | ||
oauthProvider, | ||
result.message, | ||
result.content, | ||
); | ||
return res.send(script); | ||
}); | ||
} | ||
return callbackMiddleWare; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
const simpleOauthModule = require("simple-oauth2"); | ||
const authMiddleWareInit = require("./auth.js"); | ||
const callbackMiddleWareInit = require("./callback.js"); | ||
const oauthProvider = process.env.OAUTH_PROVIDER || "github"; | ||
|
||
const config = { | ||
client: { | ||
id: process.env.OAUTH_CLIENT_ID, | ||
secret: process.env.OAUTH_CLIENT_SECRET, | ||
}, | ||
auth: { | ||
tokenHost: process.env.GIT_HOSTNAME || "https://github.com", | ||
tokenPath: process.env.OAUTH_TOKEN_PATH || "/login/oauth/access_token", | ||
authorizePath: process.env.OAUTH_AUTHORIZE_PATH || "/login/oauth/authorize", | ||
}, | ||
}; | ||
|
||
const oauth2 = new simpleOauthModule.AuthorizationCode(config); | ||
|
||
function indexMiddleWare(req, res) { | ||
res.send(`<a href="/auth"> | ||
Log in with ${oauthProvider === "github" ? "GitHub" : "GitLab"} | ||
</a>`); | ||
} | ||
|
||
module.exports = { | ||
auth: authMiddleWareInit(oauth2), | ||
callback: callbackMiddleWareInit(oauth2, oauthProvider), | ||
success: (req, res) => { | ||
res.send(""); | ||
}, | ||
index: indexMiddleWare, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// if ( | ||
// !process.env.ORIGINS.match( | ||
// /^((\*|([\w_-]{2,}))\.)*(([\w_-]{2,})\.)+(\w{2,})(\,((\*|([\w_-]{2,}))\.)*(([\w_-]{2,})\.)+(\w{2,}))*$/, | ||
// ) | ||
// ) { | ||
// throw new Error( | ||
// "process.env.ORIGINS MUST be comma separated list \ | ||
// of origins that login can succeed on.", | ||
// ); | ||
// } | ||
const origins = process.env.ORIGINS.split(","); | ||
|
||
module.exports = (oauthProvider, message, content) => ` | ||
<script> | ||
(function() { | ||
function contains(arr, elem) { | ||
for (var i = 0; i < arr.length; i++) { | ||
if (arr[i].indexOf('*') >= 0) { | ||
const regex = new RegExp(arr[i].replaceAll('.', '\\\\.').replaceAll('*', '[\\\\w_-]+')) | ||
console.log(regex) | ||
if (elem.match(regex) !== null) { | ||
return true; | ||
} | ||
} else { | ||
if (arr[i] === elem) { | ||
return true; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
function recieveMessage(e) { | ||
console.log("recieveMessage %o", e) | ||
if (!contains(${JSON.stringify(origins)}, e.origin.replace('https://', 'http://').replace('http://', ''))) { | ||
console.log('Invalid origin: %s', e.origin); | ||
return; | ||
} | ||
// send message to main window with da app | ||
window.opener.postMessage( | ||
'authorization:${oauthProvider}:${message}:${JSON.stringify(content)}', | ||
e.origin | ||
) | ||
} | ||
window.addEventListener("message", recieveMessage, false) | ||
// Start handshare with parent | ||
console.log("Sending message: %o", "${oauthProvider}") | ||
window.opener.postMessage("authorizing:${oauthProvider}", "*") | ||
})() | ||
</script>`; |
Oops, something went wrong.