Як налаштувати SSO для Discourse, коли у вас є веб-проєкт на Ruby on Rails як сервер для входу
Крок 1. Стабільна гілка для початку!
Завжди використовуйте стабільну гілку для початку ваших експериментів з Discourse.
https://github.com/discourse/discourse/tree/stable
Основна гілка нестабільна, і це нормально, якщо вона не працює.
Крок 2. Інсталяція
- https://github.com/discourse/discourse/blob/main/docs/INSTALL.md
- https://meta.discourse.org/t/install-discourse-on-macos-for-development/15772
Мій файл docker-compose.yml може стати в пригоді
name: discourse
services:
postgres:
image: postgres:13.4
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=discourse_development
- POSTGRES_PASSWORD=qwerty
- PSQL_HISTFILE=/root/log/.psql_history
ports:
- ${POSTGRES_PORT-5432}:${POSTGRES_PORT:-5432}
volumes:
- ./data/PSQL:/var/lib/postgresql/data
redis:
image: redis:7.4.2
volumes:
- ./data/REDIS:/data
app:
build:
context: ..
dockerfile: ./docker/Dockerfile
environment:
- DISCOURSE_DB_HOST=postgres
- DISCOURSE_DB_PORT=5432
- DISCOURSE_DEV_DB=discourse_development
- DISCOURSE_DB_USERNAME=postgres
- DISCOURSE_DB_PASSWORD=qwerty
- DISCOURSE_REDIS_HOST=redis
- DISCOURSE_REDIS_PORT=6379
ports:
- "3000:3000"
- "4200:4200"
volumes:
- ..:/app
command: sleep infinity
Мій Dockerfile (Mac OS / M1)
# https://meta.discourse.org/t/install-discourse-on-ubuntu-or-debian-for-development/14727/1
# bash <(wget -qO- https://raw.githubusercontent.com/discourse/install-rails/main/linux)
# https://github.com/discourse/discourse/blob/main/docs/DEVELOPER-ADVANCED.md
FROM ruby:3.2-bookworm
ARG PROJECT_PATH=${PROJECT_PATH:-__PROJECTS__/discourse}
# ВСТАНОВЛЕННЯ ЗАЛЕЖНОСТЕЙ
#
# build-essential - Основні інструменти для компіляції програм
# libxslt1-dev - Бібліотека для обробки XSLT
# libcurl4-openssl-dev - Бібліотека для HTTP-запитів з підтримкою SSL
# libksba8 - Бібліотеки для криптографічної функціональності
# libksba-dev - Бібліотеки для криптографічної функціональності
# libreadline-dev - Бібліотека для GNU readline (інтерактивна командна строка)
# libssl-dev - Бібліотека для підтримки SSL/TLS
# zlib1g-dev - Бібліотека для стиснення
# libsnappy-dev - Бібліотека для стиснення Snappy
# libyaml-dev - Бібліотека для розбору YAML
# libpq-dev - Бібліотека клієнта PostgreSQL для підключення до бази даних
# postgresql-client - Клієнт PostgreSQL для взаємодії з віддаленими базами даних
# telnet - Інструмент для тестування мережевих сервісів
# nano - Текстовий редактор командного рядка
# git - Система контролю версій Git
# net-tools - Утиліти для діагностики та тестування мережевих з'єднань
# dnsutils - Інструменти для запитів DNS
# iputils-ping - Утиліти для пінгу хостів та тестування з'єднань
# curl - Командний інструмент для передачі даних з URL
# wget - Командний інструмент для завантаження файлів
# tzdata - Дані про часові пояси для керування часом
# advancecomp - Інструменти для оптимізації PNG та MNG файлів
# jhead - Інструмент для відображення та маніпулювання даними Exif
# jpegoptim - Інструмент для оптимізації JPEG файлів
# libjpeg-turbo-progs - Інструменти для оптимізації JPEG файлів
# optipng - Інструмент для оптимізації PNG файлів
# pngcrush - Інструмент для оптимізації PNG файлів
# pngquant - Інструмент для оптимізації PNG файлів
# gnupg2 - GNU Privacy Guard для безпечного зв'язку та зберігання даних
# libjpeg-dev - Розробницькі файли для бібліотеки JPEG
# libpng-dev - Розробницькі файли для бібліотеки PNG
# libtiff-dev - Розробницькі файли для бібліотеки TIFF
# libwebp-dev - Розробницькі файли для бібліотеки WebP
# libxml2-dev - Розробницькі файли для бібліотеки XML
# libltdl-dev - Розробницькі файли для бібліотеки libtool
# libfreetype6-dev - Розробницькі файли для бібліотеки FreeType
# liblcms2-dev - Розробницькі файли для бібліотеки Little CMS
# liblqr-1-0-dev - Розробницькі файли для бібліотеки Liquid Rescale
# libfftw3-dev - Розробницькі файли для бібліотеки Fastest Fourier Transform in the West
# ghostscript - Інтерпретатор для мови PostScript та PDF
#
RUN apt-get update -qq && apt-get install -y \
build-essential \
libxs
libksba-dev \
libreadline-dev \
libssl-dev \
zlib1g-dev \
libsnappy-dev \
libyaml-dev \
libpq-dev \
postgresql-client \
telnet \
nano \
git \
net-tools \
dnsutils \
iputils-ping \
curl \
wget \
tzdata \
advancecomp \
jhead \
jpegoptim \
libjpeg-turbo-progs \
optipng \
pngcrush \
pngquant \
gnupg2 \
libjpeg-dev \
libpng-dev \
libtiff-dev \
libwebp-dev \
libxml2-dev \
libl
liblqr-1-0-dev \
libfftw3-dev \
ghostscript \
&& rm -rf /var/lib/apt/lists/*
# РОБОЧА КАТАЛОГІЯ
#
WORKDIR /tmp
# Завантажити та встановити ImageMagick 7
RUN cd /tmp && wget https://imagemagick.org/download/ImageMagick.tar.gz && \
tar xvzf ImageMagick.tar.gz && \
cd ImageMagick-* && \
./configure && \
make && \
make install && \
ldconfig /usr/local/lib && \
cd ..
&& \
rm -rf ImageMagick* && \
magick --version
## OXIPNG - ОПТИМІЗАЦІЯ PNG ФАЙЛІВ (ARM64)
# https://github.com/shssoichiro/oxipng/releases/
RUN wget https://github.com/shssoichiro/oxipng/releases/download/v9.1.3/oxipng_9.1.3-1_arm64.deb
RUN dpkg -i oxipng_9.1.3-1_arm64.deb
SHELL ["/bin/bash", "-c"]
## ВСТАНОВЛЕННЯ NODEJS, PNPM І YARN
#
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
RUN source /root/.nvm/nvm.sh && nvm install lts/hydrogen --default
# RUN source /root/.nvm/nvm.sh && \
# corepack enable pnpm && \
# corepack use pnpm@9
RUN source /root/.nvm/nvm.sh && \
npm install -g yarn
## РОБОЧА КАТАЛОГІЯ
#
WORKDIR /app
## ВСТАНОВЛЕННЯ ЗАЛЕЖНОСТЕЙ RUBY ON RAILS
#
RUN gem install bundler -v 2.5.9
COPY ${PROJECT_PATH}/Gemfile /app/Gemfile
COPY ${PROJECT_PATH}/Gemfile.lock /app/Gemfile.lock
RUN bundle install --frozen
## ВСТАНОВЛЕННЯ ЗАЛЕЖНОСТЕЙ NODEJS
#
RUN source /root/.nvm/nvm.sh && npm install -g svgo
COPY ${PROJECT_PATH}/package.json /app/package.json
COPY ${PROJECT_PATH}/patches /app/patches
RUN source /root/.nvm/nvm.sh && yarn -v
Крок 4. Налаштування бази даних
export SKIP_MULTISITE=1
congif/database.yml
development:
adapter: postgresql
database: discourse_development
username: postgres
password: password
host: postgres
port: 5432
pool: 5
test:
adapter: postgresql
database: discourse_test
username: postgres
password: password
host: postgres
port: 5432
pool: 5
$ yarn install
$ SKIP_MULTISITE=1 bundle exec rake db:create db:migrate
Крок 5. Створення адміністратора
В контейнері на localhost
$ bin/rails admin:create
Email: [email protected]
Password:
Repeat password:
Ensuring account is active!
Account created successfully with username `newforum`
Do you want to grant Admin privileges to this account? (Y/n) Y
Your account now has Admin privileges!
Крок 6. Запуск проєкту
export DISCOURSE_HOSTNAME=localhost
export DISCOURSE_PORT=4200
export SKIP_MULTISITE=1
bin/ember-cli -u
Крок 7. Налаштування DiscourseConnect (SSO)
http://localhost:4200/admin/site_settings/category/login
enable_discourse_connect
: повинен бути увімкнений, глобальний перемикач
discourse_connect_url
: зовнішня URL-адреса, на яку користувачів буде перенаправлено під час спроби увійти
discourse_connect_secret
: секретний рядок, який використовується для хешування SSO навантажень. Забезпечує автентичність навантажень.
Мій сервер для входу запущений на localhost:3002
enable discourse connect: true
discourse connect allowed redirect domains: http://localhost:3002
discourse connect url: http://localhost:3002/connect/sso
discourse connect secret: MySecretKey
Крок 8. Кнопка входу тепер веде на http://localhost:3002/connect/sso
http://localhost:3002/connect/sso?sso=PAYLOAD&sig=SIG
class SsoController < ActionController::Base
def sso
render json: params
end
end
Rails.application.routes.draw do
get '/connect/sso', to: 'sso#sso', as: 'sso'
end
Давайте розглянемо запит до сервера входу
Крок 9.
SSO контролер на вашій стороні
Давайте реалізуємо SSO контролер
require 'base64'
require 'openssl'
class SsoController < ActionController::Base
# Має бути рівним тому, що ви зберегли в налаштуваннях Discourse
DISCOURSE_SECRET = "MySecretKey"
before_action :store_user_location!, if: :storable_location?
before_action :authenticate_user!
def sso
# Отримуємо параметри з запиту
sso = params[:sso]
sig = params[:sig]
# Перевіряємо підпис
unless valid_signature?(sso, sig)
render plain: 'Невірний підпис', status: :unauthorized
return
end
# Декодуємо навантаження SSO
sso_params = decode_sso_payload(sso)
# Формуємо навантаження для відправки назад до Discourse
response_payload = {
nonce: sso_params['nonce'],
email: current_user.email,
external_id: current_user.id.to_s,
username: current_user.username
}
# Генеруємо відповідь
encoded_response, response_sig = generate_response(sso_params, response_payload)
# http://postgres:4200/session/sso_login?sso=PAYLOAD=&sig=SINGNATURE
# Перенаправляємо назад до Discourse
# МОЖЕ ПРИПАДАТИ ДОПОМІНІТЬ ДОДАТКОВІ НАЛАШТУВАННЯ
redirect_to "#{sso_params['return_sso_url']}?sso=#{encoded_response}&sig=#{response_sig}"
end
private
# Перевіряє підпис за допомогою секретного ключа Discourse
def valid_signature?(sso, sig)
computed_sig = OpenSSL::HMAC.hexdigest('sha256', DISCOURSE_SECRET, sso)
computed_sig == sig
end
# Декодує Base64-encoded навантаження SSO
def decode_sso_payload(sso)
decoded_sso = Base64.decode64(sso)
Rack::Utils.parse_nested_query(decoded_sso)
end
# Генерує відповідь і її підпис
def generate_response(sso_params, response_payload)
raw_response = URI.encode_www_form(response_payload)
encoded_response = Base64.strict_encode64(raw_response)
response_sig = OpenSSL::HMAC.hexdigest('sha256', DISCOURSE_SECRET, encoded_response)
[encoded_response, response_sig]
end
def storable_location?
request.get? && is_navigational_format? && !devise_controller? && !request.xhr?
end
def store_user_location!
session[:return_to] = request.original_url
end
end
SiteSetting.port = 4200
SiteSetting.forcehostname = “localhost”
Discourse.baseurl => “http://localhost:4200"
Крок 10. Увійдіть і побачте свій новий акаунт
Висновок
Тепер ви знаєте, як налаштувати SSO для Discourse, якщо ваш сервер для входу є застосунком на основі Rails.
Щасливого кодування!
Слідкуйте за мною на github: https://github.com/the-teacher
Перекладено з: Discourse. SSO in 10 steps (Docker based)