Watch
1
0
Fork
You've already forked grocy-oidc
0
Enables OIDC/OAuth2 login for Grocy using the authorization code flow with PKCE.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-29 16:35:13 +02:00
LICENSE Initial commit 2026-07-29 16:35:13 +02:00
OidcAuthMiddleware.php Initial commit 2026-07-29 16:35:13 +02:00
README.md Initial commit 2026-07-29 16:35:13 +02:00

Grocy OIDC Middleware

This OidcAuthMiddleware enables OIDC/OAuth2 login for Grocy using the authorization code flow with PKCE. This middleware integrates with a Grocy instance.

Note: This is not an official part of Grocy. Please report issues here and NOT in the Grocy repo.

Disclaimer: The middleware implementation was mainly created by GitHub Copilot (GPT-5.3-Codex).

This was tested against Pocket ID and should work with OAuth2/OIDC providers that support the authorization code flow.

OIDC auto-discovery is supported via issuer metadata.

Installation & Configuration

  1. Copy the OidcAuthMiddleware.php to the Grocy root at middleware/OidcAuthMiddleware.php
  2. Configure a OAuth app in your OAuth provider
  3. Add the following settings to your config.php and adapt to your setup:
Setting('AUTH_CLASS', 'Grocy\Middleware\OidcAuthMiddleware');

// Options when using OidcAuthMiddleware
Setting('OAUTH_CLIENT_ID', '');
Setting('OAUTH_CLIENT_SECRET', '');
Setting('OAUTH_CLIENT_SECRET_FILE', ''); // Optional alternative to OAUTH_CLIENT_SECRET
Setting('OAUTH_ISSUER', 'https://id.example.com');

// Optional explicit endpoint overrides (when omitted they are auto-discovered from OAUTH_ISSUER)
Setting('OAUTH_AUTH_URL', '');
Setting('OAUTH_TOKEN_URL', '');
Setting('OAUTH_USERINFO_URL', '');
Setting('OAUTH_REDIRECT_URI', 'https://grocy.example.com/stockoverview');
Setting('OAUTH_PKCE_ENABLED', true);
Setting('OAUTH_PROMPT', 'select_account');
Setting('OAUTH_SCOPES', 'openid profile');
Setting('OAUTH_USERNAME_CLAIM', 'preferred_username');
Setting('OAUTH_FIRST_NAME_CLAIM', 'given_name');
Setting('OAUTH_LAST_NAME_CLAIM', 'family_name');
Setting('OAUTH_PICTURE_CLAIM', 'picture');
Setting('OAUTH_PICTURE_MAX_BYTES', 2097152);

With Pocket ID, a minimal setup is typically:

  • OAUTH_CLIENT_ID
  • OAUTH_CLIENT_SECRET (or OAUTH_CLIENT_SECRET_FILE)
  • OAUTH_ISSUER

with the client configured to allow PKCE.

Defaults and fallbacks

  • OAUTH_SCOPES falls back to openid profile if not set.
  • OAUTH_CLIENT_SECRET_FILE is used when OAUTH_CLIENT_SECRET is empty.
  • OAUTH_USERNAME_CLAIM falls back to preferred_username and then tries username, nickname, email, sub.
  • OAUTH_FIRST_NAME_CLAIM falls back to given_name.
  • OAUTH_LAST_NAME_CLAIM falls back to family_name.
  • OAUTH_PICTURE_CLAIM falls back to picture.
  • OAUTH_PICTURE_MAX_BYTES falls back to 2097152 (2 MiB).
  • OAUTH_PROMPT is always sent as prompt on the authorization request and falls back to select_account if not set.

OIDC discovery behavior

  • If any of OAUTH_AUTH_URL, OAUTH_TOKEN_URL, or OAUTH_USERINFO_URL is missing, the middleware fetches {issuer}/.well-known/openid-configuration from OAUTH_ISSUER.
  • If explicit endpoint settings are provided, they take precedence over discovered values.
  • For issuer-only configuration, set OAUTH_ISSUER and leave endpoint settings empty.

IdP authorization controls

  • Use OAUTH_PROMPT to influence the IdP login behavior (login, consent, select_account, or none, depending on your provider).
  • To prevent silent SSO re-login, keep OAUTH_PROMPT at select_account (recommended default).

Supported

  • OAuth2 authorization code flow.
  • PKCE (S256) with server-side verifier handling.
  • PKCE provider capability verification via discovery (code_challenge_methods_supported must include S256).
  • OIDC discovery (/.well-known/openid-configuration) for auth/token/userinfo endpoints.
  • OIDC ID token validation (RS256 signature, iss, aud, exp, nonce, and sub match with userinfo).
  • User provisioning and profile synchronization (username/name/picture claim mapping).
  • Prompt forwarding (prompt) on every authorization request.

Not supported

  • OIDC RP-initiated/back-channel/front-channel logout support.
  • Refresh-token based session renewal.
  • Complex claim transformations beyond direct claim-key mapping and username fallbacks.
  • Non-RS256 ID token algorithms.

Redirect URI guidance

  • Use one fixed redirect URI and register that exact URI in your OAuth provider.
  • For Grocy, use a protected non-root, non-login page as callback (for example /stockoverview).
  • Do not use / or /login as callback when using this middleware class.
  • If OAUTH_REDIRECT_URI is omitted, the middleware auto-generates it from the external request URI (including reverse proxy headers like Forwarded, X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port) without query string.

PKCE notes

  • PKCE (S256) is enabled by default.
  • With PKCE enabled, OAUTH_ISSUER is required so provider support can be verified from discovery metadata.
  • For confidential clients, keep OAUTH_CLIENT_SECRET set; for public clients, leave it empty and rely on PKCE.

Profile sync behavior

  • On every successful login, Grocy user profile fields are synchronized from claims.
  • User first_name and last_name are created from claims and updated on subsequent logins when claim values are present.
  • User profile pictures are downloaded from the configured picture claim URL and stored in Grocy userpictures storage; unsupported mime types or failed downloads are ignored.