Skip to content

Commit

Permalink
Ability to set no-redirects=true per path (#542)
Browse files Browse the repository at this point in the history
  • Loading branch information
p53 authored Jan 13, 2025
1 parent ed7ca2e commit 5349c42
Show file tree
Hide file tree
Showing 9 changed files with 431 additions and 206 deletions.
12 changes: 12 additions & 0 deletions pkg/authorization/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ type Resource struct {
Methods []string `json:"methods" yaml:"methods"`
// WhiteListed permits the prefix through
WhiteListed bool `json:"white-listed" yaml:"white-listed"`
// NoRedirect overrides global no-redirect setting
NoRedirect bool
// RequireAnyRole indicates that ANY of the roles are required, the default is all
RequireAnyRole bool `json:"require-any-role" yaml:"require-any-role"`
// Headers required to access this url
Expand Down Expand Up @@ -116,6 +118,16 @@ func (r *Resource) Parse(resource string) (*Resource, error) {
}

r.WhiteListed = value
case "no-redirect":
value, err := strconv.ParseBool(keyPair[1])
if err != nil {
return nil, errors.New(
"the value of no-redirect must be " +
"true|TRUE|T or it's false equivalent",
)
}

r.NoRedirect = value
case "acr":
r.Acr = strings.Split(keyPair[1], ",")
default:
Expand Down
206 changes: 107 additions & 99 deletions pkg/keycloak/proxy/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,18 +345,6 @@ func (r *OauthProxy) CreateReverseProxy() error {
WithOAuthURI,
)

redToAuth := core.RedirectToAuthorization(
r.Log,
r.Config.NoRedirects,
r.Cm,
r.Config.SkipTokenVerification,
r.Config.NoProxy,
r.Config.BaseURI,
r.Config.OAuthURI,
r.Config.AllowedQueryParams,
r.Config.DefaultAllowedQueryParams,
)

if r.Config.EnableHmac {
engine.Use(gmiddleware.HmacMiddleware(r.Log, r.Config.EncryptionKey))
}
Expand Down Expand Up @@ -438,7 +426,6 @@ func (r *OauthProxy) CreateReverseProxy() error {
r.Config.EnableEncryptedToken,
r.Config.ForceEncryptedCookie,
r.Config.EncryptionKey,
redToAuth,
newOAuth2Config,
r.Store,
r.Config.AccessTokenDuration,
Expand Down Expand Up @@ -530,14 +517,33 @@ func (r *OauthProxy) CreateReverseProxy() error {
r.Config.DefaultAllowedQueryParams,
)

redToAuthMiddleware := gmiddleware.NewRedirectToAuthorizationMiddleware(
r.Log,
r.Cm,
r.Config.SkipTokenVerification,
r.Config.NoProxy,
r.Config.BaseURI,
r.Config.OAuthURI,
r.Config.AllowedQueryParams,
r.Config.DefaultAllowedQueryParams,
)
noredToAuthMiddleware := gmiddleware.NoRedirectToAuthorizationMiddleware(r.Log)

var authFailMiddleware func(http.Handler) http.Handler
if r.Config.NoRedirects {
authFailMiddleware = noredToAuthMiddleware
} else {
authFailMiddleware = redToAuthMiddleware
}

// step: add the routing for oauth
engine.With(gmiddleware.ProxyDenyMiddleware(r.Log)).Route(r.Config.BaseURI+r.Config.OAuthURI, func(eng chi.Router) {
eng.MethodNotAllowed(handlers.MethodNotAllowHandlder)
eng.HandleFunc(constant.AuthorizationURL, oauthAuthorizationHand)
eng.Get(constant.CallbackURL, oauthCallbackHand)
eng.Get(constant.ExpiredURL, handlers.ExpirationHandler(getIdentity, r.Config.CookieAccessName))
eng.With(authMid).Get(constant.LogoutURL, logoutHand)
eng.With(authMid).Get(
eng.With(authMid, authFailMiddleware).Get(constant.LogoutURL, logoutHand)
eng.With(authMid, authFailMiddleware).Get(
constant.TokenURL,
handlers.TokenHandler(getIdentity, r.Config.CookieAccessName, accessError),
)
Expand Down Expand Up @@ -644,47 +650,64 @@ func (r *OauthProxy) CreateReverseProxy() error {
zap.String("resource", res.String()),
)

authFailMiddleware := redToAuthMiddleware
if res.NoRedirect || r.Config.NoRedirects {
authFailMiddleware = noredToAuthMiddleware
}

admissionMiddleware := gmiddleware.AdmissionMiddleware(
r.Log,
res,
r.Config.MatchClaims,
accessForbidden,
)

identityMiddleware := gmiddleware.IdentityHeadersMiddleware(
r.Log,
r.Config.AddClaims,
r.Config.CookieAccessName,
r.Config.CookieRefreshName,
r.Config.NoProxy,
r.Config.EnableTokenHeader,
r.Config.EnableAuthorizationHeader,
r.Config.EnableAuthorizationCookies,
)

middlewares := []func(http.Handler) http.Handler{
authMid,
gmiddleware.AdmissionMiddleware(
authFailMiddleware,
admissionMiddleware,
}

if r.Config.EnableLoA && res.NoRedirect {
r.Log.Warn(
"disabling LoA for resource, no-redirect=true for resource",
zap.String("resource", res.URL))
}
var loAMid func(http.Handler) http.Handler
if r.Config.EnableLoA && !res.NoRedirect {
loAMid = levelOfAuthenticationMiddleware(
r.Log,
r.Config.SkipTokenVerification,
r.Config.Scopes,
r.Config.EnablePKCE,
r.Config.SignInPage,
r.Cm,
newOAuth2Config,
getRedirectionURL,
customSignInPage,
res,
r.Config.MatchClaims,
accessForbidden,
),
}

if r.Config.EnableLoA {
)
middlewares = append(
middlewares,
levelOfAuthenticationMiddleware(
r.Log,
r.Config.SkipTokenVerification,
r.Config.Scopes,
r.Config.EnablePKCE,
r.Config.SignInPage,
r.Cm,
newOAuth2Config,
getRedirectionURL,
customSignInPage,
res,
accessForbidden,
),
loAMid,
)
}

middlewares = append(
middlewares,
gmiddleware.IdentityHeadersMiddleware(
r.Log,
r.Config.AddClaims,
r.Config.CookieAccessName,
r.Config.CookieRefreshName,
r.Config.NoProxy,
r.Config.EnableTokenHeader,
r.Config.EnableAuthorizationHeader,
r.Config.EnableAuthorizationCookies,
),
identityMiddleware,
)

if res.URL == constant.AllPath && !res.WhiteListed && enableDefaultDenyStrict {
Expand All @@ -695,72 +718,57 @@ func (r *OauthProxy) CreateReverseProxy() error {
}

if r.Config.EnableUma || r.Config.EnableOpa {
enableUma := r.Config.EnableUma
if r.Config.EnableUma && res.NoRedirect {
enableUma = false
r.Log.Warn(
"disabling EnableUma for resource, no-redirect=true for resource",
zap.String("resource", res.URL))
}

authzMiddleware := authorizationMiddleware(
r.Log,
enableUma,
r.Config.EnableUmaMethodScope,
r.Config.CookieUMAName,
r.Config.NoProxy,
r.pat,
r.Provider,
r.IdpClient,
r.Config.OpenIDProviderTimeout,
r.Config.Realm,
r.Config.EnableEncryptedToken,
r.Config.ForceEncryptedCookie,
r.Config.EncryptionKey,
r.Cm,
r.Config.EnableOpa,
r.Config.OpaTimeout,
r.Config.OpaAuthzURL,
r.Config.DiscoveryURI,
r.Config.ClientID,
r.Config.SkipAccessTokenClientIDCheck,
r.Config.SkipAccessTokenIssuerCheck,
getIdentity,
accessForbidden,
)

middlewares = []func(http.Handler) http.Handler{
authMid,
authorizationMiddleware(
r.Log,
r.Config.EnableUma,
r.Config.EnableUmaMethodScope,
r.Config.CookieUMAName,
r.Config.NoProxy,
r.pat,
r.Provider,
r.IdpClient,
r.Config.OpenIDProviderTimeout,
r.Config.Realm,
r.Config.EnableEncryptedToken,
r.Config.ForceEncryptedCookie,
r.Config.EncryptionKey,
r.Cm,
r.Config.EnableOpa,
r.Config.OpaTimeout,
r.Config.OpaAuthzURL,
r.Config.DiscoveryURI,
r.Config.ClientID,
r.Config.SkipAccessTokenClientIDCheck,
r.Config.SkipAccessTokenIssuerCheck,
getIdentity,
accessForbidden,
),
gmiddleware.AdmissionMiddleware(
r.Log,
res,
r.Config.MatchClaims,
accessForbidden,
),
authFailMiddleware,
authzMiddleware,
admissionMiddleware,
}

if r.Config.EnableLoA {
if r.Config.EnableLoA && !res.NoRedirect {
middlewares = append(
middlewares,
levelOfAuthenticationMiddleware(
r.Log,
r.Config.SkipTokenVerification,
r.Config.Scopes,
r.Config.EnablePKCE,
r.Config.SignInPage,
r.Cm,
newOAuth2Config,
getRedirectionURL,
customSignInPage,
res,
accessForbidden,
),
loAMid,
)
}

middlewares = append(
middlewares,
gmiddleware.IdentityHeadersMiddleware(
r.Log,
r.Config.AddClaims,
r.Config.CookieAccessName,
r.Config.CookieRefreshName,
r.Config.NoProxy,
r.Config.EnableTokenHeader,
r.Config.EnableAuthorizationHeader,
r.Config.EnableAuthorizationCookies,
),
identityMiddleware,
)
}

Expand Down
Loading

0 comments on commit 5349c42

Please sign in to comment.