Skip to content

Commit

Permalink
✨ 增加OIDC登入功能 (#2028)
Browse files Browse the repository at this point in the history
* ✨ 增加OIDC登入功能

* ✨ added init_user and use username to identify the user instead of email

* ✨ added well-known url for oidc config discovery

* 🔥 remove default values for required oidc variables

* 🎨 added response.raise_for_status()

* 🎨 format

* 🎨 add mozilla_django_oidc.middleware.SessionRefresh in condition

* ✨ 增加OIDC登入功能

* ✨ added init_user and use username to identify the user instead of email

* ✨ added well-known url for oidc config discovery

* 🔥 remove default values for required oidc variables

* 🎨 added response.raise_for_status()

* 🎨 format

* 🎨 add mozilla_django_oidc.middleware.SessionRefresh in condition

* 🎨 conditional import mozilla_django_oidc

Co-authored-by: Leo Q <LeoQuote@users.noreply.github.com>
  • Loading branch information
shing6326 and LeoQuote authored Jan 17, 2023
1 parent c0f41a4 commit 4fdf73c
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 2 deletions.
38 changes: 38 additions & 0 deletions archery/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from typing import List
from datetime import timedelta
import environ
import requests

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

Expand All @@ -17,6 +18,7 @@
DATABASE_URL=(str, "mysql://root:@127.0.0.1:3306/archery"),
CACHE_URL=(str, "redis://127.0.0.1:6379/0"),
ENABLE_LDAP=(bool, False),
ENABLE_OIDC=(bool, False),
AUTH_LDAP_ALWAYS_UPDATE_USER=(bool, True),
AUTH_LDAP_USER_ATTR_MAP=(
dict,
Expand Down Expand Up @@ -228,6 +230,37 @@
"AUTH_HEADER_TYPES": ("Bearer",),
}

# OIDC
ENABLE_OIDC = env("ENABLE_OIDC", False)
if ENABLE_OIDC:

INSTALLED_APPS += ("mozilla_django_oidc",)
MIDDLEWARE += ("mozilla_django_oidc.middleware.SessionRefresh",)
AUTHENTICATION_BACKENDS = (
"oidc.auth.OIDCAuthenticationBackend",
"django.contrib.auth.backends.ModelBackend",
)

OIDC_RP_WELLKNOWN_URL = env(
"OIDC_RP_WELLKNOWN_URL"
) # 例如 https://keycloak.example.com/realms/<your realm>/.well-known/openid-configuration
OIDC_RP_CLIENT_ID = env("OIDC_RP_CLIENT_ID")
OIDC_RP_CLIENT_SECRET = env("OIDC_RP_CLIENT_SECRET")

response = requests.get(OIDC_RP_WELLKNOWN_URL)
response.raise_for_status()
config = response.json()
OIDC_OP_AUTHORIZATION_ENDPOINT = config["authorization_endpoint"]
OIDC_OP_TOKEN_ENDPOINT = config["token_endpoint"]
OIDC_OP_USER_ENDPOINT = config["userinfo_endpoint"]
OIDC_OP_JWKS_ENDPOINT = config["jwks_uri"]
OIDC_OP_LOGOUT_ENDPOINT = config["end_session_endpoint"]

OIDC_RP_SCOPES = env("OIDC_RP_SCOPES", default="openid profile email")
OIDC_RP_SIGN_ALGO = env("OIDC_RP_SIGN_ALGO", default="RS256")

LOGIN_REDIRECT_URL = "/"

# LDAP
ENABLE_LDAP = env("ENABLE_LDAP", False)
if ENABLE_LDAP:
Expand Down Expand Up @@ -308,6 +341,11 @@
"level": "WARNING",
"propagate": False,
},
"mozilla_django_oidc": {
"handlers": ["console", "default"],
"level": "WARNING",
"propagate": False,
},
# 'django.db': { # 打印SQL语句,方便开发
# 'handlers': ['console', 'default'],
# 'level': 'DEBUG',
Expand Down
1 change: 1 addition & 0 deletions archery/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include(("sql_api.urls", "sql_api"), namespace="sql_api")),
path("oidc/", include("mozilla_django_oidc.urls")),
path("", include(("sql.urls", "sql"), namespace="sql")),
]

Expand Down
11 changes: 10 additions & 1 deletion common/middleware/check_login_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@
from django.http import HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin

IGNORE_URL = ["/login/", "/login/2fa/", "/authenticate/", "/signup/", "/api/info"]
IGNORE_URL = [
"/login/",
"/login/2fa/",
"/authenticate/",
"/signup/",
"/api/info",
"/oidc/callback/",
"/oidc/authenticate/",
"/oidc/logout/",
]

IGNORE_URL_RE = r"/api/(v1|auth)/\w+"

Expand Down
5 changes: 5 additions & 0 deletions common/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
<a href="#" data-toggle="modal" data-target="#sign-up">注册用户</a>
</div>
{% endif %}
{% if oidc_enabled %}
<div class="form-group">
<a href="/oidc/authenticate/">以OIDC登录</a>
</div>
{% endif %}
</form>
</div>
</div>
Expand Down
31 changes: 31 additions & 0 deletions oidc/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from mozilla_django_oidc import auth
from django.core.exceptions import SuspiciousOperation
from common.auth import init_user


class OIDCAuthenticationBackend(auth.OIDCAuthenticationBackend):
def create_user(self, claims):
"""Return object for a newly created user account."""
email = claims.get("email")
username = claims.get("preferred_username")
display = claims.get("name")
if not email or not username or not display:
raise SuspiciousOperation(
"email and name and preferred_username should not be empty"
)
user = self.UserModel.objects.create_user(
username, email=email, display=display
)
init_user(user)
return user

def describe_user_by_claims(self, claims):
username = claims.get("preferred_username")
return "username {}".format(username)

def filter_users_by_claims(self, claims):
"""Return all users matching the username."""
username = claims.get("preferred_username")
if not username or username == "admin":
return self.UserModel.objects.none()
return self.UserModel.objects.filter(username__iexact=username)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ qrcode==7.3.1
django-environ==0.8.1
alibabacloud_dysmsapi20170525==2.0.9
tencentcloud-sdk-python==3.0.656
mozilla-django-oidc==3.0.0
5 changes: 4 additions & 1 deletion sql/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ def login(request):
return render(
request,
"login.html",
context={"sign_up_enabled": SysConfig().get("sign_up_enabled")},
context={
"sign_up_enabled": SysConfig().get("sign_up_enabled"),
"oidc_enabled": os.getenv("ENABLE_OIDC"),
},
)


Expand Down

0 comments on commit 4fdf73c

Please sign in to comment.