this repo has no description smallweb.run
smallweb
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

add support for oidc groups

pomdtr 4c1b44be 5fab92b8

+49 -29
+46 -29
cmd/up.go
··· 624 624 } 625 625 } 626 626 627 - email, err := me.extractEmail(r) 628 - if err != nil && IsRoutePrivate(appname, r.URL.Path) { 627 + userinfos, err := me.extractUserInfos(r) 628 + if err != nil && isRoutePrivate(appname, r.URL.Path) { 629 629 if !errors.Is(err, &oidc.TokenExpiredError{}) { 630 630 http.Redirect(w, r, fmt.Sprintf("https://%s/_smallweb/signin", r.Host), http.StatusTemporaryRedirect) 631 631 return ··· 665 665 return 666 666 } 667 667 668 - var claims struct { 669 - Email string `json:"email"` 670 - } 671 - 672 - if err := idToken.Claims(&claims); err != nil { 668 + if err := idToken.Claims(&userinfos); err != nil { 673 669 http.Redirect(w, r, fmt.Sprintf("https://%s/_smallweb/signin", r.Host), http.StatusTemporaryRedirect) 674 670 return 675 671 } ··· 698 694 } 699 695 } 700 696 701 - if IsRoutePrivate(appname, r.URL.Path) { 702 - var authorizedEmails []string 703 - authorizedEmails = append(authorizedEmails, k.Strings("authorizedEmails")...) 704 - authorizedEmails = append(authorizedEmails, k.Strings(fmt.Sprintf("apps.%s.authorizedEmails", appname))...) 705 - if len(authorizedEmails) > 0 && !slices.Contains(authorizedEmails, email) { 706 - http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden) 697 + if isRoutePrivate(appname, r.URL.Path) && !isAuthorized(appname, userinfos.Email, userinfos.Group) { 698 + if userinfos.Email == "" { 699 + http.Redirect(w, r, fmt.Sprintf("https://%s/_smallweb/signin", r.Host), http.StatusTemporaryRedirect) 707 700 return 708 701 } 709 - } 710 702 711 - if email != "" { 712 - r.Header.Set("Remote-Email", email) 703 + http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden) 704 + return 713 705 } 706 + 707 + r.Header.Set("Remote-User", userinfos.User) 708 + r.Header.Set("Remote-Email", userinfos.Email) 709 + r.Header.Set("Remote-Group", userinfos.Group) 710 + r.Header.Set("Remote-Name", userinfos.Name) 714 711 715 712 wk, err := me.GetWorker(appname, k.String("dir"), k.String("domain")) 716 713 if err != nil { ··· 728 725 wk.ServeHTTP(w, r) 729 726 } 730 727 731 - func IsRoutePrivate(appname string, route string) bool { 728 + func isRoutePrivate(appname string, route string) bool { 732 729 isPrivate := k.Bool(fmt.Sprintf("apps.%s.private", appname)) 733 730 734 731 for _, publicRoute := range k.Strings(fmt.Sprintf("apps.%s.publicRoutes", appname)) { ··· 746 743 return isPrivate 747 744 } 748 745 749 - func (me *Handler) extractEmail(r *http.Request) (string, error) { 746 + func isAuthorized(appname string, email string, group string) bool { 747 + var authorizedEmails []string 748 + authorizedEmails = append(authorizedEmails, k.Strings("authorizedEmails")...) 749 + authorizedEmails = append(authorizedEmails, k.Strings(fmt.Sprintf("apps.%s.authorizedEmails", appname))...) 750 + 751 + var authorizedGroups []string 752 + authorizedGroups = append(authorizedGroups, k.Strings("authorizedGroups")...) 753 + authorizedGroups = append(authorizedGroups, k.Strings(fmt.Sprintf("apps.%s.authorizedGroups", appname))...) 754 + 755 + return slices.Contains(authorizedEmails, email) || slices.Contains(authorizedGroups, group) 756 + } 757 + 758 + type UserInfos struct { 759 + Email string 760 + Group string 761 + User string 762 + Name string 763 + } 764 + 765 + func (me *Handler) extractUserInfos(r *http.Request) (UserInfos, error) { 750 766 if me.oidcProvider == nil { 751 - return r.Header.Get("Remote-Email"), nil 767 + return UserInfos{ 768 + Email: r.Header.Get("Remote-Email"), 769 + Group: r.Header.Get("Remote-Group"), 770 + User: r.Header.Get("Remote-User"), 771 + Name: r.Header.Get("Remote-Name"), 772 + }, nil 752 773 } 753 774 754 - r.Header.Del("Remote-Email") 755 775 idTokenCookie, err := r.Cookie("id_token") 756 776 if err != nil { 757 - return "", fmt.Errorf("id token not found") 777 + return UserInfos{}, fmt.Errorf("id token not found") 758 778 } 759 779 760 780 verifier := me.oidcProvider.Verifier(&oidc.Config{ClientID: fmt.Sprintf("https://%s", r.Host)}) 761 781 idToken, err := verifier.Verify(r.Context(), idTokenCookie.Value) 762 782 if err != nil { 763 - return "", fmt.Errorf("failed to verify id token: %v", err) 764 - } 765 - 766 - var claims struct { 767 - Email string `json:"email"` 783 + return UserInfos{}, fmt.Errorf("failed to verify id token: %v", err) 768 784 } 769 785 770 - if err := idToken.Claims(&claims); err != nil { 771 - return "", fmt.Errorf("failed to extract claims: %v", err) 786 + var userinfo UserInfos 787 + if err := idToken.Claims(&userinfo); err != nil { 788 + return UserInfos{}, fmt.Errorf("failed to extract claims: %v", err) 772 789 } 773 790 774 - return claims.Email, nil 791 + return userinfo, nil 775 792 } 776 793 777 794 func lookupApp(domain string) (app string, redirect bool, found bool) {
+3
example/.smallweb/config.json
··· 2 2 "$schema": "../../schemas/config.schema.json", 3 3 "domain": "smallweb.localhost", 4 4 "oidc.issuer": "https://lastlogin.net", 5 + "authorizedEmails": [ 6 + "achille.lacoin@gmail.com" 7 + ], 5 8 "apps": { 6 9 "ls": { 7 10 "admin": true,