backport OIDC related changes from main

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino
2022-07-23 15:31:57 +02:00
parent b34bc2b818
commit 2da19ef233
19 changed files with 364 additions and 111 deletions

View File

@@ -15,11 +15,13 @@
package httpd
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"reflect"
@@ -30,6 +32,7 @@ import (
"github.com/coreos/go-oidc/v3/oidc"
"github.com/go-chi/jwtauth/v5"
"github.com/lestrrat-go/jwx/jwa"
"github.com/rs/xid"
"github.com/sftpgo/sdk"
"github.com/stretchr/testify/assert"
@@ -1160,6 +1163,97 @@ func TestOIDCIsAdmin(t *testing.T) {
}
}
func TestOIDCWithLoginFormsDisabled(t *testing.T) {
oidcMgr, ok := oidcMgr.(*memoryOIDCManager)
require.True(t, ok)
server := getTestOIDCServer()
server.binding.OIDC.ImplicitRoles = true
server.binding.EnabledLoginMethods = 3
server.binding.EnableWebAdmin = true
server.binding.EnableWebClient = true
err := server.binding.OIDC.initialize()
assert.NoError(t, err)
server.initializeRouter()
// login with an admin user
authReq := newOIDCPendingAuth(tokenAudienceWebAdmin)
oidcMgr.addPendingAuth(authReq)
token := &oauth2.Token{
AccessToken: "1234",
Expiry: time.Now().Add(5 * time.Minute),
}
token = token.WithExtra(map[string]any{
"id_token": "id_token_val",
})
server.binding.OIDC.oauth2Config = &mockOAuth2Config{
tokenSource: &mockTokenSource{},
authCodeURL: webOIDCRedirectPath,
token: token,
}
idToken := &oidc.IDToken{
Nonce: authReq.Nonce,
Expiry: time.Now().Add(5 * time.Minute),
}
setIDTokenClaims(idToken, []byte(`{"preferred_username":"admin","sid":"sid456"}`))
server.binding.OIDC.verifier = &mockOIDCVerifier{
err: nil,
token: idToken,
}
rr := httptest.NewRecorder()
r, err := http.NewRequest(http.MethodGet, webOIDCRedirectPath+"?state="+authReq.State, nil)
assert.NoError(t, err)
server.router.ServeHTTP(rr, r)
assert.Equal(t, http.StatusFound, rr.Code)
assert.Equal(t, webUsersPath, rr.Header().Get("Location"))
var tokenCookie string
for k := range oidcMgr.tokens {
tokenCookie = k
}
// we should be able to create admins without setting a password
if csrfTokenAuth == nil {
csrfTokenAuth = jwtauth.New(jwa.HS256.String(), util.GenerateRandomBytes(32), nil)
}
adminUsername := "testAdmin"
form := make(url.Values)
form.Set(csrfFormToken, createCSRFToken(""))
form.Set("username", adminUsername)
form.Set("password", "")
form.Set("status", "1")
form.Set("permissions", "*")
rr = httptest.NewRecorder()
r, err = http.NewRequest(http.MethodPost, webAdminPath, bytes.NewBuffer([]byte(form.Encode())))
assert.NoError(t, err)
r.Header.Set("Cookie", fmt.Sprintf("%v=%v", oidcCookieKey, tokenCookie))
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
server.router.ServeHTTP(rr, r)
assert.Equal(t, http.StatusSeeOther, rr.Code)
_, err = dataprovider.AdminExists(adminUsername)
assert.NoError(t, err)
err = dataprovider.DeleteAdmin(adminUsername, "", "")
assert.NoError(t, err)
// login and password related routes are disabled
rr = httptest.NewRecorder()
r, err = http.NewRequest(http.MethodPost, webAdminLoginPath, nil)
assert.NoError(t, err)
server.router.ServeHTTP(rr, r)
assert.Equal(t, http.StatusMethodNotAllowed, rr.Code)
rr = httptest.NewRecorder()
r, err = http.NewRequest(http.MethodPost, webAdminTwoFactorPath, nil)
assert.NoError(t, err)
server.router.ServeHTTP(rr, r)
assert.Equal(t, http.StatusNotFound, rr.Code)
rr = httptest.NewRecorder()
r, err = http.NewRequest(http.MethodPost, webClientLoginPath, nil)
assert.NoError(t, err)
server.router.ServeHTTP(rr, r)
assert.Equal(t, http.StatusMethodNotAllowed, rr.Code)
rr = httptest.NewRecorder()
r, err = http.NewRequest(http.MethodPost, webClientForgotPwdPath, nil)
assert.NoError(t, err)
server.router.ServeHTTP(rr, r)
assert.Equal(t, http.StatusNotFound, rr.Code)
}
func TestDbOIDCManager(t *testing.T) {
if !isSharedProviderSupported() {
t.Skip("this test it is not available with this provider")
@@ -1284,6 +1378,7 @@ func getTestOIDCServer() *httpdServer {
ImplicitRoles: false,
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
CustomFields: nil,
Debug: true,
},
},
enableWebAdmin: true,