Migrate to AutoSecretKey
Implement OIDC login
This commit is contained in:
parent
ac18f31d9a
commit
2ff91abe82
8 changed files with 171 additions and 69 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,4 +3,5 @@ __pycache__/
|
||||||
db.sqlite3
|
db.sqlite3
|
||||||
migrations/
|
migrations/
|
||||||
venv/
|
venv/
|
||||||
localsettings.py
|
localsettings.py
|
||||||
|
settings.ini
|
13
common/templatetags/oidc.py
Normal file
13
common/templatetags/oidc.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from django import template
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def use_oidc():
|
||||||
|
return settings.USE_OIDC
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def oidc_provider():
|
||||||
|
return settings.OIDC_PROVIDER_NAME
|
|
@ -1,4 +1,5 @@
|
||||||
{% extends "registration/base.html" %}
|
{% extends "registration/base.html" %}
|
||||||
|
{% load oidc %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="p-5">
|
<div class="p-5">
|
||||||
|
@ -19,7 +20,13 @@
|
||||||
<button type="submit" class="btn btn-primary btn-user btn-block">
|
<button type="submit" class="btn btn-primary btn-user btn-block">
|
||||||
Login
|
Login
|
||||||
</button>
|
</button>
|
||||||
<hr>
|
{% use_oidc as use_oidc %}
|
||||||
|
{% if use_oidc %}
|
||||||
|
<div style="text-align: center;">or</div>
|
||||||
|
<a href="{% url 'oidc_authentication_init' %}" class="btn btn-success btn-user btn-block">
|
||||||
|
Login via {% oidc_provider %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
|
|
|
@ -1,19 +1,28 @@
|
||||||
# You shouldn't have to change anything in here, ever.
|
# You shouldn't have to change anything in here, ever.
|
||||||
# Use localsettings.py in the project's root directory instead.
|
# Use settings.ini in the project's root directory instead.
|
||||||
|
|
||||||
# If you make any changes in here, you may have trouble updating your Kumify installation.
|
# If you make any changes in here, you may have trouble updating your Kumify installation.
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from localsettings import *
|
from autosecretkey import AutoSecretKey
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
CONFIG_FILE = AutoSecretKey(BASE_DIR / "settings.ini")
|
||||||
|
|
||||||
|
SECRET_KEY = CONFIG_FILE.secret_key
|
||||||
|
DEBUG = CONFIG_FILE.config.getboolean("KUMIFY", "Debug", fallback=False)
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = [CONFIG_FILE.config.get("KUMIFY", "Host")]
|
||||||
|
CSRF_TRUSTED_ORIGINS = [f"https://{ALLOWED_HOSTS[0]}"]
|
||||||
|
|
||||||
|
TIME_ZONE = CONFIG_FILE.config.get("KUMIFY", "TimeZone", fallback="UTC")
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ENABLED_MODULES
|
ENABLED_MODULES # TODO: Move this to settings.ini
|
||||||
except NameError:
|
except NameError:
|
||||||
ENABLED_MODULES = [
|
ENABLED_MODULES = [
|
||||||
'cbt',
|
'cbt',
|
||||||
|
@ -42,6 +51,7 @@ INSTALLED_APPS = [
|
||||||
'colorfield',
|
'colorfield',
|
||||||
'multiselectfield',
|
'multiselectfield',
|
||||||
'dbsettings',
|
'dbsettings',
|
||||||
|
'mozilla_django_oidc',
|
||||||
] + CORE_MODULES + ENABLED_MODULES
|
] + CORE_MODULES + ENABLED_MODULES
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -76,30 +86,40 @@ WSGI_APPLICATION = 'kumify.wsgi.application'
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
|
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
|
||||||
|
|
||||||
DATABASES = {
|
if "MySQL" in CONFIG_FILE.config:
|
||||||
'default': {
|
DATABASES = {
|
||||||
'ENGINE': 'django.contrib.gis.db.backends.spatialite',
|
'default': {
|
||||||
'NAME': BASE_DIR / 'db.sqlite3',
|
'ENGINE': 'django.contrib.gis.db.backends.mysql',
|
||||||
} if not DB_HOST else {
|
'NAME': CONFIG_FILE.config.get("MySQL", "Database"),
|
||||||
'ENGINE': 'django.contrib.gis.db.backends.mysql',
|
'USER': CONFIG_FILE.config.get("MySQL", "Username"),
|
||||||
'NAME': DB_NAME,
|
'PASSWORD': CONFIG_FILE.config.get("MySQL", "Password"),
|
||||||
'USER': DB_USER,
|
'HOST': CONFIG_FILE.config.get("MySQL", "Host", fallback="localhost"),
|
||||||
'PASSWORD': DB_PASS,
|
'PORT': CONFIG_FILE.config.getint("MySQL", "Port", fallback=3306),
|
||||||
'HOST': DB_HOST,
|
'OPTIONS': {
|
||||||
'PORT': DB_PORT,
|
'charset': 'utf8mb4',
|
||||||
'OPTIONS': {
|
'sql_mode': 'traditional',
|
||||||
'charset': 'utf8mb4',
|
}
|
||||||
'sql_mode': 'traditional',
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else:
|
||||||
|
DATABASES = {
|
||||||
|
'default': {
|
||||||
|
'ENGINE': 'django.contrib.gis.db.backends.spatialite',
|
||||||
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS = [
|
||||||
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
|
]
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
@ -135,15 +155,48 @@ USE_TZ = True
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/3.1/howto/static-files/
|
# https://docs.djangoproject.com/en/4.0/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
STATIC_ROOT = None if DEBUG else STATIC_ROOT
|
STATIC_ROOT = None if DEBUG else CONFIG_FILE.config.get("KUMIFY", "StaticRoot", fallback=BASE_DIR / "static")
|
||||||
|
|
||||||
LOGIN_REDIRECT_URL = '/'
|
LOGIN_REDIRECT_URL = '/'
|
||||||
LOGOUT_REDIRECT_URL = "/"
|
LOGOUT_REDIRECT_URL = "/"
|
||||||
|
|
||||||
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' if not AWS_ACCESS_KEY_ID else 'storages.backends.s3boto3.S3Boto3Storage'
|
if "S3" in CONFIG_FILE.config:
|
||||||
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage' if AWS_ACCESS_KEY_ID else 'django.contrib.staticfiles.storage.StaticFilesStorage'
|
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
|
||||||
|
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'
|
||||||
|
AWS_ACCESS_KEY_ID = CONFIG_FILE.config.get("S3", "AccessKey")
|
||||||
|
AWS_SECRET_ACCESS_KEY = CONFIG_FILE.config.get("S3", "SecretKey")
|
||||||
|
AWS_STORAGE_BUCKET_NAME = CONFIG_FILE.config.get("S3", "Bucket")
|
||||||
|
AWS_S3_ENDPOINT_URL = CONFIG_FILE.config.get("S3", "Endpoint")
|
||||||
|
|
||||||
|
|
||||||
|
# OpenID Connect
|
||||||
|
# https://mozilla-django-oidc.readthedocs.io/
|
||||||
|
|
||||||
|
USE_OIDC = False
|
||||||
|
|
||||||
|
if "OIDC" in CONFIG_FILE.config:
|
||||||
|
USE_OIDC = True
|
||||||
|
|
||||||
|
OIDC_PROVIDER_NAME = CONFIG_FILE.config.get("OIDC", "ProviderName", fallback="OpenID Connect")
|
||||||
|
|
||||||
|
AUTHENTICATION_BACKENDS.append('mozilla_django_oidc.auth.OIDCAuthenticationBackend')
|
||||||
|
|
||||||
|
OIDC_RP_CLIENT_ID = CONFIG_FILE.config.get("OIDC", "ClientID")
|
||||||
|
OIDC_RP_CLIENT_SECRET = CONFIG_FILE.config.get("OIDC", "ClientSecret")
|
||||||
|
|
||||||
|
if (opsk := CONFIG_FILE.config.get("OIDC", "OPSignKey", fallback="")):
|
||||||
|
OIDC_RP_SIGN_ALGO = "RS256"
|
||||||
|
OIDC_RP_IDP_SIGN_KEY = opsk
|
||||||
|
elif (jwks := CONFIG_FILE.config.get("OIDC", "JWKSEndpoint", fallback="")):
|
||||||
|
OIDC_RP_SIGN_ALGO = "RS256"
|
||||||
|
OIDC_OP_JWKS_ENDPOINT = jwks
|
||||||
|
|
||||||
|
OIDC_OP_AUTHORIZATION_ENDPOINT = CONFIG_FILE.config.get("OIDC", "AuthorizationEndpoint")
|
||||||
|
OIDC_OP_TOKEN_ENDPOINT = CONFIG_FILE.config.get("OIDC", "TokenEndpoint")
|
||||||
|
OIDC_OP_USER_ENDPOINT = CONFIG_FILE.config.get("OIDC", "UserInfoEndpoint")
|
|
@ -26,5 +26,6 @@ urlpatterns = [
|
||||||
path('cron/', include("cronhandler.urls", "cron")),
|
path('cron/', include("cronhandler.urls", "cron")),
|
||||||
path('webhooks/telegram/', TelegramWebhookView.as_view()),
|
path('webhooks/telegram/', TelegramWebhookView.as_view()),
|
||||||
path('dreams/', include("dreams.urls", "dreams")),
|
path('dreams/', include("dreams.urls", "dreams")),
|
||||||
path('gpslog/', include("gpslog.urls"))
|
path('gpslog/', include("gpslog.urls")),
|
||||||
|
path('oidc/', include('mozilla_django_oidc.urls')),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
# The secret key must be a long random string.
|
|
||||||
# You may use the django.core.management.utils.get_random_secret_key() function to generate one, or just smash your keyboard real hard a few times.
|
|
||||||
|
|
||||||
SECRET_KEY = "longrandomstring"
|
|
||||||
|
|
||||||
# Putting the system in debug mode will give you a lot of output if an error occurs, but it potentially exposes sensitive information like passwords.
|
|
||||||
# Only set this to True if you really need to, especially if you are running a public instance.
|
|
||||||
|
|
||||||
DEBUG = False
|
|
||||||
|
|
||||||
# Specify the time zone you are in. This will affect the times displayed in the application.
|
|
||||||
|
|
||||||
TIME_ZONE = "Europe/Vienna"
|
|
||||||
|
|
||||||
# You may set this variable to a list of domain names that are allowed to be used to access your instance.
|
|
||||||
|
|
||||||
ALLOWED_HOSTS = ["*"] # Rationale: The application should be running behind a reverse proxy anyway if it's public - let that handle which hosts are allowed
|
|
||||||
|
|
||||||
# If you are using an external server to make your instance public, we need to store some static files somewhere.
|
|
||||||
# Enter the appropriate directory and make sure your webserver serves that location at /static/
|
|
||||||
|
|
||||||
STATIC_ROOT = '/var/www/html/static/'
|
|
||||||
|
|
||||||
# By default, all files, including uploads, are stored locally.
|
|
||||||
# You may use an S3 compatible storage instead in order to increase reliability and decrease disk usage.
|
|
||||||
# If AWS_ACCESS_KEY_ID is set to None, local storage will be used.
|
|
||||||
# See https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html for all options you can use here.
|
|
||||||
# (NB: Only options starting with "AWS_" are allowed here, the storage configuration will be handled automatically.)
|
|
||||||
|
|
||||||
AWS_ACCESS_KEY_ID = None
|
|
||||||
AWS_SECRET_ACCESS_KEY = None
|
|
||||||
AWS_STORAGE_BUCKET_NAME = None
|
|
||||||
AWS_S3_ENDPOINT_URL = None
|
|
||||||
|
|
||||||
# By default, this application uses a local sqlite3 database file. You can choose to use a MariaDB/MySQL database instead.
|
|
||||||
# If DB_HOST is set to None, the sqlite3 database will be used.
|
|
||||||
|
|
||||||
DB_HOST = None # Host name of the database server
|
|
||||||
DB_PORT = 3306 # Port of the database server - the default value usually works
|
|
||||||
DB_NAME = None # Name of the database to be used
|
|
||||||
DB_USER = None # User name to authenticate with
|
|
||||||
DB_PASS = None # Password to authenticate with
|
|
|
@ -18,4 +18,5 @@ bokeh
|
||||||
panel
|
panel
|
||||||
scipy
|
scipy
|
||||||
channels
|
channels
|
||||||
django-autosecretkey
|
django-autosecretkey
|
||||||
|
mozilla-django-oidc
|
68
settings.dist.ini
Normal file
68
settings.dist.ini
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
[KUMIFY]
|
||||||
|
# Putting the system in debug mode will give you a lot of output if an error occurs, but it potentially exposes sensitive information like passwords.
|
||||||
|
# Only set this to 1 (= True) if you really need to, especially if you are running a public instance.
|
||||||
|
|
||||||
|
Debug = 0
|
||||||
|
|
||||||
|
# Specify the time zone you are in. This will affect the times displayed in the application.
|
||||||
|
|
||||||
|
TimeZone = Europe/Vienna
|
||||||
|
|
||||||
|
# Set this to the domain name you are using for Kumify
|
||||||
|
|
||||||
|
Host = kumify.lan
|
||||||
|
|
||||||
|
# If you are not using S3 storage (see below), we need to store your static files somewhere locally
|
||||||
|
# Enter the appropriate directory and make sure your webserver serves that location at /static/
|
||||||
|
# If unset, the "static" subdirectory of the Kumify base directory is going to be used
|
||||||
|
|
||||||
|
StaticRoot = '/var/www/html/static/'
|
||||||
|
|
||||||
|
|
||||||
|
# By default, all files, including uploads, are stored locally.
|
||||||
|
# You may use an S3 compatible storage instead in order to increase reliability and decrease local disk usage.
|
||||||
|
# If this section is commented out, local storage will be used.
|
||||||
|
|
||||||
|
# [S3]
|
||||||
|
# AccessKey = kumify
|
||||||
|
# SecretKey = !!!verysecret!!!
|
||||||
|
# Bucket = kumify
|
||||||
|
# Endpoint = https://minio.kumify.lan
|
||||||
|
|
||||||
|
|
||||||
|
# By default, this application uses a local sqlite3 database file. You can choose to use a MariaDB/MySQL database instead.
|
||||||
|
# If this section is commented out, the local sqlite3 database is used
|
||||||
|
|
||||||
|
# [MySQL]
|
||||||
|
# Database = kumify
|
||||||
|
# Username = kumify
|
||||||
|
# Password = secret123!
|
||||||
|
# Host = localhost
|
||||||
|
# Port = 3306
|
||||||
|
|
||||||
|
|
||||||
|
# By default, Kumify uses local user authentication only
|
||||||
|
# In order to allow users to authenticate using an OpenID Connect provider, comment in this section and set the values accordingly
|
||||||
|
|
||||||
|
# [OIDC]
|
||||||
|
# Optionally, enter the name of the OIDC provider, so it can be displayed on buttons
|
||||||
|
|
||||||
|
# ProviderName = OpenID Connect
|
||||||
|
|
||||||
|
# ClientID = Your client ID
|
||||||
|
# ClientSecret = Your client secret
|
||||||
|
|
||||||
|
# To use the RS256 algorihm, set one of the following two settings
|
||||||
|
|
||||||
|
# OPSignKey = OP signing key in PEM or DER format
|
||||||
|
# JWKSEndpoint = https://kumidc.lan/openid/jwks
|
||||||
|
|
||||||
|
# These URLs need to correspond to your ID provider
|
||||||
|
|
||||||
|
# AuthorizationEndpoint = https://kumidc.lan/openid/authorize
|
||||||
|
# TokenEndpoint = https://kumidc.lan/openid/token
|
||||||
|
# UserInfoEndpoint = https://kumidc.lan/openid/userinfo
|
||||||
|
|
||||||
|
# If you want to allow users who do not yet have a Kumify account to log in using the OIDC provider, uncomment the following setting and set it to 1.
|
||||||
|
|
||||||
|
# CreateUsers = 0
|
Loading…
Reference in a new issue