fixed up auth check interval

This commit is contained in:
Ziti-Ci 2023-09-05 11:50:41 -05:00
parent 8e63548552
commit a07552f0c4
No known key found for this signature in database
GPG Key ID: 367B7C7EBD84A8BD
9 changed files with 100 additions and 65 deletions

View File

@ -111,7 +111,6 @@ func (cmd *sharePublicCommand) run(_ *cobra.Command, args []string) {
}
if cmd.oauthProvider != "" {
req.Auth = []string{}
req.OauthProvider = cmd.oauthProvider
req.OauthEmailDomains = cmd.oauthEmailDomains
req.OauthAuthorizationCheckInterval = cmd.oauthCheckInterval

View File

@ -18,7 +18,11 @@ func (a *privateResourceAllocator) allocate(envZId, shrToken string, params shar
for _, authUser := range params.Body.AuthUsers {
authUsers = append(authUsers, &sdk.AuthUser{authUser.Username, authUser.Password})
}
cfgZId, err := zrokEdgeSdk.CreateConfig(zrokProxyConfigId, envZId, shrToken, params.Body.AuthScheme, authUsers, params.Body.OauthProvider, params.Body.OauthEmailDomains, edge)
cfgZId, err := zrokEdgeSdk.CreateConfig(zrokProxyConfigId, envZId, shrToken, params.Body.AuthScheme, authUsers, &zrokEdgeSdk.OauthOptions{
Provider: params.Body.OauthProvider,
EmailDomains: params.Body.OauthEmailDomains,
AuthorizationCheckInterval: params.Body.OauthAuthorizationCheckInterval,
}, edge)
if err != nil {
return "", nil, err
}

View File

@ -18,7 +18,11 @@ func (a *publicResourceAllocator) allocate(envZId, shrToken string, frontendZIds
for _, authUser := range params.Body.AuthUsers {
authUsers = append(authUsers, &sdk.AuthUser{authUser.Username, authUser.Password})
}
cfgId, err := zrokEdgeSdk.CreateConfig(zrokProxyConfigId, envZId, shrToken, params.Body.AuthScheme, authUsers, params.Body.OauthProvider, params.Body.OauthEmailDomains, edge)
cfgId, err := zrokEdgeSdk.CreateConfig(zrokProxyConfigId, envZId, shrToken, params.Body.AuthScheme, authUsers, &zrokEdgeSdk.OauthOptions{
Provider: params.Body.OauthProvider,
EmailDomains: params.Body.OauthEmailDomains,
AuthorizationCheckInterval: params.Body.OauthAuthorizationCheckInterval,
}, edge)
if err != nil {
return "", nil, err
}

View File

@ -11,7 +11,13 @@ import (
"time"
)
func CreateConfig(cfgTypeZId, envZId, shrToken string, authSchemeStr string, authUsers []*sdk.AuthUser, oauthProvider string, oauthEmailDomains []string, edge *rest_management_api_client.ZitiEdgeManagement) (cfgZId string, err error) {
type OauthOptions struct {
Provider string
EmailDomains []string
AuthorizationCheckInterval string
}
func CreateConfig(cfgTypeZId, envZId, shrToken string, authSchemeStr string, authUsers []*sdk.AuthUser, oauthOptions *OauthOptions, edge *rest_management_api_client.ZitiEdgeManagement) (cfgZId string, err error) {
authScheme, err := sdk.ParseAuthScheme(authSchemeStr)
if err != nil {
return "", err
@ -25,10 +31,11 @@ func CreateConfig(cfgTypeZId, envZId, shrToken string, authSchemeStr string, aut
cfg.BasicAuth.Users = append(cfg.BasicAuth.Users, &sdk.AuthUser{Username: authUser.Username, Password: authUser.Password})
}
}
if cfg.AuthScheme == model.Oauth {
cfg.OauthAuth = &model.OauthAuth{
Provider: oauthProvider,
EmailDomains: oauthEmailDomains,
if cfg.AuthScheme == sdk.Oauth && oauthOptions != nil {
cfg.OauthAuth = &sdk.OauthAuth{
Provider: oauthOptions.Provider,
EmailDomains: oauthOptions.EmailDomains,
AuthorizationCheckInterval: oauthOptions.AuthorizationCheckInterval,
}
}
cfgCrt := &rest_model.ConfigCreate{

View File

@ -57,8 +57,9 @@ func configureGithubOauth(cfg *OauthConfig, tls bool) error {
}
type IntermediateJWT struct {
State string `json:"state"`
Share string `json:"share"`
State string `json:"state"`
Share string `json:"share"`
AuthorizationCheckInterval string `json:"authorizationCheckInterval"`
jwt.RegisteredClaims
}
@ -76,6 +77,7 @@ func configureGithubOauth(cfg *OauthConfig, tls bool) error {
t := jwt.NewWithClaims(jwt.SigningMethodHS256, IntermediateJWT{
id,
r.URL.Query().Get("share"),
r.URL.Query().Get("checkInterval"),
jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
@ -134,8 +136,6 @@ func configureGithubOauth(cfg *OauthConfig, tls bool) error {
}
}
SetZrokCookie(w, primaryEmail, tokens.AccessToken, "github", 3*time.Hour, key)
token, err := jwt.ParseWithClaims(state, &IntermediateJWT{}, func(t *jwt.Token) (interface{}, error) {
return key, nil
})
@ -143,6 +143,16 @@ func configureGithubOauth(cfg *OauthConfig, tls bool) error {
http.Error(w, fmt.Sprintf("After intermediate token parse: %v", err.Error()), http.StatusInternalServerError)
return
}
authCheckInterval := 3 * time.Hour
i, err := time.ParseDuration(token.Claims.(*IntermediateJWT).AuthorizationCheckInterval)
if err != nil {
logrus.Errorf("unable to parse authorization check interval: %v. Defaulting to 3 hours", err)
} else {
authCheckInterval = i
}
SetZrokCookie(w, primaryEmail, tokens.AccessToken, "github", authCheckInterval, key)
http.Redirect(w, r, fmt.Sprintf("%s://%s.%s:8080", scheme, token.Claims.(*IntermediateJWT).Share, cfg.RedirectUrl), http.StatusFound)
}

View File

@ -58,8 +58,9 @@ func configureGoogleOauth(cfg *OauthConfig, tls bool) error {
}
type IntermediateJWT struct {
State string `json:"state"`
Share string `json:"share"`
State string `json:"state"`
Share string `json:"share"`
AuthorizationCheckInterval string `json:"authorizationCheckInterval"`
jwt.RegisteredClaims
}
@ -74,6 +75,7 @@ func configureGoogleOauth(cfg *OauthConfig, tls bool) error {
t := jwt.NewWithClaims(jwt.SigningMethodHS256, IntermediateJWT{
id,
r.URL.Query().Get("share"),
r.URL.Query().Get("checkInterval"),
jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
@ -113,8 +115,6 @@ func configureGoogleOauth(cfg *OauthConfig, tls bool) error {
return
}
SetZrokCookie(w, rDat.Email, tokens.AccessToken, "google", 3*time.Hour, key)
token, err := jwt.ParseWithClaims(state, &IntermediateJWT{}, func(t *jwt.Token) (interface{}, error) {
return key, nil
})
@ -122,6 +122,16 @@ func configureGoogleOauth(cfg *OauthConfig, tls bool) error {
http.Error(w, fmt.Sprintf("After intermediate token parse: %v", err.Error()), http.StatusInternalServerError)
return
}
authCheckInterval := 3 * time.Hour
i, err := time.ParseDuration(token.Claims.(*IntermediateJWT).AuthorizationCheckInterval)
if err != nil {
logrus.Errorf("unable to parse authorization check interval: %v. Defaulting to 3 hours", err)
} else {
authCheckInterval = i
}
SetZrokCookie(w, rDat.Email, tokens.AccessToken, "google", authCheckInterval, key)
http.Redirect(w, r, fmt.Sprintf("%s://%s.%s:8080", scheme, token.Claims.(*IntermediateJWT).Share, cfg.RedirectUrl), http.StatusFound)
}

View File

@ -3,32 +3,24 @@ package publicProxy
import (
"context"
"fmt"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/zrok/endpoints"
"github.com/openziti/zrok/endpoints/publicProxy/healthUi"
"github.com/openziti/zrok/endpoints/publicProxy/notFoundUi"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk"
"github.com/openziti/zrok/util"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/openziti/sdk-golang/ziti"
"github.com/openziti/zrok/endpoints"
"github.com/openziti/zrok/endpoints/publicProxy/healthUi"
"github.com/openziti/zrok/endpoints/publicProxy/notFoundUi"
"github.com/openziti/zrok/endpoints/publicProxy/unauthorizedUi"
"github.com/openziti/zrok/environment"
"github.com/openziti/zrok/sdk"
"github.com/openziti/zrok/util"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
zhttp "github.com/zitadel/oidc/v2/pkg/http"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"time"
)
type httpFrontend struct {
@ -202,29 +194,6 @@ func authHandler(handler http.Handler, realm string, pcfg *Config, ctx ziti.Cont
case string(sdk.Oauth):
if oauthCfg, found := cfg["oauth"]; found {
if provider, found := oauthCfg.(map[string]interface{})["provider"]; found {
cookie, err := r.Cookie("zrok-access")
if err != nil {
logrus.Errorf("Unable to get access cookie: %v", err)
http.Redirect(w, r, fmt.Sprintf("http://%s.%s:28080/%s/login?share=%s", shrToken, pcfg.HostMatch, provider.(string), shrToken), http.StatusFound)
return
}
tkn, err := jwt.ParseWithClaims(cookie.Value, &ZrokClaims{}, func(t *jwt.Token) (interface{}, error) {
if pcfg.Oauth == nil {
return nil, fmt.Errorf("Missing oauth configuration for access point. Unable to parse jwt")
}
return pcfg.Oauth.HashKeyRaw, nil
})
if err != nil {
logrus.Errorf("Unable to parse JWT: %v", err)
http.Redirect(w, r, fmt.Sprintf("http://%s.%s:28080/%s/login?share=%s", shrToken, pcfg.HostMatch, provider.(string), shrToken), http.StatusFound)
return
}
claims := tkn.Claims.(*ZrokClaims)
if claims.Provider != provider {
logrus.Error("Provider mismatch. Redoing auth flow")
http.Redirect(w, r, fmt.Sprintf("http://%s.%s:28080/%s/login?share=%s", shrToken, pcfg.HostMatch, provider.(string), shrToken), http.StatusFound)
return
}
var authCheckInterval time.Duration
if checkInterval, found := oauthCfg.(map[string]interface{})["authorization_check_interval"]; !found {
logrus.Errorf("Missing authorization check interval in share config. Defaulting to 3 hours")
@ -238,9 +207,33 @@ func authHandler(handler http.Handler, realm string, pcfg *Config, ctx ziti.Cont
authCheckInterval = i
}
}
cookie, err := r.Cookie("zrok-access")
if err != nil {
logrus.Errorf("Unable to get access cookie: %v", err)
http.Redirect(w, r, fmt.Sprintf("http://%s.%s:28080/%s/login?share=%s&checkInterval=%s", shrToken, pcfg.HostMatch, provider.(string), shrToken, authCheckInterval.String()), http.StatusFound)
return
}
tkn, err := jwt.ParseWithClaims(cookie.Value, &ZrokClaims{}, func(t *jwt.Token) (interface{}, error) {
if pcfg.Oauth == nil {
return nil, fmt.Errorf("missing oauth configuration for access point. Unable to parse jwt")
}
return []byte(pcfg.Oauth.HashKeyRaw), nil
})
if err != nil {
logrus.Errorf("Unable to parse JWT: %v", err)
http.Redirect(w, r, fmt.Sprintf("http://%s.%s:28080/%s/login?share=%s&checkInterval=%s", shrToken, pcfg.HostMatch, provider.(string), shrToken, authCheckInterval.String()), http.StatusFound)
return
}
claims := tkn.Claims.(*ZrokClaims)
if claims.Provider != provider {
logrus.Error("Provider mismatch. Redoing auth flow")
http.Redirect(w, r, fmt.Sprintf("http://%s.%s:28080/%s/login?share=%s&checkInterval=%s", shrToken, pcfg.HostMatch, provider.(string), shrToken, authCheckInterval.String()), http.StatusFound)
return
}
if claims.AuthorizationCheckInterval != authCheckInterval {
logrus.Error("Authorization check interval mismatch. Redoing auth flow")
http.Redirect(w, r, fmt.Sprintf("http://%s.%s:28080/%s/login?share=%s", shrToken, pcfg.HostMatch, provider.(string), shrToken), http.StatusFound)
http.Redirect(w, r, fmt.Sprintf("http://%s.%s:28080/%s/login?share=%s&checkInterval=%s", shrToken, pcfg.HostMatch, provider.(string), shrToken, authCheckInterval.String()), http.StatusFound)
return
}
if validDomains, found := oauthCfg.(map[string]interface{})["email_domains"]; found {
@ -337,7 +330,7 @@ func SetZrokCookie(w http.ResponseWriter, email, accessToken, provider string, c
http.SetCookie(w, &http.Cookie{
Name: "zrok-access",
Value: sTkn,
MaxAge: 3000,
MaxAge: int(checkInterval.Seconds()),
Domain: "localzrok.io",
Path: "/",
Expires: time.Now().Add(checkInterval),

View File

@ -20,8 +20,9 @@ type AuthUser struct {
}
type OauthAuth struct {
Provider string `json:"provider"`
EmailDomains []string `json:"email_domains"`
Provider string `json:"provider"`
EmailDomains []string `json:"email_domains"`
AuthorizationCheckInterval string `json:"authorization_check_interval"`
}
func ParseAuthScheme(authScheme string) (AuthScheme, error) {

View File

@ -38,6 +38,10 @@ func CreateShare(root env_core.Root, request *ShareRequest) (*Share, error) {
}
}
if request.OauthProvider != "" {
out.Body.AuthScheme = string(Oauth)
}
zrok, err := root.Client()
if err != nil {
return nil, errors.Wrap(err, "error getting zrok client")
@ -70,12 +74,15 @@ func newPrivateShare(root env_core.Root, request *ShareRequest) *share.SharePara
func newPublicShare(root env_core.Root, request *ShareRequest) *share.ShareParams {
req := share.NewShareParams()
req.Body = &rest_model_zrok.ShareRequest{
EnvZID: root.Environment().ZitiIdentity,
ShareMode: string(request.ShareMode),
FrontendSelection: request.Frontends,
BackendMode: string(request.BackendMode),
BackendProxyEndpoint: request.Target,
AuthScheme: string(None),
EnvZID: root.Environment().ZitiIdentity,
ShareMode: string(request.ShareMode),
FrontendSelection: request.Frontends,
BackendMode: string(request.BackendMode),
BackendProxyEndpoint: request.Target,
AuthScheme: string(None),
OauthEmailDomains: request.OauthEmailDomains,
OauthProvider: request.OauthProvider,
OauthAuthorizationCheckInterval: request.OauthAuthorizationCheckInterval.String(),
}
return req
}