Compare commits

..

29 Commits

Author SHA1 Message Date
Stavros 250e6fb8a1 New translations en.json (Portuguese, Brazilian)
[ci skip]
2026-07-09 19:01:11 +03:00
Stavros 056116bf1e New translations en.json (Vietnamese)
[ci skip]
2026-07-09 19:01:10 +03:00
Stavros 2460528500 New translations en.json (Chinese Traditional)
[ci skip]
2026-07-09 19:01:08 +03:00
Stavros a8777f24da New translations en.json (Chinese Simplified)
[ci skip]
2026-07-09 19:01:07 +03:00
Stavros 63ab2c9e3f New translations en.json (Ukrainian)
[ci skip]
2026-07-09 19:01:06 +03:00
Stavros 941b882fc9 New translations en.json (Turkish)
[ci skip]
2026-07-09 19:01:05 +03:00
Stavros 0e7e281429 New translations en.json (Swedish)
[ci skip]
2026-07-09 19:01:03 +03:00
Stavros 181a6cf58c New translations en.json (Serbian (Cyrillic))
[ci skip]
2026-07-09 19:01:02 +03:00
Stavros 928f9b3133 New translations en.json (Russian)
[ci skip]
2026-07-09 19:01:00 +03:00
Stavros 105de0a608 New translations en.json (Portuguese)
[ci skip]
2026-07-09 19:00:59 +03:00
Stavros 9bb1e88492 New translations en.json (Polish)
[ci skip]
2026-07-09 19:00:58 +03:00
Stavros aa86e179bb New translations en.json (Norwegian)
[ci skip]
2026-07-09 19:00:57 +03:00
Stavros 3a435de109 New translations en.json (Dutch)
[ci skip]
2026-07-09 19:00:55 +03:00
Stavros e0b8151f66 New translations en.json (Korean)
[ci skip]
2026-07-09 19:00:54 +03:00
Stavros 0d94c16bff New translations en.json (Japanese)
[ci skip]
2026-07-09 19:00:53 +03:00
Stavros 097efe9d42 New translations en.json (Italian)
[ci skip]
2026-07-09 19:00:52 +03:00
Stavros 8d84b3e6af New translations en.json (Hungarian)
[ci skip]
2026-07-09 19:00:51 +03:00
Stavros c7edf79a6d New translations en.json (Hebrew)
[ci skip]
2026-07-09 19:00:49 +03:00
Stavros f6188f6a8d New translations en.json (Finnish)
[ci skip]
2026-07-09 19:00:48 +03:00
Stavros 7235855061 New translations en.json (Greek)
[ci skip]
2026-07-09 19:00:47 +03:00
Stavros 768eb29292 New translations en.json (German)
[ci skip]
2026-07-09 19:00:45 +03:00
Stavros 9743fe71cc New translations en.json (Danish)
[ci skip]
2026-07-09 19:00:44 +03:00
Stavros 93e2a6a7fa New translations en.json (Czech)
[ci skip]
2026-07-09 19:00:43 +03:00
Stavros 1649a96cd6 New translations en.json (Catalan)
[ci skip]
2026-07-09 19:00:42 +03:00
Stavros 2cb606e5aa New translations en.json (Arabic)
[ci skip]
2026-07-09 19:00:40 +03:00
Stavros 229a5ae3c3 New translations en.json (Afrikaans)
[ci skip]
2026-07-09 19:00:39 +03:00
Stavros 122e02811a New translations en.json (Spanish)
[ci skip]
2026-07-09 19:00:38 +03:00
Stavros cf97a7a251 New translations en.json (French)
[ci skip]
2026-07-09 19:00:37 +03:00
Stavros 82189617b8 New translations en.json (Romanian)
[ci skip]
2026-07-09 19:00:35 +03:00
10 changed files with 12 additions and 79 deletions
+1 -1
View File
@@ -86,7 +86,7 @@
"addressScopeName": "Adres",
"addressScopeDescription": "Geeft de app toegang tot je adres.",
"loginTailscaleTitle": "Doorgaan met Tailscale",
"loginTailscaleDescription": "Je lijkt toegang te hebben tot Tinyauth vanaf een geautoriseerd Tailscale-apparaat. Wil je doorgaan met je Tailscale-verbinding?",
"loginTailscaleDescription": "Je lijkt toegang te hebben tot Tinyauth vanaf een geautoriseerd Tailscale-apparaat. Wil je doorgaan met jeTailscale-verbinding?",
"loginTailscaleDeviceName": "Apparaatnaam:",
"loginTailscaleOtherMethod": "Op een andere manier inloggen",
"loginTailscaleSuccess": "Succesvol geauthenticeerd met Tailscale.",
+1 -1
View File
@@ -77,7 +77,7 @@
"emailScopeName": "E-mail",
"emailScopeDescription": "Zezwala aplikacji na dostęp do adresów e-mail.",
"profileScopeName": "Profil",
"profileScopeDescription": "Zezwala aplikacji na dostęp do informacji o profilu.",
"profileScopeDescription": "Zezwala aplikacji na dostęp do informacji o porfilu.",
"groupsScopeName": "Grupy",
"groupsScopeDescription": "Zezwala aplikacji na dostęp do informacji o grupie.",
"backToLoginButton": "Wróć do logowania",
+1 -1
View File
@@ -99,7 +99,7 @@
"quickActionsThemeSystem": "Систем",
"quickActionsLogout": "Одјава",
"quickActionsTitle": "Брзе радње",
"quickActionsProviderLocal": "Локално",
"quickActionsProviderLocal": "Lokalno",
"quickActionsProviderLDAP": "LDAP",
"quickActionsProviderOAuth": "{{provider}} OAuth"
}
+1 -1
View File
@@ -98,7 +98,7 @@
"quickActionsThemeDark": "暗色主题",
"quickActionsThemeSystem": "跟随系统",
"quickActionsLogout": "登出",
"quickActionsTitle": "快速操作",
"quickActionsTitle": "快速行動",
"quickActionsProviderLocal": "本地",
"quickActionsProviderLDAP": "LDAP",
"quickActionsProviderOAuth": "{{provider}} OAuth"
+2 -1
View File
@@ -184,7 +184,8 @@ export const AuthorizePage = () => {
<CardFooter className="flex flex-col items-stretch gap-3">
<Button
onClick={() => authorizeMutate()}
loading={authorizePending || shouldAutoAuthorize}
loading={authorizePending}
disabled={shouldAutoAuthorize}
>
{t("authorizeTitle")}
</Button>
+2 -1
View File
@@ -177,7 +177,8 @@ func (app *BootstrapApp) Setup() error {
cookieId := strings.Split(app.runtime.UUID, "-")[0] // first 8 characters of the uuid should be good enough
app.runtime.SessionCookieName = fmt.Sprintf("%s-%s", model.SessionCookieName, cookieId)
app.runtime.ScopeCookieName = fmt.Sprintf("%s-%s", model.OIDCScopeCookieName, cookieId)
app.runtime.CSRFCookieName = fmt.Sprintf("%s-%s", model.CSRFCookieName, cookieId)
app.runtime.RedirectCookieName = fmt.Sprintf("%s-%s", model.RedirectCookieName, cookieId)
app.runtime.OAuthSessionCookieName = fmt.Sprintf("%s-%s", model.OAuthSessionCookieName, cookieId)
// database
-45
View File
@@ -34,7 +34,6 @@ type OIDCController struct {
log *logger.Logger
oidc *service.OIDCService
runtime *model.RuntimeConfig
config *model.Config
}
type AuthorizeCallback struct {
@@ -88,7 +87,6 @@ type OIDCControllerInput struct {
Log *logger.Logger
OIDCService *service.OIDCService
Config *model.Config
RuntimeConfig *model.RuntimeConfig
RouterGroup *gin.RouterGroup `name:"apiRouterGroup"`
MainRouter *gin.RouterGroup `name:"mainRouterGroup"`
@@ -99,7 +97,6 @@ func NewOIDCController(i OIDCControllerInput) *OIDCController {
log: i.Log,
oidc: i.OIDCService,
runtime: i.RuntimeConfig,
config: i.Config,
}
i.MainRouter.POST("/authorize", controller.authorize)
@@ -244,19 +241,6 @@ func (controller *OIDCController) authorize(c *gin.Context) {
}
}
cookieId := strings.SplitN(client.ClientID, "-", 2)[0]
cookieName := fmt.Sprintf("%s-%s", controller.runtime.ScopeCookieName, cookieId)
scopeCookie, err := c.Cookie(cookieName)
if err == nil {
scopes := fmt.Sprintf("scopes=%s;", req.Scope)
if controller.oidc.VerifySignedValue(client.ClientSecret, []byte(scopes), scopeCookie) {
if values.OIDCPrompt != service.OIDCPromptLogin {
values.OIDCPrompt = service.OIDCPromptNone
}
}
}
queries, err := query.Values(values)
if err != nil {
@@ -335,19 +319,6 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) {
return
}
// Get the client
client, ok := controller.oidc.GetClient(authorizeReq.ClientID)
if !ok {
controller.authorizeError(c, authorizeErrorParams{
err: errors.New("client not found"),
reason: "Client not found",
reasonPublic: "The client is not configured",
json: true,
})
return
}
// We no longer need the ticket
controller.oidc.DeleteAuthorizeRequestTicket(req.Ticket)
@@ -390,22 +361,6 @@ func (controller *OIDCController) authorizeComplete(c *gin.Context) {
return
}
// Set a cookie for the consent screen (approved scopes)
cookieId := strings.SplitN(client.ClientID, "-", 2)[0]
cookieName := fmt.Sprintf("%s-%s", controller.runtime.ScopeCookieName, cookieId)
scopes := fmt.Sprintf("scopes=%s;", authorizeReq.Scope)
cookie := &http.Cookie{
Name: cookieName,
Value: controller.oidc.CreateSignedValue(client.ClientSecret, []byte(scopes)),
Path: "/",
Secure: controller.config.Auth.SecureCookie,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
}
http.SetCookie(c.Writer, cookie)
c.JSON(200, gin.H{
"status": 200,
"redirect_uri": fmt.Sprintf("%s?%s", authorizeReq.RedirectURI, queries.Encode()),
+2 -1
View File
@@ -20,7 +20,8 @@ var OverrideProviders = map[string]string{
var ReservedProviderNames = []string{"local", "ldap", "tailscale"}
const SessionCookieName = "tinyauth-session"
const CSRFCookieName = "tinyauth-csrf"
const RedirectCookieName = "tinyauth-redirect"
const OAuthSessionCookieName = "tinyauth-oauth"
const OIDCScopeCookieName = "tinyauth-scope"
const GracefulShutdownTimeout = 5 // seconds
+2 -1
View File
@@ -5,7 +5,8 @@ type RuntimeConfig struct {
UUID string
CookieDomain string
SessionCookieName string
ScopeCookieName string
CSRFCookieName string
RedirectCookieName string
OAuthSessionCookieName string
LocalUsers []LocalUser
OAuthProviders map[string]OAuthServiceConfig
-26
View File
@@ -3,7 +3,6 @@ package service
import (
"context"
"crypto"
"crypto/hmac"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
@@ -23,7 +22,6 @@ import (
"github.com/go-jose/go-jose/v4"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
"github.com/steveiliop56/ding"
"github.com/tinyauthapp/tinyauth/internal/model"
"github.com/tinyauthapp/tinyauth/internal/repository"
@@ -307,9 +305,6 @@ func NewOIDCService(i OIDCServiceInput) (*OIDCService, error) {
for id, client := range i.Config.OIDC.Clients {
client.ID = id
if err := uuid.Validate(client.ClientID); err != nil {
return nil, fmt.Errorf("invalid client id: %w", err)
}
if client.Name == "" {
client.Name = utils.Capitalize(client.ID)
}
@@ -323,9 +318,6 @@ func NewOIDCService(i OIDCServiceInput) (*OIDCService, error) {
client.ClientSecret = secret
}
client.ClientSecretFile = ""
if len(client.ClientSecret) < 32 {
return nil, fmt.Errorf("client secret for client %s is too short, must be >= 32 chars", client.ClientID)
}
clients[id] = client
i.Log.App.Debug().Str("clientId", client.ClientID).Msg("Loaded OIDC client configuration")
}
@@ -977,21 +969,3 @@ func (service *OIDCService) GetPrompt(prompt string) []OIDCPrompt {
return parsedPromps
}
func (service *OIDCService) CreateSignedValue(key string, data []byte) string {
// create the signature
h := hmac.New(sha256.New, []byte(key))
h.Write(data)
sig := base64.URLEncoding.EncodeToString(h.Sum(nil))
// hash the data
hasher := sha256.New()
hasher.Write(data)
hash := base64.URLEncoding.EncodeToString(hasher.Sum(nil))
return fmt.Sprintf("%s.%s", hash, sig)
}
func (service *OIDCService) VerifySignedValue(key string, data []byte, signedValue string) bool {
return service.CreateSignedValue(key, data) == signedValue
}