Enables OIDC/OAuth2 login for Grocy using the authorization code flow with PKCE.
- PHP 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| LICENSE | ||
| OidcAuthMiddleware.php | ||
| README.md | ||
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
- Copy the
OidcAuthMiddleware.phpto the Grocy root atmiddleware/OidcAuthMiddleware.php - Configure a OAuth app in your OAuth provider
- Add the following settings to your
config.phpand 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_IDOAUTH_CLIENT_SECRET(orOAUTH_CLIENT_SECRET_FILE)OAUTH_ISSUER
with the client configured to allow PKCE.
Defaults and fallbacks
OAUTH_SCOPESfalls back toopenid profileif not set.OAUTH_CLIENT_SECRET_FILEis used whenOAUTH_CLIENT_SECRETis empty.OAUTH_USERNAME_CLAIMfalls back topreferred_usernameand then triesusername,nickname,email,sub.OAUTH_FIRST_NAME_CLAIMfalls back togiven_name.OAUTH_LAST_NAME_CLAIMfalls back tofamily_name.OAUTH_PICTURE_CLAIMfalls back topicture.OAUTH_PICTURE_MAX_BYTESfalls back to2097152(2 MiB).OAUTH_PROMPTis always sent asprompton the authorization request and falls back toselect_accountif not set.
OIDC discovery behavior
- If any of
OAUTH_AUTH_URL,OAUTH_TOKEN_URL, orOAUTH_USERINFO_URLis missing, the middleware fetches{issuer}/.well-known/openid-configurationfromOAUTH_ISSUER. - If explicit endpoint settings are provided, they take precedence over discovered values.
- For issuer-only configuration, set
OAUTH_ISSUERand leave endpoint settings empty.
IdP authorization controls
- Use
OAUTH_PROMPTto influence the IdP login behavior (login,consent,select_account, ornone, depending on your provider). - To prevent silent SSO re-login, keep
OAUTH_PROMPTatselect_account(recommended default).
Supported
- OAuth2 authorization code flow.
- PKCE (
S256) with server-side verifier handling. - PKCE provider capability verification via discovery (
code_challenge_methods_supportedmust includeS256). - OIDC discovery (
/.well-known/openid-configuration) for auth/token/userinfo endpoints. - OIDC ID token validation (
RS256signature,iss,aud,exp,nonce, andsubmatch 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-
RS256ID 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/loginas callback when using this middleware class. - If
OAUTH_REDIRECT_URIis omitted, the middleware auto-generates it from the external request URI (including reverse proxy headers likeForwarded,X-Forwarded-Proto,X-Forwarded-Host,X-Forwarded-Port) without query string.
PKCE notes
- PKCE (
S256) is enabled by default. - With PKCE enabled,
OAUTH_ISSUERis required so provider support can be verified from discovery metadata. - For confidential clients, keep
OAUTH_CLIENT_SECRETset; 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_nameandlast_nameare 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
userpicturesstorage; unsupported mime types or failed downloads are ignored.