mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-30 21:55:43 +00:00 
			
		
		
		
	feat: add psl check in cookie domain
This commit is contained in:
		| @@ -5,7 +5,6 @@ export const appContextSchema = z.object({ | |||||||
|   title: z.string(), |   title: z.string(), | ||||||
|   genericName: z.string(), |   genericName: z.string(), | ||||||
|   appUrl: z.string(), |   appUrl: z.string(), | ||||||
|   rootDomain: z.string(), |  | ||||||
|   forgotPasswordMessage: z.string(), |   forgotPasswordMessage: z.string(), | ||||||
|   oauthAutoRedirect: z.enum(["none", "github", "google", "generic"]), |   oauthAutoRedirect: z.enum(["none", "github", "google", "generic"]), | ||||||
|   backgroundImage: z.string(), |   backgroundImage: z.string(), | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								go.mod
									
									
									
									
									
								
							| @@ -1,6 +1,8 @@ | |||||||
| module tinyauth | module tinyauth | ||||||
|  |  | ||||||
| go 1.23.2 | go 1.24.0 | ||||||
|  |  | ||||||
|  | toolchain go1.24.3 | ||||||
|  |  | ||||||
| require ( | require ( | ||||||
| 	github.com/cenkalti/backoff/v5 v5.0.3 | 	github.com/cenkalti/backoff/v5 v5.0.3 | ||||||
| @@ -15,7 +17,8 @@ require ( | |||||||
| 	github.com/spf13/cobra v1.9.1 | 	github.com/spf13/cobra v1.9.1 | ||||||
| 	github.com/spf13/viper v1.20.1 | 	github.com/spf13/viper v1.20.1 | ||||||
| 	github.com/traefik/paerser v0.2.2 | 	github.com/traefik/paerser v0.2.2 | ||||||
| 	golang.org/x/crypto v0.41.0 | 	github.com/weppos/publicsuffix-go v0.50.0 | ||||||
|  | 	golang.org/x/crypto v0.42.0 | ||||||
| 	golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b | 	golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b | ||||||
| 	gorm.io/gorm v1.30.1 | 	gorm.io/gorm v1.30.1 | ||||||
| 	gotest.tools/v3 v3.5.2 | 	gotest.tools/v3 v3.5.2 | ||||||
| @@ -45,7 +48,7 @@ require ( | |||||||
| 	go.opentelemetry.io/auto/sdk v1.1.0 // indirect | 	go.opentelemetry.io/auto/sdk v1.1.0 // indirect | ||||||
| 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect | 	go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect | ||||||
| 	go.opentelemetry.io/otel/sdk v1.34.0 // indirect | 	go.opentelemetry.io/otel/sdk v1.34.0 // indirect | ||||||
| 	golang.org/x/term v0.34.0 // indirect | 	golang.org/x/term v0.35.0 // indirect | ||||||
| 	modernc.org/libc v1.66.3 // indirect | 	modernc.org/libc v1.66.3 // indirect | ||||||
| 	modernc.org/mathutil v1.7.1 // indirect | 	modernc.org/mathutil v1.7.1 // indirect | ||||||
| 	modernc.org/memory v1.11.0 // indirect | 	modernc.org/memory v1.11.0 // indirect | ||||||
| @@ -123,11 +126,11 @@ require ( | |||||||
| 	go.uber.org/atomic v1.9.0 // indirect | 	go.uber.org/atomic v1.9.0 // indirect | ||||||
| 	go.uber.org/multierr v1.9.0 // indirect | 	go.uber.org/multierr v1.9.0 // indirect | ||||||
| 	golang.org/x/arch v0.13.0 // indirect | 	golang.org/x/arch v0.13.0 // indirect | ||||||
| 	golang.org/x/net v0.42.0 // indirect | 	golang.org/x/net v0.44.0 // indirect | ||||||
| 	golang.org/x/oauth2 v0.30.0 | 	golang.org/x/oauth2 v0.30.0 | ||||||
| 	golang.org/x/sync v0.16.0 // indirect | 	golang.org/x/sync v0.17.0 // indirect | ||||||
| 	golang.org/x/sys v0.35.0 // indirect | 	golang.org/x/sys v0.36.0 // indirect | ||||||
| 	golang.org/x/text v0.28.0 // indirect | 	golang.org/x/text v0.29.0 // indirect | ||||||
| 	google.golang.org/protobuf v1.36.3 // indirect | 	google.golang.org/protobuf v1.36.3 // indirect | ||||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								go.sum
									
									
									
									
									
								
							| @@ -280,6 +280,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS | |||||||
| github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= | github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= | ||||||
| github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= | github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= | ||||||
| github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= | github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= | ||||||
|  | github.com/weppos/publicsuffix-go v0.50.0 h1:M178k6l8cnh9T1c1cStkhytVxdk5zPd6gGZf8ySIuVo= | ||||||
|  | github.com/weppos/publicsuffix-go v0.50.0/go.mod h1:VXhClBYMlDrUsome4pOTpe68Ui0p6iQRAbyHQD1yKoU= | ||||||
| github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= | github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= | ||||||
| github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= | github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= | ||||||
| github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||||
| @@ -311,27 +313,27 @@ golang.org/x/arch v0.13.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= | |||||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||||
| golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||||
| golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||||
| golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= | golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= | ||||||
| golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= | golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= | ||||||
| golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= | golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= | ||||||
| golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= | golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= | ||||||
| golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||||
| golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||||
| golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= | golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= | ||||||
| golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= | golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= | ||||||
| golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||||
| golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||||
| golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||||
| golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||||||
| golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= | golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= | ||||||
| golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= | golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= | ||||||
| golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= | golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= | ||||||
| golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= | golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= | ||||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= | golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= | ||||||
| golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= | golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| @@ -339,22 +341,22 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc | |||||||
| golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
| golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
| golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
| golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= | golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= | ||||||
| golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= | golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= | ||||||
| golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= | golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= | ||||||
| golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= | golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||||
| golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= | golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= | ||||||
| golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= | golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= | ||||||
| golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= | golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= | ||||||
| golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= | golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= | ||||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||||
| golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||||
| golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | ||||||
| golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||||||
| golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= | golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= | ||||||
| golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= | golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= | ||||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
|   | |||||||
| @@ -45,8 +45,8 @@ func (app *BootstrapApp) Setup() error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Get root domain | 	// Get cookie domain | ||||||
| 	rootDomain, err := utils.GetRootDomain(app.Config.AppURL) | 	cookieDomain, err := utils.GetCookieDomain(app.Config.AppURL) | ||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| @@ -65,7 +65,7 @@ func (app *BootstrapApp) Setup() error { | |||||||
| 		OauthWhitelist:    app.Config.OAuthWhitelist, | 		OauthWhitelist:    app.Config.OAuthWhitelist, | ||||||
| 		SessionExpiry:     app.Config.SessionExpiry, | 		SessionExpiry:     app.Config.SessionExpiry, | ||||||
| 		SecureCookie:      app.Config.SecureCookie, | 		SecureCookie:      app.Config.SecureCookie, | ||||||
| 		RootDomain:        rootDomain, | 		CookieDomain:      cookieDomain, | ||||||
| 		LoginTimeout:      app.Config.LoginTimeout, | 		LoginTimeout:      app.Config.LoginTimeout, | ||||||
| 		LoginMaxRetries:   app.Config.LoginMaxRetries, | 		LoginMaxRetries:   app.Config.LoginMaxRetries, | ||||||
| 		SessionCookieName: sessionCookieName, | 		SessionCookieName: sessionCookieName, | ||||||
| @@ -156,7 +156,7 @@ func (app *BootstrapApp) Setup() error { | |||||||
| 	var middlewares []Middleware | 	var middlewares []Middleware | ||||||
|  |  | ||||||
| 	contextMiddleware := middleware.NewContextMiddleware(middleware.ContextMiddlewareConfig{ | 	contextMiddleware := middleware.NewContextMiddleware(middleware.ContextMiddlewareConfig{ | ||||||
| 		RootDomain: rootDomain, | 		CookieDomain: cookieDomain, | ||||||
| 	}, authService, oauthBrokerService) | 	}, authService, oauthBrokerService) | ||||||
|  |  | ||||||
| 	uiMiddleware := middleware.NewUIMiddleware() | 	uiMiddleware := middleware.NewUIMiddleware() | ||||||
| @@ -183,7 +183,6 @@ func (app *BootstrapApp) Setup() error { | |||||||
| 		Title:                 app.Config.Title, | 		Title:                 app.Config.Title, | ||||||
| 		GenericName:           app.Config.GenericName, | 		GenericName:           app.Config.GenericName, | ||||||
| 		AppURL:                app.Config.AppURL, | 		AppURL:                app.Config.AppURL, | ||||||
| 		RootDomain:            rootDomain, |  | ||||||
| 		ForgotPasswordMessage: app.Config.ForgotPasswordMessage, | 		ForgotPasswordMessage: app.Config.ForgotPasswordMessage, | ||||||
| 		BackgroundImage:       app.Config.BackgroundImage, | 		BackgroundImage:       app.Config.BackgroundImage, | ||||||
| 		OAuthAutoRedirect:     app.Config.OAuthAutoRedirect, | 		OAuthAutoRedirect:     app.Config.OAuthAutoRedirect, | ||||||
| @@ -194,7 +193,7 @@ func (app *BootstrapApp) Setup() error { | |||||||
| 		SecureCookie:       app.Config.SecureCookie, | 		SecureCookie:       app.Config.SecureCookie, | ||||||
| 		CSRFCookieName:     csrfCookieName, | 		CSRFCookieName:     csrfCookieName, | ||||||
| 		RedirectCookieName: redirectCookieName, | 		RedirectCookieName: redirectCookieName, | ||||||
| 		RootDomain:         rootDomain, | 		CookieDomain:       cookieDomain, | ||||||
| 	}, apiRouter, authService, oauthBrokerService) | 	}, apiRouter, authService, oauthBrokerService) | ||||||
|  |  | ||||||
| 	proxyController := controller.NewProxyController(controller.ProxyControllerConfig{ | 	proxyController := controller.NewProxyController(controller.ProxyControllerConfig{ | ||||||
| @@ -202,7 +201,7 @@ func (app *BootstrapApp) Setup() error { | |||||||
| 	}, apiRouter, dockerService, authService) | 	}, apiRouter, dockerService, authService) | ||||||
|  |  | ||||||
| 	userController := controller.NewUserController(controller.UserControllerConfig{ | 	userController := controller.NewUserController(controller.UserControllerConfig{ | ||||||
| 		RootDomain: rootDomain, | 		CookieDomain: cookieDomain, | ||||||
| 	}, apiRouter, authService) | 	}, apiRouter, authService) | ||||||
|  |  | ||||||
| 	resourcesController := controller.NewResourcesController(controller.ResourcesControllerConfig{ | 	resourcesController := controller.NewResourcesController(controller.ResourcesControllerConfig{ | ||||||
|   | |||||||
| @@ -28,7 +28,6 @@ type AppContextResponse struct { | |||||||
| 	Title                 string   `json:"title"` | 	Title                 string   `json:"title"` | ||||||
| 	GenericName           string   `json:"genericName"` | 	GenericName           string   `json:"genericName"` | ||||||
| 	AppURL                string   `json:"appUrl"` | 	AppURL                string   `json:"appUrl"` | ||||||
| 	RootDomain            string   `json:"rootDomain"` |  | ||||||
| 	ForgotPasswordMessage string   `json:"forgotPasswordMessage"` | 	ForgotPasswordMessage string   `json:"forgotPasswordMessage"` | ||||||
| 	BackgroundImage       string   `json:"backgroundImage"` | 	BackgroundImage       string   `json:"backgroundImage"` | ||||||
| 	OAuthAutoRedirect     string   `json:"oauthAutoRedirect"` | 	OAuthAutoRedirect     string   `json:"oauthAutoRedirect"` | ||||||
| @@ -39,7 +38,6 @@ type ContextControllerConfig struct { | |||||||
| 	Title                 string | 	Title                 string | ||||||
| 	GenericName           string | 	GenericName           string | ||||||
| 	AppURL                string | 	AppURL                string | ||||||
| 	RootDomain            string |  | ||||||
| 	ForgotPasswordMessage string | 	ForgotPasswordMessage string | ||||||
| 	BackgroundImage       string | 	BackgroundImage       string | ||||||
| 	OAuthAutoRedirect     string | 	OAuthAutoRedirect     string | ||||||
| @@ -100,7 +98,6 @@ func (controller *ContextController) appContextHandler(c *gin.Context) { | |||||||
| 		Title:                 controller.config.Title, | 		Title:                 controller.config.Title, | ||||||
| 		GenericName:           controller.config.GenericName, | 		GenericName:           controller.config.GenericName, | ||||||
| 		AppURL:                fmt.Sprintf("%s://%s", appUrl.Scheme, appUrl.Host), | 		AppURL:                fmt.Sprintf("%s://%s", appUrl.Scheme, appUrl.Host), | ||||||
| 		RootDomain:            controller.config.RootDomain, |  | ||||||
| 		ForgotPasswordMessage: controller.config.ForgotPasswordMessage, | 		ForgotPasswordMessage: controller.config.ForgotPasswordMessage, | ||||||
| 		BackgroundImage:       controller.config.BackgroundImage, | 		BackgroundImage:       controller.config.BackgroundImage, | ||||||
| 		OAuthAutoRedirect:     controller.config.OAuthAutoRedirect, | 		OAuthAutoRedirect:     controller.config.OAuthAutoRedirect, | ||||||
|   | |||||||
| @@ -16,7 +16,6 @@ var controllerCfg = controller.ContextControllerConfig{ | |||||||
| 	Title:                 "Test App", | 	Title:                 "Test App", | ||||||
| 	GenericName:           "Generic", | 	GenericName:           "Generic", | ||||||
| 	AppURL:                "http://localhost:8080", | 	AppURL:                "http://localhost:8080", | ||||||
| 	RootDomain:            "localhost", |  | ||||||
| 	ForgotPasswordMessage: "Contact admin to reset your password.", | 	ForgotPasswordMessage: "Contact admin to reset your password.", | ||||||
| 	BackgroundImage:       "/assets/bg.jpg", | 	BackgroundImage:       "/assets/bg.jpg", | ||||||
| 	OAuthAutoRedirect:     "google", | 	OAuthAutoRedirect:     "google", | ||||||
| @@ -62,7 +61,6 @@ func TestAppContextHandler(t *testing.T) { | |||||||
| 		Title:                 controllerCfg.Title, | 		Title:                 controllerCfg.Title, | ||||||
| 		GenericName:           controllerCfg.GenericName, | 		GenericName:           controllerCfg.GenericName, | ||||||
| 		AppURL:                controllerCfg.AppURL, | 		AppURL:                controllerCfg.AppURL, | ||||||
| 		RootDomain:            controllerCfg.RootDomain, |  | ||||||
| 		ForgotPasswordMessage: controllerCfg.ForgotPasswordMessage, | 		ForgotPasswordMessage: controllerCfg.ForgotPasswordMessage, | ||||||
| 		BackgroundImage:       controllerCfg.BackgroundImage, | 		BackgroundImage:       controllerCfg.BackgroundImage, | ||||||
| 		OAuthAutoRedirect:     controllerCfg.OAuthAutoRedirect, | 		OAuthAutoRedirect:     controllerCfg.OAuthAutoRedirect, | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ type OAuthControllerConfig struct { | |||||||
| 	RedirectCookieName string | 	RedirectCookieName string | ||||||
| 	SecureCookie       bool | 	SecureCookie       bool | ||||||
| 	AppURL             string | 	AppURL             string | ||||||
| 	RootDomain         string | 	CookieDomain       string | ||||||
| } | } | ||||||
|  |  | ||||||
| type OAuthController struct { | type OAuthController struct { | ||||||
| @@ -74,13 +74,13 @@ func (controller *OAuthController) oauthURLHandler(c *gin.Context) { | |||||||
|  |  | ||||||
| 	state := service.GenerateState() | 	state := service.GenerateState() | ||||||
| 	authURL := service.GetAuthURL(state) | 	authURL := service.GetAuthURL(state) | ||||||
| 	c.SetCookie(controller.config.CSRFCookieName, state, int(time.Hour.Seconds()), "/", fmt.Sprintf(".%s", controller.config.RootDomain), controller.config.SecureCookie, true) | 	c.SetCookie(controller.config.CSRFCookieName, state, int(time.Hour.Seconds()), "/", fmt.Sprintf(".%s", controller.config.CookieDomain), controller.config.SecureCookie, true) | ||||||
|  |  | ||||||
| 	redirectURI := c.Query("redirect_uri") | 	redirectURI := c.Query("redirect_uri") | ||||||
|  |  | ||||||
| 	if redirectURI != "" && utils.IsRedirectSafe(redirectURI, controller.config.RootDomain) { | 	if redirectURI != "" && utils.IsRedirectSafe(redirectURI, controller.config.CookieDomain) { | ||||||
| 		log.Debug().Msg("Setting redirect URI cookie") | 		log.Debug().Msg("Setting redirect URI cookie") | ||||||
| 		c.SetCookie(controller.config.RedirectCookieName, redirectURI, int(time.Hour.Seconds()), "/", fmt.Sprintf(".%s", controller.config.RootDomain), controller.config.SecureCookie, true) | 		c.SetCookie(controller.config.RedirectCookieName, redirectURI, int(time.Hour.Seconds()), "/", fmt.Sprintf(".%s", controller.config.CookieDomain), controller.config.SecureCookie, true) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	c.JSON(200, gin.H{ | 	c.JSON(200, gin.H{ | ||||||
| @@ -108,12 +108,12 @@ func (controller *OAuthController) oauthCallbackHandler(c *gin.Context) { | |||||||
|  |  | ||||||
| 	if err != nil || state != csrfCookie { | 	if err != nil || state != csrfCookie { | ||||||
| 		log.Warn().Err(err).Msg("CSRF token mismatch or cookie missing") | 		log.Warn().Err(err).Msg("CSRF token mismatch or cookie missing") | ||||||
| 		c.SetCookie(controller.config.CSRFCookieName, "", -1, "/", fmt.Sprintf(".%s", controller.config.RootDomain), controller.config.SecureCookie, true) | 		c.SetCookie(controller.config.CSRFCookieName, "", -1, "/", fmt.Sprintf(".%s", controller.config.CookieDomain), controller.config.SecureCookie, true) | ||||||
| 		c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/error", controller.config.AppURL)) | 		c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/error", controller.config.AppURL)) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	c.SetCookie(controller.config.CSRFCookieName, "", -1, "/", fmt.Sprintf(".%s", controller.config.RootDomain), controller.config.SecureCookie, true) | 	c.SetCookie(controller.config.CSRFCookieName, "", -1, "/", fmt.Sprintf(".%s", controller.config.CookieDomain), controller.config.SecureCookie, true) | ||||||
|  |  | ||||||
| 	code := c.Query("code") | 	code := c.Query("code") | ||||||
| 	service, exists := controller.broker.GetService(req.Provider) | 	service, exists := controller.broker.GetService(req.Provider) | ||||||
| @@ -196,7 +196,7 @@ func (controller *OAuthController) oauthCallbackHandler(c *gin.Context) { | |||||||
|  |  | ||||||
| 	redirectURI, err := c.Cookie(controller.config.RedirectCookieName) | 	redirectURI, err := c.Cookie(controller.config.RedirectCookieName) | ||||||
|  |  | ||||||
| 	if err != nil || !utils.IsRedirectSafe(redirectURI, controller.config.RootDomain) { | 	if err != nil || !utils.IsRedirectSafe(redirectURI, controller.config.CookieDomain) { | ||||||
| 		log.Debug().Msg("No redirect URI cookie found, redirecting to app root") | 		log.Debug().Msg("No redirect URI cookie found, redirecting to app root") | ||||||
| 		c.Redirect(http.StatusTemporaryRedirect, controller.config.AppURL) | 		c.Redirect(http.StatusTemporaryRedirect, controller.config.AppURL) | ||||||
| 		return | 		return | ||||||
| @@ -212,6 +212,6 @@ func (controller *OAuthController) oauthCallbackHandler(c *gin.Context) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	c.SetCookie(controller.config.RedirectCookieName, "", -1, "/", fmt.Sprintf(".%s", controller.config.RootDomain), controller.config.SecureCookie, true) | 	c.SetCookie(controller.config.RedirectCookieName, "", -1, "/", fmt.Sprintf(".%s", controller.config.CookieDomain), controller.config.SecureCookie, true) | ||||||
| 	c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/continue?%s", controller.config.AppURL, queries.Encode())) | 	c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/continue?%s", controller.config.AppURL, queries.Encode())) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -50,7 +50,7 @@ func setupProxyController(t *testing.T, middlewares *[]gin.HandlerFunc) (*gin.En | |||||||
| 		OauthWhitelist:    "", | 		OauthWhitelist:    "", | ||||||
| 		SessionExpiry:     3600, | 		SessionExpiry:     3600, | ||||||
| 		SecureCookie:      false, | 		SecureCookie:      false, | ||||||
| 		RootDomain:        "localhost", | 		CookieDomain:      "localhost", | ||||||
| 		LoginTimeout:      300, | 		LoginTimeout:      300, | ||||||
| 		LoginMaxRetries:   3, | 		LoginMaxRetries:   3, | ||||||
| 		SessionCookieName: "tinyauth-session", | 		SessionCookieName: "tinyauth-session", | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ func TestResourcesHandler(t *testing.T) { | |||||||
| 	// Create test data | 	// Create test data | ||||||
| 	err := os.Mkdir("/tmp/tinyauth", 0755) | 	err := os.Mkdir("/tmp/tinyauth", 0755) | ||||||
| 	assert.NilError(t, err) | 	assert.NilError(t, err) | ||||||
|  | 	defer os.RemoveAll("/tmp/tinyauth") | ||||||
|  |  | ||||||
| 	file, err := os.Create("/tmp/tinyauth/test.txt") | 	file, err := os.Create("/tmp/tinyauth/test.txt") | ||||||
| 	assert.NilError(t, err) | 	assert.NilError(t, err) | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ type TotpRequest struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type UserControllerConfig struct { | type UserControllerConfig struct { | ||||||
| 	RootDomain string | 	CookieDomain string | ||||||
| } | } | ||||||
|  |  | ||||||
| type UserController struct { | type UserController struct { | ||||||
| @@ -115,7 +115,7 @@ func (controller *UserController) loginHandler(c *gin.Context) { | |||||||
| 			err := controller.auth.CreateSessionCookie(c, &config.SessionCookie{ | 			err := controller.auth.CreateSessionCookie(c, &config.SessionCookie{ | ||||||
| 				Username:    user.Username, | 				Username:    user.Username, | ||||||
| 				Name:        utils.Capitalize(req.Username), | 				Name:        utils.Capitalize(req.Username), | ||||||
| 				Email:       fmt.Sprintf("%s@%s", strings.ToLower(req.Username), controller.config.RootDomain), | 				Email:       fmt.Sprintf("%s@%s", strings.ToLower(req.Username), controller.config.CookieDomain), | ||||||
| 				Provider:    "username", | 				Provider:    "username", | ||||||
| 				TotpPending: true, | 				TotpPending: true, | ||||||
| 			}) | 			}) | ||||||
| @@ -141,7 +141,7 @@ func (controller *UserController) loginHandler(c *gin.Context) { | |||||||
| 	err = controller.auth.CreateSessionCookie(c, &config.SessionCookie{ | 	err = controller.auth.CreateSessionCookie(c, &config.SessionCookie{ | ||||||
| 		Username: req.Username, | 		Username: req.Username, | ||||||
| 		Name:     utils.Capitalize(req.Username), | 		Name:     utils.Capitalize(req.Username), | ||||||
| 		Email:    fmt.Sprintf("%s@%s", strings.ToLower(req.Username), controller.config.RootDomain), | 		Email:    fmt.Sprintf("%s@%s", strings.ToLower(req.Username), controller.config.CookieDomain), | ||||||
| 		Provider: "username", | 		Provider: "username", | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| @@ -246,7 +246,7 @@ func (controller *UserController) totpHandler(c *gin.Context) { | |||||||
| 	err = controller.auth.CreateSessionCookie(c, &config.SessionCookie{ | 	err = controller.auth.CreateSessionCookie(c, &config.SessionCookie{ | ||||||
| 		Username: user.Username, | 		Username: user.Username, | ||||||
| 		Name:     utils.Capitalize(user.Username), | 		Name:     utils.Capitalize(user.Username), | ||||||
| 		Email:    fmt.Sprintf("%s@%s", strings.ToLower(user.Username), controller.config.RootDomain), | 		Email:    fmt.Sprintf("%s@%s", strings.ToLower(user.Username), controller.config.CookieDomain), | ||||||
| 		Provider: "username", | 		Provider: "username", | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ func setupUserController(t *testing.T, middlewares *[]gin.HandlerFunc) (*gin.Eng | |||||||
| 		OauthWhitelist:    "", | 		OauthWhitelist:    "", | ||||||
| 		SessionExpiry:     3600, | 		SessionExpiry:     3600, | ||||||
| 		SecureCookie:      false, | 		SecureCookie:      false, | ||||||
| 		RootDomain:        "localhost", | 		CookieDomain:      "localhost", | ||||||
| 		LoginTimeout:      300, | 		LoginTimeout:      300, | ||||||
| 		LoginMaxRetries:   3, | 		LoginMaxRetries:   3, | ||||||
| 		SessionCookieName: "tinyauth-session", | 		SessionCookieName: "tinyauth-session", | ||||||
| @@ -66,7 +66,7 @@ func setupUserController(t *testing.T, middlewares *[]gin.HandlerFunc) (*gin.Eng | |||||||
|  |  | ||||||
| 	// Controller | 	// Controller | ||||||
| 	ctrl := controller.NewUserController(controller.UserControllerConfig{ | 	ctrl := controller.NewUserController(controller.UserControllerConfig{ | ||||||
| 		RootDomain: "localhost", | 		CookieDomain: "localhost", | ||||||
| 	}, group, authService) | 	}, group, authService) | ||||||
| 	ctrl.SetupRoutes() | 	ctrl.SetupRoutes() | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type ContextMiddlewareConfig struct { | type ContextMiddlewareConfig struct { | ||||||
| 	RootDomain string | 	CookieDomain string | ||||||
| } | } | ||||||
|  |  | ||||||
| type ContextMiddleware struct { | type ContextMiddleware struct { | ||||||
| @@ -134,7 +134,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc { | |||||||
| 			c.Set("context", &config.UserContext{ | 			c.Set("context", &config.UserContext{ | ||||||
| 				Username:    user.Username, | 				Username:    user.Username, | ||||||
| 				Name:        utils.Capitalize(user.Username), | 				Name:        utils.Capitalize(user.Username), | ||||||
| 				Email:       fmt.Sprintf("%s@%s", strings.ToLower(user.Username), m.config.RootDomain), | 				Email:       fmt.Sprintf("%s@%s", strings.ToLower(user.Username), m.config.CookieDomain), | ||||||
| 				Provider:    "basic", | 				Provider:    "basic", | ||||||
| 				IsLoggedIn:  true, | 				IsLoggedIn:  true, | ||||||
| 				TotpEnabled: user.TotpSecret != "", | 				TotpEnabled: user.TotpSecret != "", | ||||||
| @@ -146,7 +146,7 @@ func (m *ContextMiddleware) Middleware() gin.HandlerFunc { | |||||||
| 			c.Set("context", &config.UserContext{ | 			c.Set("context", &config.UserContext{ | ||||||
| 				Username:   basic.Username, | 				Username:   basic.Username, | ||||||
| 				Name:       utils.Capitalize(basic.Username), | 				Name:       utils.Capitalize(basic.Username), | ||||||
| 				Email:      fmt.Sprintf("%s@%s", strings.ToLower(basic.Username), m.config.RootDomain), | 				Email:      fmt.Sprintf("%s@%s", strings.ToLower(basic.Username), m.config.CookieDomain), | ||||||
| 				Provider:   "basic", | 				Provider:   "basic", | ||||||
| 				IsLoggedIn: true, | 				IsLoggedIn: true, | ||||||
| 			}) | 			}) | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ type AuthServiceConfig struct { | |||||||
| 	OauthWhitelist    string | 	OauthWhitelist    string | ||||||
| 	SessionExpiry     int | 	SessionExpiry     int | ||||||
| 	SecureCookie      bool | 	SecureCookie      bool | ||||||
| 	RootDomain        string | 	CookieDomain      string | ||||||
| 	LoginTimeout      int | 	LoginTimeout      int | ||||||
| 	LoginMaxRetries   int | 	LoginMaxRetries   int | ||||||
| 	SessionCookieName string | 	SessionCookieName string | ||||||
| @@ -218,7 +218,7 @@ func (auth *AuthService) CreateSessionCookie(c *gin.Context, data *config.Sessio | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	c.SetCookie(auth.config.SessionCookieName, session.UUID, expiry, "/", fmt.Sprintf(".%s", auth.config.RootDomain), auth.config.SecureCookie, true) | 	c.SetCookie(auth.config.SessionCookieName, session.UUID, expiry, "/", fmt.Sprintf(".%s", auth.config.CookieDomain), auth.config.SecureCookie, true) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -236,7 +236,7 @@ func (auth *AuthService) DeleteSessionCookie(c *gin.Context) error { | |||||||
| 		return res.Error | 		return res.Error | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	c.SetCookie(auth.config.SessionCookieName, "", -1, "/", fmt.Sprintf(".%s", auth.config.RootDomain), auth.config.SecureCookie, true) | 	c.SetCookie(auth.config.SessionCookieName, "", -1, "/", fmt.Sprintf(".%s", auth.config.CookieDomain), auth.config.SecureCookie, true) | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,30 +8,38 @@ import ( | |||||||
| 	"tinyauth/internal/config" | 	"tinyauth/internal/config" | ||||||
|  |  | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
|  |  | ||||||
| 	"github.com/rs/zerolog" | 	"github.com/rs/zerolog" | ||||||
|  | 	"github.com/weppos/publicsuffix-go/publicsuffix" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Get root domain parses a hostname and returns the upper domain (e.g. sub1.sub2.domain.com -> sub2.domain.com) | // Get cookie domain parses a hostname and returns the upper domain (e.g. sub1.sub2.domain.com -> sub2.domain.com) | ||||||
| func GetRootDomain(u string) (string, error) { | func GetCookieDomain(u string) (string, error) { | ||||||
| 	appUrl, err := url.Parse(u) | 	parsed, err := url.Parse(u) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return "", err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	host := appUrl.Hostname() | 	host := parsed.Hostname() | ||||||
|  |  | ||||||
| 	if netIP := net.ParseIP(host); netIP != nil { | 	if netIP := net.ParseIP(host); netIP != nil { | ||||||
| 		return "", errors.New("IP addresses are not allowed") | 		return "", errors.New("IP addresses not allowed") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	urlParts := strings.Split(host, ".") | 	parts := strings.Split(host, ".") | ||||||
|  |  | ||||||
| 	if len(urlParts) < 3 { | 	if len(parts) < 3 { | ||||||
| 		return "", errors.New("invalid domain, must be at least second level domain") | 		return "", errors.New("invalid app url, must be at least second level domain") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return strings.Join(urlParts[1:], "."), nil | 	domain := strings.Join(parts[1:], ".") | ||||||
|  |  | ||||||
|  | 	_, err = publicsuffix.DomainFromListWithOptions(publicsuffix.DefaultList, domain, nil) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", errors.New("domain in public suffix list, cannot set cookies") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return domain, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func ParseFileToLine(content string) string { | func ParseFileToLine(content string) string { | ||||||
| @@ -89,13 +97,13 @@ func IsRedirectSafe(redirectURL string, domain string) bool { | |||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	upper, err := GetRootDomain(redirectURL) | 	cookieDomain, err := GetCookieDomain(redirectURL) | ||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if upper != domain { | 	if cookieDomain != domain { | ||||||
| 		return false | 		return false | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,53 +11,58 @@ import ( | |||||||
|  |  | ||||||
| func TestGetRootDomain(t *testing.T) { | func TestGetRootDomain(t *testing.T) { | ||||||
| 	// Normal case | 	// Normal case | ||||||
| 	domain := "http://sub.example.com" | 	domain := "http://sub.tinyauth.app" | ||||||
| 	expected := "example.com" | 	expected := "tinyauth.app" | ||||||
| 	result, err := utils.GetRootDomain(domain) | 	result, err := utils.GetCookieDomain(domain) | ||||||
| 	assert.NilError(t, err) | 	assert.NilError(t, err) | ||||||
| 	assert.Equal(t, expected, result) | 	assert.Equal(t, expected, result) | ||||||
|  |  | ||||||
| 	// Domain with multiple subdomains | 	// Domain with multiple subdomains | ||||||
| 	domain = "http://b.c.example.com" | 	domain = "http://b.c.tinyauth.app" | ||||||
| 	expected = "c.example.com" | 	expected = "c.tinyauth.app" | ||||||
| 	result, err = utils.GetRootDomain(domain) | 	result, err = utils.GetCookieDomain(domain) | ||||||
| 	assert.NilError(t, err) | 	assert.NilError(t, err) | ||||||
| 	assert.Equal(t, expected, result) | 	assert.Equal(t, expected, result) | ||||||
|  |  | ||||||
| 	// Domain with no subdomain | 	// Domain with no subdomain | ||||||
| 	domain = "http://example.com" | 	domain = "http://tinyauth.app" | ||||||
| 	expected = "example.com" | 	expected = "tinyauth.app" | ||||||
| 	_, err = utils.GetRootDomain(domain) | 	_, err = utils.GetCookieDomain(domain) | ||||||
| 	assert.Error(t, err, "invalid domain, must be at least second level domain") | 	assert.Error(t, err, "invalid app url, must be at least second level domain") | ||||||
|  |  | ||||||
| 	// Invalid domain (only TLD) | 	// Invalid domain (only TLD) | ||||||
| 	domain = "com" | 	domain = "com" | ||||||
| 	_, err = utils.GetRootDomain(domain) | 	_, err = utils.GetCookieDomain(domain) | ||||||
| 	assert.ErrorContains(t, err, "invalid domain") | 	assert.ErrorContains(t, err, "invalid app url, must be at least second level domain") | ||||||
|  |  | ||||||
| 	// IP address | 	// IP address | ||||||
| 	domain = "http://10.10.10.10" | 	domain = "http://10.10.10.10" | ||||||
| 	_, err = utils.GetRootDomain(domain) | 	_, err = utils.GetCookieDomain(domain) | ||||||
| 	assert.ErrorContains(t, err, "IP addresses are not allowed") | 	assert.ErrorContains(t, err, "IP addresses not allowed") | ||||||
|  |  | ||||||
| 	// Invalid URL | 	// Invalid URL | ||||||
| 	domain = "http://[::1]:namedport" | 	domain = "http://[::1]:namedport" | ||||||
| 	_, err = utils.GetRootDomain(domain) | 	_, err = utils.GetCookieDomain(domain) | ||||||
| 	assert.ErrorContains(t, err, "parse \"http://[::1]:namedport\": invalid port \":namedport\" after host") | 	assert.ErrorContains(t, err, "parse \"http://[::1]:namedport\": invalid port \":namedport\" after host") | ||||||
|  |  | ||||||
| 	// URL with scheme and path | 	// URL with scheme and path | ||||||
| 	domain = "https://sub.example.com/path" | 	domain = "https://sub.tinyauth.app/path" | ||||||
| 	expected = "example.com" | 	expected = "tinyauth.app" | ||||||
| 	result, err = utils.GetRootDomain(domain) | 	result, err = utils.GetCookieDomain(domain) | ||||||
| 	assert.NilError(t, err) | 	assert.NilError(t, err) | ||||||
| 	assert.Equal(t, expected, result) | 	assert.Equal(t, expected, result) | ||||||
|  |  | ||||||
| 	// URL with port | 	// URL with port | ||||||
| 	domain = "http://sub.example.com:8080" | 	domain = "http://sub.tinyauth.app:8080" | ||||||
| 	expected = "example.com" | 	expected = "tinyauth.app" | ||||||
| 	result, err = utils.GetRootDomain(domain) | 	result, err = utils.GetCookieDomain(domain) | ||||||
| 	assert.NilError(t, err) | 	assert.NilError(t, err) | ||||||
| 	assert.Equal(t, expected, result) | 	assert.Equal(t, expected, result) | ||||||
|  |  | ||||||
|  | 	// Domain managed by ICANN | ||||||
|  | 	domain = "http://example.co.uk" | ||||||
|  | 	_, err = utils.GetCookieDomain(domain) | ||||||
|  | 	assert.Error(t, err, "domain in public suffix list, cannot set cookies") | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestParseFileToLine(t *testing.T) { | func TestParseFileToLine(t *testing.T) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Stavros
					Stavros