Skip to content

Commit

Permalink
Merge pull request #1689 from pbiering/auth-oauth2
Browse files Browse the repository at this point in the history
migrate oauth2 into upstream
  • Loading branch information
pbiering authored Feb 2, 2025
2 parents 780aaa7 + 6f68a64 commit c2def71
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 3.4.2.dev

* Add: option [auth] type oauth2 by code migration from https://gitlab.mim-libre.fr/alphabet/radicale_oauth/-/blob/dev/oauth2/

## 3.4.1
* Add: option [auth] dovecot_connection_type / dovecot_host / dovecot_port
* Add: option [auth] type imap by code migration from https://github.com/Unrud/RadicaleIMAP/
Expand Down
11 changes: 10 additions & 1 deletion DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,10 @@ Available backends:
: Use a Dovecot server to authenticate users.

`imap`
: Use a IMAP server to authenticate users.
: Use an IMAP server to authenticate users.

`oauth2`
: Use an OAuth2 server to authenticate users.

Default: `none`

Expand Down Expand Up @@ -1019,6 +1022,12 @@ Secure the IMAP connection: tls | starttls | none

Default: `tls`

##### oauth2_token_endpoint

OAuth2 token endpoint URL

Default:

##### lc_username

Сonvert username to lowercase, must be true for case-insensitive auth
Expand Down
3 changes: 3 additions & 0 deletions config
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@
# Value: tls | starttls | none
#imap_security = tls

# OAuth2 token endpoint URL
#oauth2_token_endpoint = <URL>

# Htpasswd filename
#htpasswd_filename = /etc/radicale/users

Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "Radicale"
# When the version is updated, a new section in the CHANGELOG.md file must be
# added too.
readme = "README.md"
version = "3.4.1"
version = "3.4.2.dev"
authors = [{name = "Guillaume Ayoub", email = "[email protected]"}, {name = "Unrud", email = "[email protected]"}, {name = "Peter Bieringer", email = "[email protected]"}]
license = {text = "GNU GPL v3"}
description = "CalDAV and CardDAV Server"
Expand Down Expand Up @@ -72,7 +72,7 @@ skip_install = true

[tool.tox.env.mypy]
deps = ["mypy==1.11.0"]
commands = [["mypy", "."]]
commands = [["mypy", "--install-types", "--non-interactive", "."]]
skip_install = true


Expand Down
2 changes: 2 additions & 0 deletions radicale/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@
"htpasswd",
"ldap",
"imap",
"oauth2",
"dovecot")

CACHE_LOGIN_TYPES: Sequence[str] = (
"dovecot",
"ldap",
"htpasswd",
"imap",
"oauth2",
)

AUTH_SOCKET_FAMILY: Sequence[str] = ("AF_UNIX", "AF_INET", "AF_INET6")
Expand Down
66 changes: 66 additions & 0 deletions radicale/auth/oauth2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# This file is part of Radicale Server - Calendar Server
#
# Original from https://gitlab.mim-libre.fr/alphabet/radicale_oauth/
# Copyright © 2021-2022 Bruno Boiget
# Copyright © 2022-2022 Daniel Dehennin
#
# Since migration into upstream
# Copyright © 2025-2025 Peter Bieringer <[email protected]>
#
# This library is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.

"""
Authentication backend that checks credentials against an oauth2 server auth endpoint
"""

import requests

from radicale import auth
from radicale.log import logger


class Auth(auth.BaseAuth):
def __init__(self, configuration):
super().__init__(configuration)
self._endpoint = configuration.get("auth", "oauth2_token_endpoint")
if not self._endpoint:
logger.error("auth.oauth2_token_endpoint URL missing")
raise RuntimeError("OAuth2 token endpoint URL is required")
logger.info("auth OAuth2 token endpoint: %s" % (self._endpoint))

def _login(self, login, password):
"""Validate credentials.
Sends login credentials to oauth token endpoint and checks that a token is returned
"""
try:
# authenticate to authentication endpoint and return login if ok, else ""
req_params = {
"username": login,
"password": password,
"grant_type": "password",
"client_id": "radicale",
}
req_headers = {"Content-Type": "application/x-www-form-urlencoded"}
response = requests.post(
self._endpoint, data=req_params, headers=req_headers
)
if (
response.status_code == requests.codes.ok
and "access_token" in response.json()
):
return login
except OSError as e:
logger.critical("Failed to authenticate against OAuth2 server %s: %s" % (self._endpoint, e))
logger.warning("User failed to authenticate using OAuth2: %r" % login)
return ""
4 changes: 4 additions & 0 deletions radicale/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,10 @@ def json_str(value: Any) -> dict:
"value": "tls",
"help": "Secure the IMAP connection: *tls*|starttls|none",
"type": imap_security}),
("oauth2_token_endpoint", {
"value": "",
"help": "OAuth2 token endpoint URL",
"type": str}),
("strip_domain", {
"value": "False",
"help": "strip domain from username",
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg.legacy
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ skip_install = True

[testenv:mypy]
deps = mypy==1.11.0
commands = mypy .
commands = mypy --install-types --non-interactive .
skip_install = True

[tool:isort]
Expand Down
2 changes: 1 addition & 1 deletion setup.py.legacy
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ from setuptools import find_packages, setup

# When the version is updated, a new section in the CHANGELOG.md file must be
# added too.
VERSION = "3.4.1"
VERSION = "3.4.2.dev"

with open("README.md", encoding="utf-8") as f:
long_description = f.read()
Expand Down

0 comments on commit c2def71

Please sign in to comment.