mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-31 14:15:50 +00:00 
			
		
		
		
	Compare commits
	
		
			7 Commits
		
	
	
		
			v2.0.0-alp
			...
			v2.0.2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 2385599c80 | ||
|   | 6f184856f1 | ||
|   | e2e3b3bdc6 | ||
|   | 3efcb26db1 | ||
|   | c54267f50d | ||
|   | 4de12ce5c1 | ||
|   | 0cf0aafc14 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -11,4 +11,5 @@ docker-compose.test.yml | ||||
| users.txt | ||||
|  | ||||
| # secret test file | ||||
| secret.txt | ||||
| secret.txt | ||||
| secret_oauth.txt | ||||
							
								
								
									
										35
									
								
								cmd/root.go
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								cmd/root.go
									
									
									
									
									
								
							| @@ -1,9 +1,12 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| 	cmd "tinyauth/cmd/user" | ||||
| 	"tinyauth/internal/api" | ||||
| 	"tinyauth/internal/assets" | ||||
| 	"tinyauth/internal/auth" | ||||
| 	"tinyauth/internal/hooks" | ||||
| 	"tinyauth/internal/providers" | ||||
| @@ -22,21 +25,28 @@ var rootCmd = &cobra.Command{ | ||||
| 	Short: "The simplest way to protect your apps with a login screen.", | ||||
| 	Long:  `Tinyauth is a simple authentication middleware that adds simple username/password login or OAuth with Google, Github and any generic OAuth provider to all of your docker apps.`, | ||||
| 	Run: func(cmd *cobra.Command, args []string) { | ||||
| 		// Logger | ||||
| 		log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger().Level(zerolog.FatalLevel) | ||||
|  | ||||
| 		// Get config | ||||
| 		log.Info().Msg("Parsing config") | ||||
| 		var config types.Config | ||||
| 		parseErr := viper.Unmarshal(&config) | ||||
| 		HandleError(parseErr, "Failed to parse config") | ||||
|  | ||||
| 		// Secrets | ||||
| 		config.Secret = utils.GetSecret(config.Secret, config.SecretFile) | ||||
| 		config.GithubClientSecret = utils.GetSecret(config.GithubClientSecret, config.GithubClientSecretFile) | ||||
| 		config.GoogleClientSecret = utils.GetSecret(config.GoogleClientSecret, config.GoogleClientSecretFile) | ||||
| 		config.GenericClientSecret = utils.GetSecret(config.GenericClientSecret, config.GenericClientSecretFile) | ||||
|  | ||||
| 		// Validate config | ||||
| 		log.Info().Msg("Validating config") | ||||
| 		validator := validator.New() | ||||
| 		validateErr := validator.Struct(config) | ||||
| 		HandleError(validateErr, "Invalid config") | ||||
| 		HandleError(validateErr, "Failed to validate config") | ||||
|  | ||||
| 		// Set log level | ||||
| 		log.Info().Int8("log_level", config.LogLevel).Msg("Setting log level") | ||||
| 		log.Logger = log.Logger.Level(zerolog.Level(config.LogLevel)) | ||||
| 		// Logger | ||||
| 		log.Logger = log.Level(zerolog.Level(config.LogLevel)) | ||||
| 		log.Info().Str("version", assets.Version).Msg("Starting tinyauth") | ||||
|  | ||||
| 		// Users | ||||
| 		log.Info().Msg("Parsing users") | ||||
| @@ -46,17 +56,9 @@ var rootCmd = &cobra.Command{ | ||||
| 			log.Fatal().Err(usersErr).Msg("Failed to parse users") | ||||
| 		} | ||||
|  | ||||
| 		// Secrets | ||||
| 		log.Info().Msg("Parsing secrets") | ||||
|  | ||||
| 		config.Secret = utils.GetSecret(config.Secret, config.SecretFile) | ||||
| 		config.GithubClientSecret = utils.GetSecret(config.GithubClientSecret, config.GithubClientSecretFile) | ||||
| 		config.GoogleClientSecret = utils.GetSecret(config.GoogleClientSecret, config.GoogleClientSecretFile) | ||||
| 		config.GenericClientSecret = utils.GetSecret(config.GenericClientSecret, config.GenericClientSecretFile) | ||||
|  | ||||
| 		// Create oauth whitelist | ||||
| 		oauthWhitelist := strings.Split(config.OAuthWhitelist, ",") | ||||
| 		log.Debug().Strs("oauth_whitelist", oauthWhitelist).Msg("Parsed OAuth whitelist") | ||||
| 		log.Debug().Msg("Parsed OAuth whitelist") | ||||
|  | ||||
| 		// Create OAuth config | ||||
| 		oauthConfig := types.OAuthConfig{ | ||||
| @@ -72,7 +74,8 @@ var rootCmd = &cobra.Command{ | ||||
| 			GenericUserURL:      config.GenericUserURL, | ||||
| 			AppURL:              config.AppURL, | ||||
| 		} | ||||
| 		log.Debug().Interface("oauth_config", oauthConfig).Msg("Parsed OAuth config") | ||||
|  | ||||
| 		log.Debug().Msg("Parsed OAuth config") | ||||
|  | ||||
| 		// Create auth service | ||||
| 		auth := auth.NewAuth(users, oauthWhitelist) | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/charmbracelet/huh" | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| 	"github.com/spf13/cobra" | ||||
| 	"golang.org/x/crypto/bcrypt" | ||||
| @@ -21,6 +22,8 @@ var CreateCmd = &cobra.Command{ | ||||
| 	Short: "Create a user", | ||||
| 	Long:  `Create a user either interactively or by passing flags.`, | ||||
| 	Run: func(cmd *cobra.Command, args []string) { | ||||
| 		log.Logger = log.Level(zerolog.InfoLevel) | ||||
|  | ||||
| 		if interactive { | ||||
| 			form := huh.NewForm( | ||||
| 				huh.NewGroup( | ||||
|   | ||||
| @@ -8,12 +8,17 @@ import ( | ||||
| ) | ||||
|  | ||||
| func UserCmd() *cobra.Command { | ||||
| 	// Create the user command | ||||
| 	userCmd := &cobra.Command{ | ||||
| 		Use:  "user", | ||||
| 		Use:   "user", | ||||
| 		Short: "User utilities", | ||||
| 		Long: `Utilities for creating and verifying tinyauth compatible users.`, | ||||
| 		Long:  `Utilities for creating and verifying tinyauth compatible users.`, | ||||
| 	} | ||||
|  | ||||
| 	// Add subcommands | ||||
| 	userCmd.AddCommand(create.CreateCmd) | ||||
| 	userCmd.AddCommand(verify.VerifyCmd) | ||||
|  | ||||
| 	// Return the user command | ||||
| 	return userCmd | ||||
| }	 | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/charmbracelet/huh" | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| 	"github.com/spf13/cobra" | ||||
| 	"golang.org/x/crypto/bcrypt" | ||||
| @@ -21,6 +22,8 @@ var VerifyCmd = &cobra.Command{ | ||||
| 	Short: "Verify a user is set up correctly", | ||||
| 	Long:  `Verify a user is set up correctly meaning that it has a correct username and password.`, | ||||
| 	Run: func(cmd *cobra.Command, args []string) { | ||||
| 		log.Logger = log.Level(zerolog.InfoLevel) | ||||
|  | ||||
| 		if interactive { | ||||
| 			form := huh.NewForm( | ||||
| 				huh.NewGroup( | ||||
|   | ||||
| @@ -114,7 +114,7 @@ func (api *API) SetupRoutes() { | ||||
| 			RedirectURI: fmt.Sprintf("%s://%s%s", proto, host, uri), | ||||
| 		}) | ||||
|  | ||||
| 		log.Debug().Interface("queries", queries).Msg("Redirecting to login") | ||||
| 		log.Debug().Interface("redirect_uri", fmt.Sprintf("%s://%s%s", proto, host, uri)).Msg("Redirecting to login") | ||||
|  | ||||
| 		if queryErr != nil { | ||||
| 			log.Error().Err(queryErr).Msg("Failed to build query") | ||||
| @@ -142,7 +142,7 @@ func (api *API) SetupRoutes() { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		log.Debug().Interface("login", login).Msg("Got login request") | ||||
| 		log.Debug().Msg("Got login request") | ||||
|  | ||||
| 		user := api.Auth.GetUser(login.Username) | ||||
|  | ||||
| @@ -250,7 +250,7 @@ func (api *API) SetupRoutes() { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		log.Debug().Interface("request", request).Msg("Got OAuth request") | ||||
| 		log.Debug().Msg("Got OAuth request") | ||||
|  | ||||
| 		provider := api.Providers.GetProvider(request.Provider) | ||||
|  | ||||
| @@ -266,7 +266,7 @@ func (api *API) SetupRoutes() { | ||||
|  | ||||
| 		authURL := provider.GetAuthURL() | ||||
|  | ||||
| 		log.Debug().Str("authURL", authURL).Msg("Got auth URL") | ||||
| 		log.Debug().Msg("Got auth URL") | ||||
|  | ||||
| 		redirectURI := c.Query("redirect_uri") | ||||
|  | ||||
| @@ -291,7 +291,7 @@ func (api *API) SetupRoutes() { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		log.Debug().Interface("providerName", providerName).Msg("Got provider name") | ||||
| 		log.Debug().Interface("provider", providerName.Provider).Msg("Got provider name") | ||||
|  | ||||
| 		code := c.Query("code") | ||||
|  | ||||
| @@ -301,7 +301,7 @@ func (api *API) SetupRoutes() { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		log.Debug().Str("code", code).Msg("Got code") | ||||
| 		log.Debug().Msg("Got code") | ||||
|  | ||||
| 		provider := api.Providers.GetProvider(providerName.Provider) | ||||
|  | ||||
| @@ -312,9 +312,9 @@ func (api *API) SetupRoutes() { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		token, tokenErr := provider.ExchangeToken(code) | ||||
| 		_, tokenErr := provider.ExchangeToken(code) | ||||
|  | ||||
| 		log.Debug().Str("token", token).Msg("Got token") | ||||
| 		log.Debug().Msg("Got token") | ||||
|  | ||||
| 		if handleApiError(c, "Failed to exchange token", tokenErr) { | ||||
| 			return | ||||
| @@ -363,7 +363,7 @@ func (api *API) SetupRoutes() { | ||||
| 			RedirectURI: redirectURI, | ||||
| 		}) | ||||
|  | ||||
| 		log.Debug().Interface("redirectQuery", redirectQuery).Msg("Got redirect query") | ||||
| 		log.Debug().Msg("Got redirect query") | ||||
|  | ||||
| 		if handleApiError(c, "Failed to build query", redirectQueryErr) { | ||||
| 			return | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| v2.0.0 | ||||
| v2.0.2 | ||||
| @@ -50,7 +50,7 @@ func (auth *Auth) EmailWhitelisted(emailSrc string) bool { | ||||
| func (auth *Auth) CreateSessionCookie(c *gin.Context, data *types.SessionCookie) { | ||||
| 	log.Debug().Msg("Creating session cookie") | ||||
| 	sessions := sessions.Default(c) | ||||
| 	log.Debug().Interface("data", data).Msg("Setting session cookie") | ||||
| 	log.Debug().Msg("Setting session cookie") | ||||
| 	sessions.Set("username", data.Username) | ||||
| 	sessions.Set("provider", data.Provider) | ||||
| 	sessions.Save() | ||||
| @@ -70,13 +70,10 @@ func (auth *Auth) GetSessionCookie(c *gin.Context) (types.SessionCookie, error) | ||||
| 	cookieUsername := sessions.Get("username") | ||||
| 	cookieProvider := sessions.Get("provider") | ||||
|  | ||||
| 	log.Debug().Interface("cookieUsername", cookieUsername).Msg("Got username") | ||||
| 	log.Debug().Interface("cookieProvider", cookieProvider).Msg("Got provider") | ||||
|  | ||||
| 	username, usernameOk := cookieUsername.(string) | ||||
| 	provider, providerOk := cookieProvider.(string) | ||||
|  | ||||
| 	log.Debug().Str("username", username).Bool("usernameOk", usernameOk).Str("provider", provider).Bool("providerOk", providerOk).Msg("Parsed cookie") | ||||
| 	log.Debug().Str("username", username).Str("provider", provider).Msg("Parsed cookie") | ||||
|  | ||||
| 	if !usernameOk || !providerOk { | ||||
| 		log.Warn().Msg("Session cookie invalid") | ||||
|   | ||||
| @@ -34,8 +34,6 @@ func (hooks *Hooks) UseUserContext(c *gin.Context) types.UserContext { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	log.Debug().Interface("cookie", cookie).Msg("Got session cookie") | ||||
|  | ||||
| 	if cookie.Provider == "username" { | ||||
| 		log.Debug().Msg("Provider is username") | ||||
| 		if hooks.Auth.GetUser(cookie.Username) != nil { | ||||
| @@ -55,7 +53,7 @@ func (hooks *Hooks) UseUserContext(c *gin.Context) types.UserContext { | ||||
| 	if provider != nil { | ||||
| 		log.Debug().Msg("Provider exists") | ||||
| 		if !hooks.Auth.EmailWhitelisted(cookie.Username) { | ||||
| 			log.Error().Msgf("Email %s not whitelisted", cookie.Username) | ||||
| 			log.Error().Str("email", cookie.Username).Msg("Email is not whitelisted") | ||||
| 			hooks.Auth.DeleteSessionCookie(c) | ||||
| 			return types.UserContext{ | ||||
| 				Username:   "", | ||||
| @@ -73,7 +71,6 @@ func (hooks *Hooks) UseUserContext(c *gin.Context) types.UserContext { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	log.Error().Msg("Provider does not exist") | ||||
| 	return types.UserContext{ | ||||
| 		Username:   "", | ||||
| 		IsLoggedIn: false, | ||||
|   | ||||
| @@ -37,7 +37,7 @@ func GetGenericEmail(client *http.Client, url string) (string, error) { | ||||
| 		return "", jsonErr | ||||
| 	} | ||||
|  | ||||
| 	log.Debug().Interface("user", user).Msg("Parsed user from generic provider") | ||||
| 	log.Debug().Msg("Parsed user from generic provider") | ||||
|  | ||||
| 	return user.Email, nil | ||||
| } | ||||
|   | ||||
| @@ -43,7 +43,7 @@ func GetGithubEmail(client *http.Client) (string, error) { | ||||
| 		return "", jsonErr | ||||
| 	} | ||||
|  | ||||
| 	log.Debug().Interface("emails", emails).Msg("Parsed emails from github") | ||||
| 	log.Debug().Msg("Parsed emails from github") | ||||
|  | ||||
| 	for _, email := range emails { | ||||
| 		if email.Primary { | ||||
|   | ||||
| @@ -41,7 +41,7 @@ func GetGoogleEmail(client *http.Client) (string, error) { | ||||
| 		return "", jsonErr | ||||
| 	} | ||||
|  | ||||
| 	log.Debug().Interface("user", user).Msg("Parsed user from google") | ||||
| 	log.Debug().Msg("Parsed user from google") | ||||
|  | ||||
| 	return user.Email, nil | ||||
| } | ||||
|   | ||||
| @@ -19,8 +19,8 @@ type User struct { | ||||
| type Users []User | ||||
|  | ||||
| type Config struct { | ||||
| 	Port                    int    `validate:"number" mapstructure:"port"` | ||||
| 	Address                 string `mapstructure:"address, ip4_addr"` | ||||
| 	Port                    int    `mapstructure:"port" validate:"required"` | ||||
| 	Address                 string `validate:"required,ip4_addr" mapstructure:"address"` | ||||
| 	Secret                  string `validate:"required,len=32" mapstructure:"secret"` | ||||
| 	SecretFile              string `mapstructure:"secret-file"` | ||||
| 	AppURL                  string `validate:"required,url" mapstructure:"app-url"` | ||||
| @@ -43,7 +43,7 @@ type Config struct { | ||||
| 	DisableContinue         bool   `mapstructure:"disable-continue"` | ||||
| 	OAuthWhitelist          string `mapstructure:"oauth-whitelist"` | ||||
| 	CookieExpiry            int    `mapstructure:"cookie-expiry"` | ||||
| 	LogLevel                int8   `mapstructure:"log-level"` | ||||
| 	LogLevel                int8   `mapstructure:"log-level" validate:"min=-1,max=5"` | ||||
| } | ||||
|  | ||||
| type UserContext struct { | ||||
|   | ||||
| @@ -15,15 +15,12 @@ func ParseUsers(users string) (types.Users, error) { | ||||
| 	var usersParsed types.Users | ||||
| 	userList := strings.Split(users, ",") | ||||
|  | ||||
| 	log.Debug().Strs("users", userList).Msg("Splitted users") | ||||
|  | ||||
| 	if len(userList) == 0 { | ||||
| 		return types.Users{}, errors.New("invalid user format") | ||||
| 	} | ||||
|  | ||||
| 	for _, user := range userList { | ||||
| 		userSplit := strings.Split(user, ":") | ||||
| 		log.Debug().Strs("user", userSplit).Msg("Splitting user") | ||||
| 		if len(userSplit) != 2 { | ||||
| 			return types.Users{}, errors.New("invalid user format") | ||||
| 		} | ||||
| @@ -33,7 +30,7 @@ func ParseUsers(users string) (types.Users, error) { | ||||
| 		}) | ||||
| 	} | ||||
|  | ||||
| 	log.Debug().Interface("users", usersParsed).Msg("Parsed users") | ||||
| 	log.Debug().Msg("Parsed users") | ||||
|  | ||||
| 	return usersParsed, nil | ||||
| } | ||||
| @@ -45,7 +42,7 @@ func GetRootURL(urlSrc string) (string, error) { | ||||
| 		return "", parseErr | ||||
| 	} | ||||
|  | ||||
| 	urlSplitted := strings.Split(urlParsed.Host, ".") | ||||
| 	urlSplitted := strings.Split(urlParsed.Hostname(), ".") | ||||
|  | ||||
| 	urlFinal := strings.Join(urlSplitted[1:], ".") | ||||
|  | ||||
| @@ -77,21 +74,19 @@ func ParseFileToLine(content string) string { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		users = append(users, line) | ||||
| 		users = append(users, strings.TrimSpace(line)) | ||||
| 	} | ||||
|  | ||||
| 	return strings.Join(users, ",") | ||||
| } | ||||
|  | ||||
| func GetSecret(env string, file string) string { | ||||
| 	if env == "" && file == "" { | ||||
| 		log.Debug().Msg("No secret provided") | ||||
| func GetSecret(conf string, file string) string { | ||||
| 	if conf == "" && file == "" { | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	if env != "" { | ||||
| 		log.Debug().Str("secret", env).Msg("Using secret from env") | ||||
| 		return env | ||||
| 	if conf != "" { | ||||
| 		return conf | ||||
| 	} | ||||
|  | ||||
| 	contents, err := ReadFile(file) | ||||
| @@ -100,29 +95,29 @@ func GetSecret(env string, file string) string { | ||||
| 		return "" | ||||
| 	} | ||||
|  | ||||
| 	log.Debug().Str("secret", contents).Msg("Using secret from file") | ||||
|  | ||||
| 	return contents | ||||
| } | ||||
|  | ||||
| func GetUsers(env string, file string) (types.Users, error) { | ||||
| func GetUsers(conf string, file string) (types.Users, error) { | ||||
| 	var users string | ||||
|  | ||||
| 	if env == "" && file == "" { | ||||
| 	if conf == "" && file == "" { | ||||
| 		return types.Users{}, errors.New("no users provided") | ||||
| 	} | ||||
|  | ||||
| 	if env != "" { | ||||
| 		log.Debug().Str("users", env).Msg("Using users from env") | ||||
| 		users += env | ||||
| 	if conf != "" { | ||||
| 		log.Debug().Msg("Using users from config") | ||||
| 		users += conf | ||||
| 	} | ||||
|  | ||||
| 	if file != "" { | ||||
| 		fileContents, fileErr := ReadFile(file) | ||||
|  | ||||
| 		if fileErr == nil { | ||||
| 			log.Debug().Str("users", ParseFileToLine(fileContents)).Msg("Using users from file") | ||||
| 			users += "," | ||||
| 			log.Debug().Msg("Using users from file") | ||||
| 			if users != "" { | ||||
| 				users += "," | ||||
| 			} | ||||
| 			users += ParseFileToLine(fileContents) | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										4
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								main.go
									
									
									
									
									
								
							| @@ -4,7 +4,6 @@ import ( | ||||
| 	"os" | ||||
| 	"time" | ||||
| 	"tinyauth/cmd" | ||||
| 	"tinyauth/internal/assets" | ||||
|  | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"github.com/rs/zerolog/log" | ||||
| @@ -12,8 +11,7 @@ import ( | ||||
|  | ||||
| func main() { | ||||
| 	// Logger | ||||
| 	log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger() | ||||
| 	log.Info().Str("version", assets.Version).Msg("Starting tinyauth") | ||||
| 	log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger().Level(zerolog.FatalLevel) | ||||
|  | ||||
| 	// Run cmd | ||||
| 	cmd.Execute() | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								site/bun.lockb
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								site/bun.lockb
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -1,8 +1,9 @@ | ||||
| import { Button, Paper, Text } from "@mantine/core"; | ||||
| import { Button, Code, Paper, Text } from "@mantine/core"; | ||||
| import { notifications } from "@mantine/notifications"; | ||||
| import { Navigate } from "react-router"; | ||||
| import { useUserContext } from "../context/user-context"; | ||||
| import { Layout } from "../components/layouts/layout"; | ||||
| import { ReactNode } from "react"; | ||||
|  | ||||
| export const ContinuePage = () => { | ||||
|   const queryString = window.location.search; | ||||
| @@ -12,11 +13,11 @@ export const ContinuePage = () => { | ||||
|   const { isLoggedIn, disableContinue } = useUserContext(); | ||||
|  | ||||
|   if (!isLoggedIn) { | ||||
|     return <Navigate to="/login" />; | ||||
|     return <Navigate to={`/login?redirect_uri=${redirectUri}`} />; | ||||
|   } | ||||
|  | ||||
|   if (disableContinue && redirectUri !== "null") { | ||||
|     window.location.replace(redirectUri!); | ||||
|   if (redirectUri === "null") { | ||||
|     return <Navigate to="/" />; | ||||
|   } | ||||
|  | ||||
|   const redirect = () => { | ||||
| @@ -26,31 +27,62 @@ export const ContinuePage = () => { | ||||
|       color: "blue", | ||||
|     }); | ||||
|     setTimeout(() => { | ||||
|       window.location.replace(redirectUri!); | ||||
|       window.location.href = redirectUri!; | ||||
|     }, 500); | ||||
|   }; | ||||
|  | ||||
|   const urlParsed = URL.parse(redirectUri!); | ||||
|  | ||||
|   if ( | ||||
|     window.location.protocol === "https:" && | ||||
|     urlParsed!.protocol === "http:" | ||||
|   ) { | ||||
|     return ( | ||||
|       <ContinuePageLayout> | ||||
|         <Text size="xl" fw={700}> | ||||
|           Insecure Redirect | ||||
|         </Text> | ||||
|         <Text> | ||||
|           Your are logged in but trying to redirect from <Code>https</Code> to{" "} | ||||
|           <Code>http</Code>, please click the button to redirect. | ||||
|         </Text> | ||||
|         <Button fullWidth mt="xl" onClick={redirect}> | ||||
|           Continue | ||||
|         </Button> | ||||
|       </ContinuePageLayout> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   if (disableContinue) { | ||||
|     window.location.href = redirectUri!; | ||||
|     return ( | ||||
|       <ContinuePageLayout> | ||||
|         <Text size="xl" fw={700}> | ||||
|           Redirecting | ||||
|         </Text> | ||||
|         <Text>You should be redirected to your app soon.</Text> | ||||
|       </ContinuePageLayout> | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   return ( | ||||
|     <ContinuePageLayout> | ||||
|       <Text size="xl" fw={700}> | ||||
|         Continue | ||||
|       </Text> | ||||
|       <Text>Click the button to continue to your app.</Text> | ||||
|       <Button fullWidth mt="xl" onClick={redirect}> | ||||
|         Continue | ||||
|       </Button> | ||||
|     </ContinuePageLayout> | ||||
|   ); | ||||
| }; | ||||
|  | ||||
| export const ContinuePageLayout = ({ children }: { children: ReactNode }) => { | ||||
|   return ( | ||||
|     <Layout> | ||||
|       <Paper shadow="md" p={30} mt={30} radius="md" withBorder> | ||||
|         {redirectUri !== "null" ? ( | ||||
|           <> | ||||
|             <Text size="xl" fw={700}> | ||||
|               Continue | ||||
|             </Text> | ||||
|             <Text>Click the button to continue to your app.</Text> | ||||
|             <Button fullWidth mt="xl" onClick={redirect}> | ||||
|               Continue | ||||
|             </Button> | ||||
|           </> | ||||
|         ) : ( | ||||
|           <> | ||||
|             <Text size="xl" fw={700}> | ||||
|               Logged in | ||||
|             </Text> | ||||
|             <Text>You are now signed in and can use your apps.</Text> | ||||
|           </> | ||||
|         )} | ||||
|         {children} | ||||
|       </Paper> | ||||
|     </Layout> | ||||
|   ); | ||||
|   | ||||
| @@ -65,8 +65,12 @@ export const LoginPage = () => { | ||||
|         color: "green", | ||||
|       }); | ||||
|       setTimeout(() => { | ||||
|         window.location.replace(`/continue?redirect_uri=${redirectUri}`); | ||||
|       }); | ||||
|         if (redirectUri === "null") { | ||||
|           window.location.replace("/"); | ||||
|         } else { | ||||
|           window.location.replace(`/continue?redirect_uri=${redirectUri}`); | ||||
|         } | ||||
|       }, 500); | ||||
|     }, | ||||
|   }); | ||||
|  | ||||
| @@ -84,7 +88,14 @@ export const LoginPage = () => { | ||||
|       }); | ||||
|     }, | ||||
|     onSuccess: (data) => { | ||||
|       window.location.replace(data.data.url); | ||||
|       notifications.show({ | ||||
|         title: "Redirecting", | ||||
|         message: "Redirecting to your OAuth provider", | ||||
|         color: "blue", | ||||
|       }); | ||||
|       setTimeout(() => { | ||||
|         window.location.href = data.data.url; | ||||
|       }, 500); | ||||
|     }, | ||||
|   }); | ||||
|  | ||||
|   | ||||
| @@ -32,7 +32,7 @@ export const LogoutPage = () => { | ||||
|         color: "green", | ||||
|       }); | ||||
|       setTimeout(() => { | ||||
|         window.location.reload(); | ||||
|         window.location.replace("/login"); | ||||
|       }, 500); | ||||
|     }, | ||||
|   }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user