Skip to content

Commit

Permalink
Switched docker build to path based to allow .dockerignore to work. I…
Browse files Browse the repository at this point in the history
…mplemented OIDC support. Updated README.md
  • Loading branch information
glenndehaan committed Aug 23, 2024
1 parent 89bc27a commit bfe2d39
Show file tree
Hide file tree
Showing 8 changed files with 729 additions and 30 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: glenndehaan/unifi-voucher-site:${{ github.ref_name }}
- name: Build and push (latest)
if: github.ref == 'refs/heads/master'
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: glenndehaan/unifi-voucher-site:latest
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ services:
AUTH_PASSWORD: '0000'
# The Bearer token used for the API
AUTH_TOKEN: '00000000-0000-0000-0000-000000000000'
# OIDC issuer base url provided by oauth provider. Example: https://auth.example.com/.well-known/openid-configuration
AUTH_OIDC_ISSUER_BASE_URL: ''
# OIDC UniFi Voucher base url (This application). Example: https://voucher.example.com
AUTH_OIDC_APP_BASE_URL: ''
# OIDC client id provided by oauth provider
AUTH_OIDC_CLIENT_ID: ''
# Disables the login/authentication for the portal and API
AUTH_DISABLE: 'false'
# Voucher Types, format: expiration in minutes (required),single-use or multi-use vouchers value - '0' is for multi-use - '1' is for single-use (optional),upload speed limit in kbps (optional),download speed limit in kbps (optional),data transfer limit in MB (optional)
Expand Down Expand Up @@ -290,6 +296,31 @@ Once the SMTP environment variables are configured, the email feature will be av

![Example Email](https://github.com/user-attachments/assets/45615db3-df76-48b0-ad30-05236e3754c1)

## OpenID Connect (OIDC) Authentication

The UniFi Voucher Site allows seamless integration with OpenID Connect (OIDC), enabling users to authenticate through their preferred identity provider (IdP). The setup is straightforward, requiring configuration through environment variables to align with your existing OIDC provider.

### Configuration

To enable OIDC authentication, set the following environment variables in your application’s environment:

- **`AUTH_OIDC_ISSUER_BASE_URL`**:
The base URL of your OIDC provider. This is typically the URL where the well-known OIDC configuration is hosted (e.g., `https://auth.example.com/.well-known/openid-configuration`).

- **`AUTH_OIDC_APP_BASE_URL`**:
The base URL of your UniFi Voucher Site application. This should be the public URL where the site is accessible to users (e.g., `https://voucher.example.com`).

- **`AUTH_OIDC_CLIENT_ID`**:
The client ID registered with your OIDC provider. This value is specific to the OIDC client created for the UniFi Voucher Site.

> Please note that **enabling OIDC support will automatically disable the built-in login system**. Once OIDC is activated, all user authentication will be handled through your configured identity provider, and the local login mechanism will no longer be available.

### OIDC Client Configuration

When configuring your OIDC client, ensure that the following settings are enabled:

- **Implicit Flow Support**: The OIDC client **must** support the Implicit flow. This is essential as the UniFi Voucher Site relies on this flow for authentication.

## Screenshots

### Login (Desktop)
Expand Down
14 changes: 12 additions & 2 deletions middlewares/authorization.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
* Import own modules
*/
const jwt = require('../modules/jwt');
const oidc = require('express-openid-connect');

/**
* Global variables
*/
const authDisabled = (process.env.AUTH_DISABLE === 'true') || false;
const oidcIssuerBaseUrl = process.env.AUTH_OIDC_ISSUER_BASE_URL || '';
const oidcAppBaseUrl = process.env.AUTH_OIDC_APP_BASE_URL || '';
const oidcClientId = process.env.AUTH_OIDC_CLIENT_ID || '';

/**
* Verifies if a user is signed in
Expand All @@ -23,8 +27,8 @@ module.exports = {
* @return {Promise<void>}
*/
web: async (req, res, next) => {
// Check if authentication is enabled
if(!authDisabled) {
// Check if authentication is enabled & OIDC is disabled
if(!authDisabled && (oidcIssuerBaseUrl === '' && oidcAppBaseUrl === '' && oidcClientId === '')) {
// Check if user has an existing authorization cookie
if (!req.cookies.authorization) {
res.redirect(302, `${req.headers['x-ingress-path'] ? req.headers['x-ingress-path'] : ''}/login`);
Expand All @@ -44,6 +48,12 @@ module.exports = {
}
}

// Check if authentication is enabled & OIDC is enabled
if(!authDisabled && (oidcIssuerBaseUrl !== '' && oidcAppBaseUrl !== '' && oidcClientId !== '')) {
const middleware = oidc.requiresAuth();
return middleware(req, res, next);
}

next();
},

Expand Down
2 changes: 1 addition & 1 deletion modules/jwt.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const settings = {
};

/**
* Exports the UniFi voucher functions
* Exports the JWT functions
*/
module.exports = {
/**
Expand Down
41 changes: 41 additions & 0 deletions modules/oidc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Import base packages
*/
const crypto = require('crypto');
const oidc = require('express-openid-connect');

/**
* Import own modules
*/
const log = require('./log');

/**
* OIDC Settings
*
* @type {{baseURL: string, idpLogout: boolean, authRequired: boolean, clientID: string, issuerBaseURL: string, secret: string}}
*/
const settings = {
issuerBaseURL: process.env.AUTH_OIDC_ISSUER_BASE_URL,
baseURL: process.env.AUTH_OIDC_APP_BASE_URL,
clientID: process.env.AUTH_OIDC_CLIENT_ID,
secret: '',
idpLogout: true,
authRequired: false
};

/**
* Exports the OIDC functions
*/
module.exports = {
/**
* Set the OIDC secret & setup OIDC middleware
*
* @param app
*/
init: (app) => {
settings.secret = crypto.randomBytes(20).toString('hex');
log.info(`[OIDC] Set secret: ${settings.secret}`);
app.use(oidc.auth(settings));
log.info(`[OIDC] Issuer: ${settings.issuerBaseURL}, Client: ${settings.clientID}`);
}
};
Loading

0 comments on commit bfe2d39

Please sign in to comment.