add new environment variable for specififying the signing algorithm

This commit is contained in:
Carter Mintey 2024-03-22 01:32:33 +00:00
parent 1c6c5042ae
commit ff5131018b
5 changed files with 26 additions and 8 deletions

View File

@ -46,6 +46,14 @@ Before you can start using OIDC Authentication, you must first configure a new c
Take the client id and your discovery URL and update your environment variables to include the required OIDC variables described in [Installation - Backend Configuration](../installation/backend-config.md#openid-connect-oidc).
### Groups
There are two (optional) [environment variables](../installation/backend-config.md#openid-connect-oidc) that can control which of the users in your IdP can log in to Mealie and what permissions they will have. The groups should be **defined in your IdP** and be returned in the `groups` claim.
`OIDC_USER_GROUP`: Users must be a part of this group (within your IdP) to be able to log in.
`OIDC_ADMIN_GROUP`: Users that are in this group (within your IdP) will be made an **admin** in Mealie.
## Examples
Example configurations for several Identity Providers have been provided by the Community in the [GitHub Discussions](https://github.com/mealie-recipes/mealie/discussions/categories/oauth-provider-example).

View File

@ -85,11 +85,12 @@ For usage, see [Usage - OpenID Connect](../authentication/oidc.md)
| OIDC_SIGNUP_ENABLED | True | Enables new users to be created when signing in for the first time with OIDC |
| OIDC_CONFIGURATION_URL | None | The URL to the OIDC configuration of your provider. This is usually something like https://auth.example.com/.well-known/openid-configuration |
| OIDC_CLIENT_ID | None | The client id of your configured client in your provider |
| OIDC_USER_GROUP| None | If specified, only users belonging to this group will be able to successfully authenticate, regardless of the OIDC_ADMIN_GROUP |
| OIDC_ADMIN_GROUP | None | If specified, users belonging to this group will be made an admin |
| OIDC_USER_GROUP| None | If specified, only users belonging to this group will be able to successfully authenticate, regardless of the `OIDC_ADMIN_GROUP`. For more information see [this page](../authentication/oidc.md#groups) |
| OIDC_ADMIN_GROUP | None | If specified, users belonging to this group will be made an admin. For more information see [this page](../authentication/oidc.md#groups) |
| OIDC_AUTO_REDIRECT | False | If `True`, then the login page will be bypassed an you will be sent directly to your Identity Provider. You can still get to the login page by adding `?direct=1` to the login URL |
| OIDC_PROVIDER_NAME | OAuth | The provider name is shown in SSO login button. "Login with <OIDC_PROVIDER_NAME\>" |
| OIDC_REMEMBER_ME | False | Because redirects bypass the login screen, you cant extend your session by clicking the "Remember Me" checkbox. By setting this value to true, a session will be extended as if "Remember Me" was checked |
| OIDC_SIGNING_ALGORITHM | RS256 | The algorithm used to sign the id token (examples: RS256, HS256) |
### Themeing

File diff suppressed because one or more lines are too long

View File

@ -3,13 +3,14 @@ from functools import lru_cache
import requests
from authlib.jose import JsonWebKey, JsonWebToken, JWTClaims, KeySet
from authlib.jose.errors import ExpiredTokenError
from authlib.jose.errors import ExpiredTokenError, UnsupportedAlgorithmError
from authlib.oidc.core import CodeIDToken
from sqlalchemy.orm.session import Session
from mealie.core import root_logger
from mealie.core.config import get_app_settings
from mealie.core.security.providers.auth_provider import AuthProvider
from mealie.core.settings.settings import AppSettings
from mealie.db.models.users.users import AuthMethod
from mealie.repos.all_repositories import get_repositories
from mealie.schema.user.auth import OIDCRequest
@ -26,11 +27,11 @@ class OpenIDProvider(AuthProvider[OIDCRequest]):
async def authenticate(self) -> tuple[str, timedelta] | None:
"""Attempt to authenticate a user given a username and password"""
claims = self.get_claims()
settings = get_app_settings()
claims = self.get_claims(settings)
if not claims:
return None
settings = get_app_settings()
repos = get_repositories(self.session)
user = self.try_get_user(claims.get("email"))
@ -76,13 +77,20 @@ class OpenIDProvider(AuthProvider[OIDCRequest]):
self._logger.info("[OIDC] Found user but their AuthMethod does not match OIDC")
return None
def get_claims(self) -> JWTClaims | None:
def get_claims(self, settings: AppSettings) -> JWTClaims | None:
"""Get the claims from the ID token and check if the required claims are present"""
required_claims = {"preferred_username", "name", "email"}
jwks = OpenIDProvider.get_jwks()
if not jwks:
return None
claims = JsonWebToken(["RS256"]).decode(s=self.data.id_token, key=jwks, claims_cls=CodeIDToken)
algorithm = settings.OIDC_SIGNING_ALGORITHM
try:
claims = JsonWebToken([algorithm]).decode(s=self.data.id_token, key=jwks, claims_cls=CodeIDToken)
except UnsupportedAlgorithmError as e:
self._logger.error(
f"[OIDC] Unsupported algorithm '{algorithm}'. Unable to decode id token due to mismatched algorithm."
)
try:
claims.validate()

View File

@ -182,6 +182,7 @@ class AppSettings(BaseSettings):
OIDC_AUTO_REDIRECT: bool = False
OIDC_PROVIDER_NAME: str = "OAuth"
OIDC_REMEMBER_ME: bool = False
OIDC_SIGNING_ALGORITHM: str = "RS256"
@property
def OIDC_READY(self) -> bool: