mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-02-27 11:21:59 +00:00
Compare commits
6 Commits
feat/oidc-
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b2975256d | ||
|
|
43e0f3e713 | ||
|
|
14c08172d8 | ||
|
|
456d8d17c3 | ||
|
|
f2b2826a48 | ||
|
|
4a1889c20b |
@@ -1,5 +1,5 @@
|
||||
# Site builder
|
||||
FROM oven/bun:1.3.9-alpine AS frontend-builder
|
||||
FROM oven/bun:1.3.10-alpine AS frontend-builder
|
||||
|
||||
WORKDIR /frontend
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Site builder
|
||||
FROM oven/bun:1.3.9-alpine AS frontend-builder
|
||||
FROM oven/bun:1.3.10-alpine AS frontend-builder
|
||||
|
||||
WORKDIR /frontend
|
||||
|
||||
|
||||
43
cmd/tinyauth/create_oidc_client.go
Normal file
43
cmd/tinyauth/create_oidc_client.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/steveiliop56/tinyauth/internal/utils"
|
||||
"github.com/traefik/paerser/cli"
|
||||
)
|
||||
|
||||
func createOidcClientCmd() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "create",
|
||||
Description: "Create a new OIDC Client",
|
||||
Configuration: nil,
|
||||
Resources: nil,
|
||||
AllowArg: true,
|
||||
Run: func(args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("client name is required. use tinyauth oidc create <name>")
|
||||
}
|
||||
|
||||
clientName := args[0]
|
||||
|
||||
match, err := regexp.MatchString("^[a-zA-Z0-9-]*$", clientName)
|
||||
|
||||
if !match || err != nil {
|
||||
return errors.New("client name can only contain alphanumeric characters and hyphens")
|
||||
}
|
||||
|
||||
uuid := uuid.New()
|
||||
clientId := uuid.String()
|
||||
clientSecret := "ta-" + utils.GenerateString(61)
|
||||
|
||||
fmt.Printf("Client Name: %s\n", clientName)
|
||||
fmt.Printf("Client ID: %s\n", clientId)
|
||||
fmt.Printf("Client Secret: %s\n", clientSecret)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ func main() {
|
||||
|
||||
cmdTinyauth := &cli.Command{
|
||||
Name: "tinyauth",
|
||||
Description: "The simplest way to protect your apps with a login screen.",
|
||||
Description: "The simplest way to protect your apps with a login screen",
|
||||
Configuration: tConfig,
|
||||
Resources: loaders,
|
||||
Run: func(_ []string) error {
|
||||
@@ -33,12 +33,17 @@ func main() {
|
||||
|
||||
cmdUser := &cli.Command{
|
||||
Name: "user",
|
||||
Description: "Utilities for creating and verifying Tinyauth users.",
|
||||
Description: "Manage Tinyauth users",
|
||||
}
|
||||
|
||||
cmdTotp := &cli.Command{
|
||||
Name: "totp",
|
||||
Description: "Utilities for creating Tinyauth TOTP users.",
|
||||
Description: "Manage Tinyauth TOTP users",
|
||||
}
|
||||
|
||||
cmdOidc := &cli.Command{
|
||||
Name: "oidc",
|
||||
Description: "Manage Tinyauth OIDC clients",
|
||||
}
|
||||
|
||||
err := cmdTinyauth.AddCommand(versionCmd())
|
||||
@@ -71,6 +76,12 @@ func main() {
|
||||
log.Fatal().Err(err).Msg("Failed to add create command")
|
||||
}
|
||||
|
||||
err = cmdOidc.AddCommand(createOidcClientCmd())
|
||||
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to add create command")
|
||||
}
|
||||
|
||||
err = cmdTinyauth.AddCommand(cmdUser)
|
||||
|
||||
if err != nil {
|
||||
@@ -83,6 +94,12 @@ func main() {
|
||||
log.Fatal().Err(err).Msg("Failed to add totp command")
|
||||
}
|
||||
|
||||
err = cmdTinyauth.AddCommand(cmdOidc)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to add oidc command")
|
||||
}
|
||||
|
||||
err = cli.Execute(cmdTinyauth)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -40,7 +40,7 @@ func verifyUserCmd() *cli.Command {
|
||||
|
||||
return &cli.Command{
|
||||
Name: "verify",
|
||||
Description: "Verify a user is set up correctly.",
|
||||
Description: "Verify a user is set up correctly",
|
||||
Configuration: tCfg,
|
||||
Resources: loaders,
|
||||
Run: func(_ []string) error {
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
func versionCmd() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "version",
|
||||
Description: "Print the version number of Tinyauth.",
|
||||
Description: "Print the version number of Tinyauth",
|
||||
Configuration: nil,
|
||||
Resources: nil,
|
||||
Run: func(_ []string) error {
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@tanstack/eslint-plugin-query": "^5.91.4",
|
||||
"@types/node": "^25.3.0",
|
||||
"@types/node": "^25.3.2",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
@@ -360,7 +360,7 @@
|
||||
|
||||
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
||||
|
||||
"@types/node": ["@types/node@25.3.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A=="],
|
||||
"@types/node": ["@types/node@25.3.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-RpV6r/ij22zRRdyBPcxDeKAzH43phWVKEjL2iksqo1Vz3CuBUrgmPpPhALKiRfU7OMCmeeO9vECBMsV0hMTG8Q=="],
|
||||
|
||||
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^10.0.1",
|
||||
"@tanstack/eslint-plugin-query": "^5.91.4",
|
||||
"@types/node": "^25.3.0",
|
||||
"@types/node": "^25.3.2",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
|
||||
@@ -14,17 +14,17 @@
|
||||
"loginOauthFailSubtitle": "Неуспело преузимање OAuth адресе",
|
||||
"loginOauthSuccessTitle": "Преусмеравање",
|
||||
"loginOauthSuccessSubtitle": "Преусмеравање на вашег OAuth провајдера",
|
||||
"loginOauthAutoRedirectTitle": "OAuth Auto Redirect",
|
||||
"loginOauthAutoRedirectSubtitle": "You will be automatically redirected to your OAuth provider to authenticate.",
|
||||
"loginOauthAutoRedirectButton": "Redirect now",
|
||||
"loginOauthAutoRedirectTitle": "OAuth аутоматско преусмерење",
|
||||
"loginOauthAutoRedirectSubtitle": "Бићете аутоматски преусмерени на вашег OAuth провајдера за аутентификацију.",
|
||||
"loginOauthAutoRedirectButton": "Преусмери сада",
|
||||
"continueTitle": "Настави",
|
||||
"continueRedirectingTitle": "Преусмеравање...",
|
||||
"continueRedirectingSubtitle": "Требали би сте ускоро да будете преусмерени на апликацију",
|
||||
"continueRedirectManually": "Redirect me manually",
|
||||
"continueRedirectManually": "Преусмери ме ручно",
|
||||
"continueInsecureRedirectTitle": "Небезбедно преусмеравање",
|
||||
"continueInsecureRedirectSubtitle": "Покушавате да преусмерите са <code>https</code> на <code>http</code> што није безбедно. Да ли желите да наставите?",
|
||||
"continueUntrustedRedirectTitle": "Untrusted redirect",
|
||||
"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?",
|
||||
"continueUntrustedRedirectTitle": "Неповерљиво преусмерење",
|
||||
"continueUntrustedRedirectSubtitle": "Покушавате да преусмерите на домен који се не поклапа са вашим подешеним доменом (<code>{{cookieDomain}}</code>). Да ли заиста желите да наставите?",
|
||||
"logoutFailTitle": "Неуспешно одјављивање",
|
||||
"logoutFailSubtitle": "Молим вас покушајте поново",
|
||||
"logoutSuccessTitle": "Одјављени",
|
||||
@@ -51,31 +51,31 @@
|
||||
"forgotPasswordTitle": "Заборавили сте лозинку?",
|
||||
"failedToFetchProvidersTitle": "Није успело учитавање провајдера аутентификације. Молим вас проверите ваша подешавања.",
|
||||
"errorTitle": "Појавила се грешка",
|
||||
"errorSubtitleInfo": "The following error occurred while processing your request:",
|
||||
"errorSubtitleInfo": "Појавила се следећа грешка током обраде вашег захтева:",
|
||||
"errorSubtitle": "Појавила се грешка при покушају извршавања ове радње. Молим вас проверите конзолу за додатне информације.",
|
||||
"forgotPasswordMessage": "Можете поништити вашу лозинку променом `USERS` променљиве окружења.",
|
||||
"fieldRequired": "This field is required",
|
||||
"invalidInput": "Invalid input",
|
||||
"domainWarningTitle": "Invalid Domain",
|
||||
"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": "Ignore",
|
||||
"goToCorrectDomainTitle": "Go to correct domain",
|
||||
"authorizeTitle": "Authorize",
|
||||
"authorizeCardTitle": "Continue to {{app}}?",
|
||||
"authorizeSubtitle": "Would you like to continue to this app? Please carefully review the permissions requested by the app.",
|
||||
"authorizeSubtitleOAuth": "Would you like to continue to this app?",
|
||||
"authorizeLoadingTitle": "Loading...",
|
||||
"authorizeLoadingSubtitle": "Please wait while we load the client information.",
|
||||
"authorizeSuccessTitle": "Authorized",
|
||||
"authorizeSuccessSubtitle": "You will be redirected to the app in a few seconds.",
|
||||
"authorizeErrorClientInfo": "An error occurred while loading the client information. Please try again later.",
|
||||
"authorizeErrorMissingParams": "The following parameters are missing: {{missingParams}}",
|
||||
"openidScopeName": "OpenID Connect",
|
||||
"openidScopeDescription": "Allows the app to access your OpenID Connect information.",
|
||||
"emailScopeName": "Email",
|
||||
"emailScopeDescription": "Allows the app to access your email address.",
|
||||
"profileScopeName": "Profile",
|
||||
"profileScopeDescription": "Allows the app to access your profile information.",
|
||||
"groupsScopeName": "Groups",
|
||||
"groupsScopeDescription": "Allows the app to access your group information."
|
||||
"fieldRequired": "Ово поље је неопходно",
|
||||
"invalidInput": "Неисправан унос",
|
||||
"domainWarningTitle": "Неисправан домен",
|
||||
"domainWarningSubtitle": "Ова инстанца је подешена да јој се приступа са <code>{{appUrl}}</code>, али се користи <code>{{currentUrl}}</code>. Ако наставите, можете искусити проблеме са аутентификацијом.",
|
||||
"ignoreTitle": "Игнориши",
|
||||
"goToCorrectDomainTitle": "Иди на исправан домен",
|
||||
"authorizeTitle": "Ауторизуј",
|
||||
"authorizeCardTitle": "Наставити на {{app}}?",
|
||||
"authorizeSubtitle": "Да ли желите да наставите на ову апликацију? Пажљиво проверите дозволе које вам тражи апликација.",
|
||||
"authorizeSubtitleOAuth": "Да ли желите да наставите на ову апликацију?",
|
||||
"authorizeLoadingTitle": "Учитавање...",
|
||||
"authorizeLoadingSubtitle": "Молим вас сачекајте док ми учитамо информације о клијенту.",
|
||||
"authorizeSuccessTitle": "Ауторизован",
|
||||
"authorizeSuccessSubtitle": "Бићете преусмерени на апликацију за неколико секунди.",
|
||||
"authorizeErrorClientInfo": "Појавила се грешка током учитавања информација о клијенту. Молим вас покушајте поново касније.",
|
||||
"authorizeErrorMissingParams": "Следећи параметри недостају: {{missingParams}}",
|
||||
"openidScopeName": "OpenID повезивање",
|
||||
"openidScopeDescription": "Омогућава апликацији да приступа информацији о вашој OpenID вези.",
|
||||
"emailScopeName": "Е-пошта",
|
||||
"emailScopeDescription": "Омогућава апликацији да приступа вашој адреси е-поште.",
|
||||
"profileScopeName": "Профил",
|
||||
"profileScopeDescription": "Омогућава апликацији да приступа информацијама о вашем профилу.",
|
||||
"groupsScopeName": "Групе",
|
||||
"groupsScopeDescription": "Омогућава апликацији да приступа информацијама о вашој групи."
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -145,7 +144,7 @@ func (controller *OIDCController) Authorize(c *gin.Context) {
|
||||
|
||||
// WARNING: Since Tinyauth is stateless, we cannot have a sub that never changes. We will just create a uuid out of the username and client name which remains stable, but if username or client name changes then sub changes too.
|
||||
sub := utils.GenerateUUID(fmt.Sprintf("%s:%s", userContext.Username, client.ID))
|
||||
code := rand.Text()
|
||||
code := utils.GenerateString(32)
|
||||
|
||||
// Before storing the code, delete old session
|
||||
err = controller.oidc.DeleteOldSession(c, sub)
|
||||
|
||||
@@ -60,7 +60,7 @@ func (controller *WellKnownController) OpenIDConnectConfiguration(c *gin.Context
|
||||
IDTokenSigningAlgValuesSupported: []string{"RS256"},
|
||||
TokenEndpointAuthMethodsSupported: []string{"client_secret_basic", "client_secret_post"},
|
||||
ClaimsSupported: []string{"sub", "updated_at", "name", "preferred_username", "email", "groups"},
|
||||
ServiceDocumentation: "https://tinyauth.app/docs/reference/openid",
|
||||
ServiceDocumentation: "https://tinyauth.app/docs/guides/oidc",
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -403,8 +403,8 @@ func (service *OIDCService) GenerateAccessToken(c *gin.Context, client config.OI
|
||||
return TokenResponse{}, err
|
||||
}
|
||||
|
||||
accessToken := rand.Text()
|
||||
refreshToken := rand.Text()
|
||||
accessToken := utils.GenerateString(32)
|
||||
refreshToken := utils.GenerateString(32)
|
||||
|
||||
tokenExpiresAt := time.Now().Add(time.Duration(service.config.SessionExpiry) * time.Second).Unix()
|
||||
|
||||
@@ -464,8 +464,8 @@ func (service *OIDCService) RefreshAccessToken(c *gin.Context, refreshToken stri
|
||||
return TokenResponse{}, err
|
||||
}
|
||||
|
||||
accessToken := rand.Text()
|
||||
newRefreshToken := rand.Text()
|
||||
accessToken := utils.GenerateString(32)
|
||||
newRefreshToken := utils.GenerateString(32)
|
||||
|
||||
tokenExpiresAt := time.Now().Add(time.Duration(service.config.SessionExpiry) * time.Second).Unix()
|
||||
refrshTokenExpiresAt := time.Now().Add(time.Duration(service.config.SessionExpiry*2) * time.Second).Unix()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"net"
|
||||
@@ -105,3 +106,9 @@ func GenerateUUID(str string) string {
|
||||
uuid := uuid.NewSHA1(uuid.NameSpaceURL, []byte(str))
|
||||
return uuid.String()
|
||||
}
|
||||
|
||||
func GenerateString(length int) string {
|
||||
src := make([]byte, length)
|
||||
rand.Read(src)
|
||||
return base64.RawURLEncoding.EncodeToString(src)[:length]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user