mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-30 21:55:43 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			a9c1bf8865
			...
			v4.0.1-bet
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 2ea921f3ca | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 473109b36a | ||
|   | f628d1f0b3 | 
| @@ -1,5 +1,5 @@ | |||||||
| # Site builder | # Site builder | ||||||
| FROM oven/bun:1.2.23-alpine AS frontend-builder | FROM oven/bun:1.3.0-alpine AS frontend-builder | ||||||
|  |  | ||||||
| WORKDIR /frontend | WORKDIR /frontend | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| # Site builder | # Site builder | ||||||
| FROM oven/bun:1.2.23-alpine AS frontend-builder | FROM oven/bun:1.3.0-alpine AS frontend-builder | ||||||
|  |  | ||||||
| WORKDIR /frontend | WORKDIR /frontend | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ | |||||||
|         "axios": "^1.12.2", |         "axios": "^1.12.2", | ||||||
|         "class-variance-authority": "^0.7.1", |         "class-variance-authority": "^0.7.1", | ||||||
|         "clsx": "^2.1.1", |         "clsx": "^2.1.1", | ||||||
|         "i18next": "^25.5.3", |         "i18next": "^25.6.0", | ||||||
|         "i18next-browser-languagedetector": "^8.2.0", |         "i18next-browser-languagedetector": "^8.2.0", | ||||||
|         "i18next-resources-to-backend": "^1.2.1", |         "i18next-resources-to-backend": "^1.2.1", | ||||||
|         "input-otp": "^1.4.2", |         "input-otp": "^1.4.2", | ||||||
| @@ -22,7 +22,7 @@ | |||||||
|         "next-themes": "^0.4.6", |         "next-themes": "^0.4.6", | ||||||
|         "react": "^19.2.0", |         "react": "^19.2.0", | ||||||
|         "react-dom": "^19.2.0", |         "react-dom": "^19.2.0", | ||||||
|         "react-hook-form": "^7.64.0", |         "react-hook-form": "^7.65.0", | ||||||
|         "react-i18next": "^16.0.0", |         "react-i18next": "^16.0.0", | ||||||
|         "react-markdown": "^10.1.0", |         "react-markdown": "^10.1.0", | ||||||
|         "react-router": "^7.9.4", |         "react-router": "^7.9.4", | ||||||
| @@ -34,7 +34,7 @@ | |||||||
|       "devDependencies": { |       "devDependencies": { | ||||||
|         "@eslint/js": "^9.37.0", |         "@eslint/js": "^9.37.0", | ||||||
|         "@tanstack/eslint-plugin-query": "^5.91.0", |         "@tanstack/eslint-plugin-query": "^5.91.0", | ||||||
|         "@types/node": "^24.7.1", |         "@types/node": "^24.7.2", | ||||||
|         "@types/react": "^19.2.2", |         "@types/react": "^19.2.2", | ||||||
|         "@types/react-dom": "^19.2.1", |         "@types/react-dom": "^19.2.1", | ||||||
|         "@vitejs/plugin-react": "^5.0.4", |         "@vitejs/plugin-react": "^5.0.4", | ||||||
| @@ -355,7 +355,7 @@ | |||||||
|  |  | ||||||
|     "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], |     "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], | ||||||
|  |  | ||||||
|     "@types/node": ["@types/node@24.7.1", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-CmyhGZanP88uuC5GpWU9q+fI61j2SkhO3UGMUdfYRE6Bcy0ccyzn1Rqj9YAB/ZY4kOXmNf0ocah5GtphmLMP6Q=="], |     "@types/node": ["@types/node@24.7.2", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA=="], | ||||||
|  |  | ||||||
|     "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="], |     "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="], | ||||||
|  |  | ||||||
| @@ -583,7 +583,7 @@ | |||||||
|  |  | ||||||
|     "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], |     "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="], | ||||||
|  |  | ||||||
|     "i18next": ["i18next@25.5.3", "", { "dependencies": { "@babel/runtime": "^7.27.6" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-joFqorDeQ6YpIXni944upwnuHBf5IoPMuqAchGVeQLdWC2JOjxgM9V8UGLhNIIH/Q8QleRxIi0BSRQehSrDLcg=="], |     "i18next": ["i18next@25.6.0", "", { "dependencies": { "@babel/runtime": "^7.27.6" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-tTn8fLrwBYtnclpL5aPXK/tAYBLWVvoHM1zdfXoRNLcI+RvtMsoZRV98ePlaW3khHYKuNh/Q65W/+NVFUeIwVw=="], | ||||||
|  |  | ||||||
|     "i18next-browser-languagedetector": ["i18next-browser-languagedetector@8.2.0", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g=="], |     "i18next-browser-languagedetector": ["i18next-browser-languagedetector@8.2.0", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g=="], | ||||||
|  |  | ||||||
| @@ -791,7 +791,7 @@ | |||||||
|  |  | ||||||
|     "react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="], |     "react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="], | ||||||
|  |  | ||||||
|     "react-hook-form": ["react-hook-form@7.64.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-fnN+vvTiMLnRqKNTVhDysdrUay0kUUAymQnFIznmgDvapjveUWOOPqMNzPg+A+0yf9DuE2h6xzBjN1s+Qx8wcg=="], |     "react-hook-form": ["react-hook-form@7.65.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-xtOzDz063WcXvGWaHgLNrNzlsdFgtUWcb32E6WFaGTd7kPZG3EeDusjdZfUsPwKCKVXy1ZlntifaHZ4l8pAsmw=="], | ||||||
|  |  | ||||||
|     "react-i18next": ["react-i18next@16.0.0", "", { "dependencies": { "@babel/runtime": "^7.27.6", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { "i18next": ">= 25.5.2", "react": ">= 16.8.0", "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-JQ+dFfLnFSKJQt7W01lJHWRC0SX7eDPobI+MSTJ3/gP39xH2g33AuTE7iddAfXYHamJdAeMGM0VFboPaD3G68Q=="], |     "react-i18next": ["react-i18next@16.0.0", "", { "dependencies": { "@babel/runtime": "^7.27.6", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { "i18next": ">= 25.5.2", "react": ">= 16.8.0", "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-JQ+dFfLnFSKJQt7W01lJHWRC0SX7eDPobI+MSTJ3/gP39xH2g33AuTE7iddAfXYHamJdAeMGM0VFboPaD3G68Q=="], | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
|     "axios": "^1.12.2", |     "axios": "^1.12.2", | ||||||
|     "class-variance-authority": "^0.7.1", |     "class-variance-authority": "^0.7.1", | ||||||
|     "clsx": "^2.1.1", |     "clsx": "^2.1.1", | ||||||
|     "i18next": "^25.5.3", |     "i18next": "^25.6.0", | ||||||
|     "i18next-browser-languagedetector": "^8.2.0", |     "i18next-browser-languagedetector": "^8.2.0", | ||||||
|     "i18next-resources-to-backend": "^1.2.1", |     "i18next-resources-to-backend": "^1.2.1", | ||||||
|     "input-otp": "^1.4.2", |     "input-otp": "^1.4.2", | ||||||
| @@ -28,7 +28,7 @@ | |||||||
|     "next-themes": "^0.4.6", |     "next-themes": "^0.4.6", | ||||||
|     "react": "^19.2.0", |     "react": "^19.2.0", | ||||||
|     "react-dom": "^19.2.0", |     "react-dom": "^19.2.0", | ||||||
|     "react-hook-form": "^7.64.0", |     "react-hook-form": "^7.65.0", | ||||||
|     "react-i18next": "^16.0.0", |     "react-i18next": "^16.0.0", | ||||||
|     "react-markdown": "^10.1.0", |     "react-markdown": "^10.1.0", | ||||||
|     "react-router": "^7.9.4", |     "react-router": "^7.9.4", | ||||||
| @@ -40,7 +40,7 @@ | |||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "@eslint/js": "^9.37.0", |     "@eslint/js": "^9.37.0", | ||||||
|     "@tanstack/eslint-plugin-query": "^5.91.0", |     "@tanstack/eslint-plugin-query": "^5.91.0", | ||||||
|     "@types/node": "^24.7.1", |     "@types/node": "^24.7.2", | ||||||
|     "@types/react": "^19.2.2", |     "@types/react": "^19.2.2", | ||||||
|     "@types/react-dom": "^19.2.1", |     "@types/react-dom": "^19.2.1", | ||||||
|     "@vitejs/plugin-react": "^5.0.4", |     "@vitejs/plugin-react": "^5.0.4", | ||||||
|   | |||||||
| @@ -100,17 +100,17 @@ func IsRedirectSafe(redirectURL string, domain string) bool { | |||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	cookieDomain, err := GetCookieDomain(redirectURL) | 	host := parsedURL.Hostname() | ||||||
|  | 	if host == domain { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	cookieDomain, err := GetCookieDomain(redirectURL) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if cookieDomain != domain { | 	return cookieDomain == domain | ||||||
| 		return false |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return true |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func GetLogLevel(level string) zerolog.Level { | func GetLogLevel(level string) zerolog.Level { | ||||||
|   | |||||||
| @@ -164,7 +164,7 @@ func TestIsRedirectSafe(t *testing.T) { | |||||||
| 	// Case with no subdomain | 	// Case with no subdomain | ||||||
| 	redirectURL := "http://example.com/welcome" | 	redirectURL := "http://example.com/welcome" | ||||||
| 	result := utils.IsRedirectSafe(redirectURL, domain) | 	result := utils.IsRedirectSafe(redirectURL, domain) | ||||||
| 	assert.Equal(t, false, result) | 	assert.Equal(t, true, result) | ||||||
|  |  | ||||||
| 	// Case with different domain | 	// Case with different domain | ||||||
| 	redirectURL = "http://malicious.com/phishing" | 	redirectURL = "http://malicious.com/phishing" | ||||||
| @@ -202,6 +202,41 @@ func TestIsRedirectSafe(t *testing.T) { | |||||||
| 	assert.Equal(t, false, result) | 	assert.Equal(t, false, result) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestIsRedirectSafeMultiLevel(t *testing.T) { | ||||||
|  | 	// Setup | ||||||
|  | 	cookieDomain := "tinyauth.example.com" | ||||||
|  |  | ||||||
|  | 	// Case with 3rd level domain | ||||||
|  | 	redirectURL := "http://tinyauth.example.com/welcome" | ||||||
|  | 	result := utils.IsRedirectSafe(redirectURL, cookieDomain) | ||||||
|  | 	assert.Equal(t, true, result) | ||||||
|  |  | ||||||
|  | 	// Case with root domain | ||||||
|  | 	redirectURL = "http://example.com/unsafe" | ||||||
|  | 	result = utils.IsRedirectSafe(redirectURL, cookieDomain) | ||||||
|  | 	assert.Equal(t, false, result) | ||||||
|  |  | ||||||
|  | 	// Case with 4th level domain | ||||||
|  | 	redirectURL = "http://auth.tinyauth.example.com/post-login" | ||||||
|  | 	result = utils.IsRedirectSafe(redirectURL, cookieDomain) | ||||||
|  | 	assert.Equal(t, true, result) | ||||||
|  |  | ||||||
|  | 	// Case with 5th level domain (should be unsafe) | ||||||
|  | 	redirectURL = "http://x.auth.tinyauth.example.com/deep" | ||||||
|  | 	result = utils.IsRedirectSafe(redirectURL, cookieDomain) | ||||||
|  | 	assert.Equal(t, false, result) | ||||||
|  |  | ||||||
|  | 	// Case with different subdomain | ||||||
|  | 	redirectURL = "http://auth.tinyauth.example.net/attack" | ||||||
|  | 	result = utils.IsRedirectSafe(redirectURL, cookieDomain) | ||||||
|  | 	assert.Equal(t, false, result) | ||||||
|  |  | ||||||
|  | 	// Case with malformed URL | ||||||
|  | 	redirectURL = "http://[::1]:namedport" | ||||||
|  | 	result = utils.IsRedirectSafe(redirectURL, cookieDomain) | ||||||
|  | 	assert.Equal(t, false, result) | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestGetOAuthProvidersConfig(t *testing.T) { | func TestGetOAuthProvidersConfig(t *testing.T) { | ||||||
| 	env := []string{"PROVIDERS_CLIENT1_CLIENT_ID=client1-id", "PROVIDERS_CLIENT1_CLIENT_SECRET=client1-secret"} | 	env := []string{"PROVIDERS_CLIENT1_CLIENT_ID=client1-id", "PROVIDERS_CLIENT1_CLIENT_SECRET=client1-secret"} | ||||||
| 	args := []string{"/tinyauth/tinyauth", "--providers-client2-client-id=client2-id", "--providers-client2-client-secret=client2-secret"} | 	args := []string{"/tinyauth/tinyauth", "--providers-client2-client-id=client2-id", "--providers-client2-client-secret=client2-secret"} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user