mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2025-10-28 20:55:42 +00:00
Compare commits
3 Commits
l10n_main
...
6647c6cd78
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6647c6cd78 | ||
|
|
7231efcbc3 | ||
|
|
5482430907 |
@@ -1,62 +1,62 @@
|
|||||||
{
|
{
|
||||||
"loginTitle": "Tervetuloa takaisin, kirjaudu sisään käyttäen",
|
"loginTitle": "Welcome back, login with",
|
||||||
"loginTitleSimple": "Tervetuloa takaisin, ole hyvä ja kirjaudu",
|
"loginTitleSimple": "Welcome back, please login",
|
||||||
"loginDivider": "Tai",
|
"loginDivider": "Or",
|
||||||
"loginUsername": "Käyttäjätunnus",
|
"loginUsername": "Username",
|
||||||
"loginPassword": "Salasana",
|
"loginPassword": "Password",
|
||||||
"loginSubmit": "Kirjaudu",
|
"loginSubmit": "Login",
|
||||||
"loginFailTitle": "Kirjautuminen epäonnistui",
|
"loginFailTitle": "Failed to log in",
|
||||||
"loginFailSubtitle": "Tarkista käyttäjätunnuksesi ja salasanasi",
|
"loginFailSubtitle": "Please check your username and password",
|
||||||
"loginFailRateLimit": "Kirjautuminen epäonnistui liian monta kertaa. Yritä myöhemmin uudelleen",
|
"loginFailRateLimit": "You failed to login too many times. Please try again later",
|
||||||
"loginSuccessTitle": "Olet kirjautunut sisään",
|
"loginSuccessTitle": "Logged in",
|
||||||
"loginSuccessSubtitle": "Tervetuloa takaisin!",
|
"loginSuccessSubtitle": "Welcome back!",
|
||||||
"loginOauthFailTitle": "Tapahtui virhe",
|
"loginOauthFailTitle": "An error occurred",
|
||||||
"loginOauthFailSubtitle": "OAuthin URL-osoitteen haku epäonnistui",
|
"loginOauthFailSubtitle": "Failed to get OAuth URL",
|
||||||
"loginOauthSuccessTitle": "Uudelleenohjataan",
|
"loginOauthSuccessTitle": "Redirecting",
|
||||||
"loginOauthSuccessSubtitle": "Uudelleenohjaus OAuth -palveluntarjoajallesi",
|
"loginOauthSuccessSubtitle": "Redirecting to your OAuth provider",
|
||||||
"loginOauthAutoRedirectTitle": "Automaattinen OAuth -uudelleenohjaus",
|
"loginOauthAutoRedirectTitle": "OAuth Auto Redirect",
|
||||||
"loginOauthAutoRedirectSubtitle": "Sinut ohjataan automaattisesti OAuth -palveluntarjoajallesi todentamista varten.",
|
"loginOauthAutoRedirectSubtitle": "You will be automatically redirected to your OAuth provider to authenticate.",
|
||||||
"loginOauthAutoRedirectButton": "Siirry nyt",
|
"loginOauthAutoRedirectButton": "Redirect now",
|
||||||
"continueTitle": "Jatka",
|
"continueTitle": "Continue",
|
||||||
"continueRedirectingTitle": "Uudelleenohjataan...",
|
"continueRedirectingTitle": "Redirecting...",
|
||||||
"continueRedirectingSubtitle": "Sinun pitäisi ohjautua sovellukseen pian",
|
"continueRedirectingSubtitle": "You should be redirected to the app soon",
|
||||||
"continueRedirectManually": "Siirrä minut manuaalisesti",
|
"continueRedirectManually": "Redirect me manually",
|
||||||
"continueInsecureRedirectTitle": "Turvaton uudelleenohjaus",
|
"continueInsecureRedirectTitle": "Insecure redirect",
|
||||||
"continueInsecureRedirectSubtitle": "Yrität siirtyä suojatusta <code>https</code> -sivusta suojaamattomalle <code>http</code> -sivulle. Oletko varma, että haluat jatkaa?",
|
"continueInsecureRedirectSubtitle": "You are trying to redirect from <code>https</code> to <code>http</code> which is not secure. Are you sure you want to continue?",
|
||||||
"continueUntrustedRedirectTitle": "Ei-luotettu uudelleenohjaus",
|
"continueUntrustedRedirectTitle": "Untrusted redirect",
|
||||||
"continueUntrustedRedirectSubtitle": "Yrität uudelleenohjata domainiin, joka ei vastaa määritettyä verkkotunnusta (<code>{{cookieDomain}}</code>). Oletko varma, että haluat jatkaa?",
|
"continueUntrustedRedirectSubtitle": "You are trying to redirect to a domain that does not match your configured domain (<code>{{cookieDomain}}</code>). Are you sure you want to continue?",
|
||||||
"logoutFailTitle": "Uloskirjautuminen epäonnistui",
|
"logoutFailTitle": "Failed to log out",
|
||||||
"logoutFailSubtitle": "Ole hyvä ja yritä uudelleen",
|
"logoutFailSubtitle": "Please try again",
|
||||||
"logoutSuccessTitle": "Kirjauduttu ulos",
|
"logoutSuccessTitle": "Logged out",
|
||||||
"logoutSuccessSubtitle": "Sinut on kirjattu ulos",
|
"logoutSuccessSubtitle": "You have been logged out",
|
||||||
"logoutTitle": "Kirjaudu ulos",
|
"logoutTitle": "Logout",
|
||||||
"logoutUsernameSubtitle": "Olet kirjautuneena sisään tunnuksella <code>{{username}}</code>. Kirjaudu ulos alla olevasta painikkeesta.",
|
"logoutUsernameSubtitle": "You are currently logged in as <code>{{username}}</code>. Click the button below to logout.",
|
||||||
"logoutOauthSubtitle": "Olet kirjautuneena sisään tunnuksella <code>{{username}}</code> OAuth palvelun {{provider}} kautta. Kirjaudu ulos alla olevasta painikkeesta.",
|
"logoutOauthSubtitle": "You are currently logged in as <code>{{username}}</code> using the {{provider}} OAuth provider. Click the button below to logout.",
|
||||||
"notFoundTitle": "Sivua ei löydy",
|
"notFoundTitle": "Page not found",
|
||||||
"notFoundSubtitle": "Sivua, jota etsit ei ole olemassa.",
|
"notFoundSubtitle": "The page you are looking for does not exist.",
|
||||||
"notFoundButton": "Palaa kotinäkymään",
|
"notFoundButton": "Go home",
|
||||||
"totpFailTitle": "Koodin vahvistus epäonnistui",
|
"totpFailTitle": "Failed to verify code",
|
||||||
"totpFailSubtitle": "Tarkista koodisi ja yritä uudelleen",
|
"totpFailSubtitle": "Please check your code and try again",
|
||||||
"totpSuccessTitle": "Vahvistettu",
|
"totpSuccessTitle": "Verified",
|
||||||
"totpSuccessSubtitle": "Uudelleenohjataan sovelluksellesi",
|
"totpSuccessSubtitle": "Redirecting to your app",
|
||||||
"totpTitle": "Syötä TOTP -koodisi",
|
"totpTitle": "Enter your TOTP code",
|
||||||
"totpSubtitle": "Ole hyvä ja syötä koodi todennussovelluksestasi.",
|
"totpSubtitle": "Please enter the code from your authenticator app.",
|
||||||
"unauthorizedTitle": "Ei sallittu",
|
"unauthorizedTitle": "Unauthorized",
|
||||||
"unauthorizedResourceSubtitle": "Käyttäjällä <code>{{username}}</code> ei ole pääsyä kohteeseen <code>{{resource}}</code>.",
|
"unauthorizedResourceSubtitle": "The user with username <code>{{username}}</code> is not authorized to access the resource <code>{{resource}}</code>.",
|
||||||
"unauthorizedLoginSubtitle": "Käyttäjällä <code>{{username}}</code> ei ole lupaa kirjautua.",
|
"unauthorizedLoginSubtitle": "The user with username <code>{{username}}</code> is not authorized to login.",
|
||||||
"unauthorizedGroupsSubtitle": "Käyttäjä <code>{{username}}</code> ei ole ryhmässä, joka vaaditaan pääsyyn kohteeseen <code>{{resource}}</code>.",
|
"unauthorizedGroupsSubtitle": "The user with username <code>{{username}}</code> is not in the groups required by the resource <code>{{resource}}</code>.",
|
||||||
"unauthorizedIpSubtitle": "IP osoitteestasi <code>{{ip}}</code> ei ole pääsyä kohteeseen <code>{{resource}}</code>.",
|
"unauthorizedIpSubtitle": "Your IP address <code>{{ip}}</code> is not authorized to access the resource <code>{{resource}}</code>.",
|
||||||
"unauthorizedButton": "Yritä uudelleen",
|
"unauthorizedButton": "Try again",
|
||||||
"cancelTitle": "Peruuta",
|
"cancelTitle": "Cancel",
|
||||||
"forgotPasswordTitle": "Unohditko salasanasi?",
|
"forgotPasswordTitle": "Forgot your password?",
|
||||||
"failedToFetchProvidersTitle": "Todennuspalvelujen tarjoajien lataaminen epäonnistui. Tarkista määrityksesi.",
|
"failedToFetchProvidersTitle": "Failed to load authentication providers. Please check your configuration.",
|
||||||
"errorTitle": "Tapahtui virhe",
|
"errorTitle": "An error occurred",
|
||||||
"errorSubtitle": "Tapahtui virhe yritettäessä suorittaa tämä toiminto. Ole hyvä ja tarkista konsoli saadaksesi lisätietoja.",
|
"errorSubtitle": "An error occurred while trying to perform this action. Please check the console for more information.",
|
||||||
"forgotPasswordMessage": "Voit nollata salasanasi vaihtamalla ympäristömuuttujan `USERS`.",
|
"forgotPasswordMessage": "You can reset your password by changing the `USERS` environment variable.",
|
||||||
"fieldRequired": "Tämä kenttä on pakollinen",
|
"fieldRequired": "This field is required",
|
||||||
"invalidInput": "Virheellinen syöte",
|
"invalidInput": "Invalid input",
|
||||||
"domainWarningTitle": "Virheellinen verkkotunnus",
|
"domainWarningTitle": "Invalid Domain",
|
||||||
"domainWarningSubtitle": "Tämä instanssi on määritelty käyttämään osoitetta <code>{{appUrl}}</code>, mutta nykyinen osoite on <code>{{currentUrl}}</code>. Jos jatkat, saatat törmätä ongelmiin autentikoinnissa.",
|
"domainWarningSubtitle": "This instance is configured to be accessed from <code>{{appUrl}}</code>, but <code>{{currentUrl}}</code> is being used. If you proceed, you may encounter issues with authentication.",
|
||||||
"ignoreTitle": "Jätä huomiotta",
|
"ignoreTitle": "Ignore",
|
||||||
"goToCorrectDomainTitle": "Siirry oikeaan verkkotunnukseen"
|
"goToCorrectDomainTitle": "Go to correct domain"
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package bootstrap
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -13,11 +14,13 @@ import (
|
|||||||
"tinyauth/internal/config"
|
"tinyauth/internal/config"
|
||||||
"tinyauth/internal/controller"
|
"tinyauth/internal/controller"
|
||||||
"tinyauth/internal/middleware"
|
"tinyauth/internal/middleware"
|
||||||
|
"tinyauth/internal/model"
|
||||||
"tinyauth/internal/service"
|
"tinyauth/internal/service"
|
||||||
"tinyauth/internal/utils"
|
"tinyauth/internal/utils"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Controller interface {
|
type Controller interface {
|
||||||
@@ -277,6 +280,10 @@ func (app *BootstrapApp) Setup() error {
|
|||||||
go app.heartbeat()
|
go app.heartbeat()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start DB cleanup routine
|
||||||
|
log.Debug().Msg("Starting database cleanup routine")
|
||||||
|
go app.dbCleanup(database)
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
address := fmt.Sprintf("%s:%d", app.config.Address, app.config.Port)
|
address := fmt.Sprintf("%s:%d", app.config.Address, app.config.Port)
|
||||||
log.Info().Msgf("Starting server on %s", address)
|
log.Info().Msgf("Starting server on %s", address)
|
||||||
@@ -338,3 +345,17 @@ func (app *BootstrapApp) heartbeat() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *BootstrapApp) dbCleanup(db *gorm.DB) {
|
||||||
|
ticker := time.NewTicker(time.Duration(30) * time.Minute)
|
||||||
|
defer ticker.Stop()
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
for ; true; <-ticker.C {
|
||||||
|
log.Debug().Msg("Cleaning up old database sessions")
|
||||||
|
_, err := gorm.G[model.Session](db).Where("expiry < ?", time.Now().UnixMilli()).Delete(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("Failed to cleanup old sessions")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ func (controller *OAuthController) oauthURLHandler(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
service.GenerateVerifier()
|
||||||
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.CookieDomain), controller.config.SecureCookie, true)
|
c.SetCookie(controller.config.CSRFCookieName, state, int(time.Hour.Seconds()), "/", fmt.Sprintf(".%s", controller.config.CookieDomain), controller.config.SecureCookie, true)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -41,6 +43,7 @@ type AuthService struct {
|
|||||||
loginMutex sync.RWMutex
|
loginMutex sync.RWMutex
|
||||||
ldap *LdapService
|
ldap *LdapService
|
||||||
database *gorm.DB
|
database *gorm.DB
|
||||||
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuthService(config AuthServiceConfig, docker *DockerService, ldap *LdapService, database *gorm.DB) *AuthService {
|
func NewAuthService(config AuthServiceConfig, docker *DockerService, ldap *LdapService, database *gorm.DB) *AuthService {
|
||||||
@@ -54,6 +57,7 @@ func NewAuthService(config AuthServiceConfig, docker *DockerService, ldap *LdapS
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (auth *AuthService) Init() error {
|
func (auth *AuthService) Init() error {
|
||||||
|
auth.ctx = context.Background()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +217,7 @@ func (auth *AuthService) CreateSessionCookie(c *gin.Context, data *config.Sessio
|
|||||||
OAuthName: data.OAuthName,
|
OAuthName: data.OAuthName,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = auth.database.Create(&session).Error
|
err = gorm.G[model.Session](auth.database).Create(auth.ctx, &session)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -231,10 +235,10 @@ func (auth *AuthService) DeleteSessionCookie(c *gin.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
res := auth.database.Unscoped().Where("uuid = ?", cookie).Delete(&model.Session{})
|
_, err = gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).Delete(auth.ctx)
|
||||||
|
|
||||||
if res.Error != nil {
|
if err != nil {
|
||||||
return res.Error
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.SetCookie(auth.config.SessionCookieName, "", -1, "/", fmt.Sprintf(".%s", auth.config.CookieDomain), auth.config.SecureCookie, true)
|
c.SetCookie(auth.config.SessionCookieName, "", -1, "/", fmt.Sprintf(".%s", auth.config.CookieDomain), auth.config.SecureCookie, true)
|
||||||
@@ -249,15 +253,13 @@ func (auth *AuthService) GetSessionCookie(c *gin.Context) (config.SessionCookie,
|
|||||||
return config.SessionCookie{}, err
|
return config.SessionCookie{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var session model.Session
|
session, err := gorm.G[model.Session](auth.database).Where("uuid = ?", cookie).First(auth.ctx)
|
||||||
|
|
||||||
res := auth.database.Unscoped().Where("uuid = ?", cookie).First(&session)
|
if err != nil {
|
||||||
|
return config.SessionCookie{}, err
|
||||||
if res.Error != nil {
|
|
||||||
return config.SessionCookie{}, res.Error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if res.RowsAffected == 0 {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return config.SessionCookie{}, fmt.Errorf("session not found")
|
return config.SessionCookie{}, fmt.Errorf("session not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,10 +59,8 @@ func (generic *GenericOAuthService) Init() error {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
||||||
verifier := oauth2.GenerateVerifier()
|
|
||||||
|
|
||||||
generic.context = ctx
|
generic.context = ctx
|
||||||
generic.verifier = verifier
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +74,12 @@ func (generic *GenericOAuthService) GenerateState() string {
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (generic *GenericOAuthService) GenerateVerifier() string {
|
||||||
|
verifier := oauth2.GenerateVerifier()
|
||||||
|
generic.verifier = verifier
|
||||||
|
return verifier
|
||||||
|
}
|
||||||
|
|
||||||
func (generic *GenericOAuthService) GetAuthURL(state string) string {
|
func (generic *GenericOAuthService) GetAuthURL(state string) string {
|
||||||
return generic.config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(generic.verifier))
|
return generic.config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(generic.verifier))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,10 +53,7 @@ func (github *GithubOAuthService) Init() error {
|
|||||||
httpClient := &http.Client{}
|
httpClient := &http.Client{}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
||||||
verifier := oauth2.GenerateVerifier()
|
|
||||||
|
|
||||||
github.context = ctx
|
github.context = ctx
|
||||||
github.verifier = verifier
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +67,12 @@ func (github *GithubOAuthService) GenerateState() string {
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (github *GithubOAuthService) GenerateVerifier() string {
|
||||||
|
verifier := oauth2.GenerateVerifier()
|
||||||
|
github.verifier = verifier
|
||||||
|
return verifier
|
||||||
|
}
|
||||||
|
|
||||||
func (github *GithubOAuthService) GetAuthURL(state string) string {
|
func (github *GithubOAuthService) GetAuthURL(state string) string {
|
||||||
return github.config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(github.verifier))
|
return github.config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(github.verifier))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,10 +48,7 @@ func (google *GoogleOAuthService) Init() error {
|
|||||||
httpClient := &http.Client{}
|
httpClient := &http.Client{}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
||||||
verifier := oauth2.GenerateVerifier()
|
|
||||||
|
|
||||||
google.context = ctx
|
google.context = ctx
|
||||||
google.verifier = verifier
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +62,12 @@ func (oauth *GoogleOAuthService) GenerateState() string {
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (google *GoogleOAuthService) GenerateVerifier() string {
|
||||||
|
verifier := oauth2.GenerateVerifier()
|
||||||
|
google.verifier = verifier
|
||||||
|
return verifier
|
||||||
|
}
|
||||||
|
|
||||||
func (google *GoogleOAuthService) GetAuthURL(state string) string {
|
func (google *GoogleOAuthService) GetAuthURL(state string) string {
|
||||||
return google.config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(google.verifier))
|
return google.config.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.S256ChallengeOption(google.verifier))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
type OAuthService interface {
|
type OAuthService interface {
|
||||||
Init() error
|
Init() error
|
||||||
GenerateState() string
|
GenerateState() string
|
||||||
|
GenerateVerifier() string
|
||||||
GetAuthURL(state string) string
|
GetAuthURL(state string) string
|
||||||
VerifyCode(code string) error
|
VerifyCode(code string) error
|
||||||
Userinfo() (config.Claims, error)
|
Userinfo() (config.Claims, error)
|
||||||
|
|||||||
Reference in New Issue
Block a user