75 lines
2.7 KiB
Go
75 lines
2.7 KiB
Go
package app
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"testing"
|
|
)
|
|
|
|
func TestAdminOAuthEndpointAllowlist(t *testing.T) {
|
|
valid := map[string]string{
|
|
"wechat": "https://api.weixin.qq.com/sns/userinfo",
|
|
"qq": "https://graph.qq.com/user/get_user_info",
|
|
"github": "https://api.github.com/user",
|
|
"google": "https://openidconnect.googleapis.com/v1/userinfo",
|
|
}
|
|
for provider, endpoint := range valid {
|
|
if err := validateAdminOAuthEndpoint(provider, endpoint); err != nil {
|
|
t.Fatalf("expected %s endpoint to be accepted: %v", provider, err)
|
|
}
|
|
}
|
|
invalid := []struct {
|
|
provider string
|
|
endpoint string
|
|
}{
|
|
{"github", "http://api.github.com/user"},
|
|
{"github", "https://127.0.0.1/user"},
|
|
{"google", "https://evil.example.com/token"},
|
|
{"github", "https://api.github.com:8443/user"},
|
|
{"qq", "javascript:alert(1)"},
|
|
}
|
|
for _, item := range invalid {
|
|
if err := validateAdminOAuthEndpoint(item.provider, item.endpoint); err == nil {
|
|
t.Fatalf("expected endpoint to be rejected: %s", item.endpoint)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAdminOAuthRedirectURLPolicy(t *testing.T) {
|
|
production := &App{config: productionConfigForTest()}
|
|
if err := production.validateAdminOAuthRedirectURL("https://admin.example.com/auth/social-callback"); err != nil {
|
|
t.Fatalf("expected HTTPS callback to be accepted: %v", err)
|
|
}
|
|
if err := production.validateAdminOAuthRedirectURL("http://localhost:5560/auth/social-callback"); err == nil {
|
|
t.Fatal("expected production HTTP callback to be rejected")
|
|
}
|
|
development := &App{config: Config{Environment: "development"}}
|
|
if err := development.validateAdminOAuthRedirectURL("http://127.0.0.1:8888/admin/v1/auth/oauth/callback"); err != nil {
|
|
t.Fatalf("expected local development callback to be accepted: %v", err)
|
|
}
|
|
if err := development.validateAdminOAuthRedirectURL("http://admin.example.com/callback"); err == nil {
|
|
t.Fatal("expected non-local HTTP callback to be rejected")
|
|
}
|
|
}
|
|
|
|
func TestUserOAuthResultKeepsHashRouteAndAddsQuery(t *testing.T) {
|
|
app := &App{}
|
|
request := httptest.NewRequest(http.MethodGet, "/api/v1/auth/oauth/callback", nil)
|
|
recorder := httptest.NewRecorder()
|
|
app.redirectUserOAuthResult(recorder, request, "http://localhost:5174/#/pages/auth/oauth-callback", "one-time-code", "")
|
|
if recorder.Code != http.StatusFound {
|
|
t.Fatalf("expected redirect status, got %d", recorder.Code)
|
|
}
|
|
target, err := url.Parse(recorder.Header().Get("Location"))
|
|
if err != nil {
|
|
t.Fatalf("invalid redirect URL: %v", err)
|
|
}
|
|
if target.Query().Get("oauthCode") != "one-time-code" {
|
|
t.Fatalf("missing one-time code in redirect: %s", target.String())
|
|
}
|
|
if target.Fragment != "/pages/auth/oauth-callback" {
|
|
t.Fatalf("hash route was lost: %s", target.String())
|
|
}
|
|
}
|