mirror of
https://github.com/oddlama/nix-config.git
synced 2025-10-10 23:00:39 +02:00
feat: patch oauth2-proxy to support scopes as groups
This commit is contained in:
parent
1a0378ee5c
commit
eb9ee0bf0d
7 changed files with 65 additions and 16 deletions
|
@ -151,7 +151,7 @@ kanidm group create grafana-server-admins
|
|||
kanidm group create grafana-admins
|
||||
kanidm group create grafana-editors
|
||||
kanidm system oauth2 create grafana "Grafana" https://grafana.${personalDomain}
|
||||
kanidm system oauth2 update-scope-map grafana grafana-access openid profile email
|
||||
kanidm system oauth2 update-scope-map grafana grafana-access openid email profile
|
||||
kanidm system oauth2 update-sup-scope-map grafana grafana-server-admins server_admin
|
||||
kanidm system oauth2 update-sup-scope-map grafana grafana-admins admin
|
||||
kanidm system oauth2 update-sup-scope-map grafana grafana-editors editor
|
||||
|
@ -160,7 +160,7 @@ kanidm system oauth2 show-basic-secret grafana
|
|||
kanidm group create web-sentinel-access
|
||||
kanidm group create web-sentinel-adguardhome-access
|
||||
kanidm system oauth2 create web-sentinel "Web services" https://oauth2.${personalDomain}
|
||||
kanidm system oauth2 update-scope-map web-sentinel web-sentinel-access openid profile email
|
||||
kanidm system oauth2 update-scope-map web-sentinel web-sentinel-access openid email
|
||||
kanidm system oauth2 update-sup-scope-map web-sentinel web-sentinel-adguardhome-access access_adguardhome
|
||||
kanidm system oauth2 show-basic-secret web-sentinel
|
||||
# Add new user
|
||||
|
@ -169,6 +169,7 @@ kanidm person create myuser "My User"
|
|||
kanidm person update myuser --legalname "Full Name" --mail "myuser@example.com"
|
||||
kanidm group add-members grafana-access myuser
|
||||
kanidm group add-members grafana-server-admins myuser
|
||||
kanidm group add-members web-sentinel-access myuser
|
||||
|
||||
|
||||
```
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
enable = true;
|
||||
cookieDomain = config.repo.secrets.local.personalDomain;
|
||||
portalDomain = "oauth2.${config.repo.secrets.local.personalDomain}";
|
||||
# TODO portal redirect to dashboard (in case someone clicks on kanidm "Web services")
|
||||
};
|
||||
|
||||
age.secrets.oauth2-proxy-secret = {
|
||||
|
@ -16,24 +17,21 @@
|
|||
group = "oauth2_proxy";
|
||||
};
|
||||
|
||||
services.oauth2_proxy = {
|
||||
services.oauth2_proxy = let
|
||||
clientId = "web-sentinel";
|
||||
in {
|
||||
provider = "oidc";
|
||||
scope = "openid email";
|
||||
loginURL = "https://${config.proxiedDomains.kanidm}/ui/oauth2";
|
||||
redeemURL = "https://${config.proxiedDomains.kanidm}/oauth2/token";
|
||||
validateURL = "https://${config.proxiedDomains.kanidm}/oauth2/openid/web-sentinel/userinfo";
|
||||
clientID = "web-sentinel";
|
||||
validateURL = "https://${config.proxiedDomains.kanidm}/oauth2/openid/${clientId}/userinfo";
|
||||
clientID = clientId;
|
||||
keyFile = config.age.secrets.oauth2-proxy-secret.path;
|
||||
email.domains = ["*"];
|
||||
|
||||
extraConfig = {
|
||||
# TODO good idea? would fail when offline
|
||||
# TODO autorestart after 30 minutes, infinite times.
|
||||
oidc-issuer-url = "https://${config.proxiedDomains.kanidm}/oauth2/openid/web-sentinel";
|
||||
oidc-issuer-url = "https://${config.proxiedDomains.kanidm}/oauth2/openid/${clientId}";
|
||||
skip-provider-button = true;
|
||||
|
||||
# TODO away
|
||||
show-debug-on-error = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ in {
|
|||
forceSSL = true;
|
||||
useACMEHost = sentinelCfg.lib.extra.matchingWildcardCert adguardhomeDomain;
|
||||
oauth2.enable = true;
|
||||
oauth2.allowedGroups = ["adguardhome"];
|
||||
oauth2.allowedGroups = ["access_adguardhome"];
|
||||
locations."/" = {
|
||||
proxyPass = "http://adguardhome";
|
||||
proxyWebsockets = true;
|
||||
|
|
|
@ -99,12 +99,14 @@ in {
|
|||
|
||||
cookie.domain = ".${cfg.cookieDomain}";
|
||||
cookie.secure = true;
|
||||
cookie.httpOnly = false;
|
||||
cookie.refresh = "5m";
|
||||
# FIXME disabled because of errors. My closest guess is that this
|
||||
# reuses refresh tokens but kanidm forbids that. Not sure though.
|
||||
#cookie.refresh = "5m";
|
||||
cookie.expire = "30m";
|
||||
|
||||
reverseProxy = true;
|
||||
httpAddress = "unix:///run/oauth2_proxy/oauth2_proxy.sock";
|
||||
redirectURL = "https://${cfg.portalDomain}/oauth2/callback";
|
||||
setXauthrequest = true;
|
||||
|
||||
extraConfig = {
|
||||
|
@ -112,12 +114,10 @@ in {
|
|||
code-challenge-method = "S256";
|
||||
# Share the cookie with all subpages
|
||||
whitelist-domain = ".${cfg.cookieDomain}";
|
||||
redirect-url = "https://${cfg.portalDomain}/oauth2/callback";
|
||||
set-authorization-header = true;
|
||||
pass-access-token = true;
|
||||
skip-jwt-bearer-tokens = true;
|
||||
upstream = "static://202";
|
||||
# TODO allowed group?
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
[
|
||||
(import ./caddy.nix)
|
||||
(import ./oauth2-proxy)
|
||||
]
|
||||
|
|
44
pkgs/oauth2-proxy/0001-scopes-as-groups.patch
Normal file
44
pkgs/oauth2-proxy/0001-scopes-as-groups.patch
Normal file
|
@ -0,0 +1,44 @@
|
|||
diff --git a/providers/oidc.go b/providers/oidc.go
|
||||
index aadaf7c5..18b03a3e 100644
|
||||
--- a/providers/oidc.go
|
||||
+++ b/providers/oidc.go
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
|
||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
|
||||
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
|
||||
+ "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/requests"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
@@ -80,6 +81,31 @@ func (p *OIDCProvider) Redeem(ctx context.Context, redirectURL, code, codeVerifi
|
||||
// EnrichSession is called after Redeem to allow providers to enrich session fields
|
||||
// such as User, Email, Groups with provider specific API calls.
|
||||
func (p *OIDCProvider) EnrichSession(ctx context.Context, s *sessions.SessionState) error {
|
||||
+ // Fallback to ValidateURL if ProfileURL not set for legacy compatibility
|
||||
+ profileURL := p.ValidateURL.String()
|
||||
+ if p.ProfileURL.String() != "" {
|
||||
+ profileURL = p.ProfileURL.String()
|
||||
+ }
|
||||
+
|
||||
+ json, err := requests.New(profileURL).
|
||||
+ WithContext(ctx).
|
||||
+ SetHeader("Authorization", "Bearer "+s.AccessToken).
|
||||
+ Do().
|
||||
+ UnmarshalSimpleJSON()
|
||||
+ if err != nil {
|
||||
+ logger.Errorf("failed making request %v", err)
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ groups, err := json.Get("scopes").StringArray()
|
||||
+ if err == nil {
|
||||
+ for _, group := range groups {
|
||||
+ if group != "" {
|
||||
+ s.Groups = append(s.Groups, group)
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
// If a mandatory email wasn't set, error at this point.
|
||||
if s.Email == "" {
|
||||
return errors.New("neither the id_token nor the profileURL set an email")
|
5
pkgs/oauth2-proxy/default.nix
Normal file
5
pkgs/oauth2-proxy/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
final: prev: {
|
||||
oauth2-proxy = prev.oauth2-proxy.overrideAttrs (_: {
|
||||
patches = [./0001-scopes-as-groups.patch];
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue