1
1
Fork 1
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:
oddlama 2023-06-23 15:20:58 +02:00
parent 1a0378ee5c
commit eb9ee0bf0d
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
7 changed files with 65 additions and 16 deletions

View file

@ -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
```

View file

@ -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;
};
};
}

View file

@ -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;

View file

@ -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?
};
};

View file

@ -1,3 +1,4 @@
[
(import ./caddy.nix)
(import ./oauth2-proxy)
]

View 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")

View file

@ -0,0 +1,5 @@
final: prev: {
oauth2-proxy = prev.oauth2-proxy.overrideAttrs (_: {
patches = [./0001-scopes-as-groups.patch];
});
}