WIP: Start implementing the internal auth
All checks were successful
ci/woodpecker/push/build Pipeline was successful

Signed-off-by: Nikolai Rodionov <allanger@badhouseplants.net>
This commit is contained in:
2026-05-05 22:56:56 +02:00
parent 4d73dbfd44
commit c52c3d1046
7 changed files with 51 additions and 63 deletions

View File

@@ -38,3 +38,16 @@ tasks:
helmfile-deploy:
desc: Deploy the helmfile for the local dev
cmd: helmfile apply
get-proto-from-branch:
desc: Get the latest version of generated protobuf code from the branch
silent: true
vars:
WORKDIR:
sh: mktemp -d
cmds:
- git clone git@gitea.badhouseplants.net:softplayer/softplayer-go-proto.git '{{ .WORKDIR }}'
- git -C '{{ .WORKDIR }}' checkout '{{ .CLI_ARGS }}'
- go get gitea.badhouseplants.net/softplayer/softplayer-go-proto@$(git -C '{{ .WORKDIR }}' rev-parse HEAD)
- rm -rf '{{ .WORKDIR }}'
- go mod tidy

View File

@@ -4,10 +4,9 @@ import (
"context"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers"
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/tools/logger"
accounts "gitea.badhouseplants.net/softplayer/softplayer-go-proto/pkg/accounts/v1"
"github.com/coreos/go-oidc/v3/oidc"
"github.com/golang/protobuf/ptypes/empty"
"golang.org/x/oauth2"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
@@ -25,49 +24,20 @@ type AccountsNoAuthServer struct {
}
func (a *AccountsNoAuthServer) SignIn(ctx context.Context, in *accounts.SignInRequest) (*empty.Empty, error) {
provider, err := oidc.NewProvider(ctx, "https://authentik.badhouseplants.net")
if err != nil {
return nil, err
}
// Configure an OpenID Connect aware OAuth2 client.
oauth2Config := oauth2.Config{
ClientID: "softplayer-localhost",
ClientSecret: "pRpe3scGUE2jNH6t5rqI9R4OROeQHs4eO6ku957mYjDumKhQGX8QJcO0BMJ2FG4sUpvFrqccEqWgc3wKMp94tC8LyvTnkPF0Tg0CaldAEHuoQQdNKAzXVxwrHE6kNyBC",
RedirectURL: "http://localhost:8080/#/auth/callback",
// Discovery returns the OAuth2 endpoints.
Endpoint: provider.Endpoint(),
// "openid" is a required scope for OpenID Connect flows.
Scopes: []string{oidc.ScopeOpenID, "profile", "email"},
}
verifier := provider.Verifier(&oidc.Config{ClientID: "softplayer-localhost"})
oauth2Token, err := oauth2Config.Exchange(ctx, in.Code)
if err != nil {
return nil, err
}
// Extract the ID Token from OAuth2 token.
rawIDToken, ok := oauth2Token.Extra("id_token").(string)
if !ok {
return nil, status.Error(codes.Unauthenticated, "Couldn't parse oauth token")
}
// Parse and verify ID Token payload.
idToken, err := verifier.Verify(ctx, rawIDToken)
if err != nil {
return nil, status.Error(codes.Unauthenticated, "Couldn't verify oauth token")
}
// Extract custom claims
var claims struct {
Email string `json:"email"`
Verified bool `json:"email_verified"`
}
if err := idToken.Claims(&claims); err != nil {
// handle error
}
return &emptypb.Empty{}, nil
}
func (a *AccountsNoAuthServer) SignUp(ctx context.Context, in *accounts.SignUpRequest) (*empty.Empty, error) {
log := logger.FromContext(ctx)
data := &controllers.AccountData{
Password: in.GetPassword(),
Email: in.GetEmail(),
}
id, err := a.ctrl.Create(ctx, data)
if err != nil {
return nil, status.Error(codes.Aborted, "Couldn't create a user")
}
log.Info(id)
return &emptypb.Empty{}, nil
}

2
go.mod
View File

@@ -140,7 +140,7 @@ require (
)
require (
gitea.badhouseplants.net/softplayer/softplayer-go-proto v0.0.0-20260430152421-88c087f0cea0
gitea.badhouseplants.net/softplayer/softplayer-go-proto v0.0.0-20260505200910-6680dffa2e8b
github.com/golang/protobuf v1.5.4
golang.org/x/net v0.49.0 // indirect
golang.org/x/sys v0.40.0 // indirect

12
go.sum
View File

@@ -6,8 +6,8 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
gitea.badhouseplants.net/softplayer/softplayer-go-proto v0.0.0-20260430152421-88c087f0cea0 h1:2UggBAWgOJ1MYgkk+RTaWhfTGtzAZ0B9MriZMoHqnq4=
gitea.badhouseplants.net/softplayer/softplayer-go-proto v0.0.0-20260430152421-88c087f0cea0/go.mod h1:AgOh1lkPHyRgBf3/s1btKcAqke/33LbKYarTD13qeAg=
gitea.badhouseplants.net/softplayer/softplayer-go-proto v0.0.0-20260505200910-6680dffa2e8b h1:/mhdJ1VEhIWmLd6Wrs6xIs+USjhHcAn8MsK7wZqzi3Y=
gitea.badhouseplants.net/softplayer/softplayer-go-proto v0.0.0-20260505200910-6680dffa2e8b/go.mod h1:AgOh1lkPHyRgBf3/s1btKcAqke/33LbKYarTD13qeAg=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
@@ -189,8 +189,6 @@ github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJr
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw=
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 h1:B+8ClL/kCQkRiU82d9xajRPKYMrB7E0MbtzWVi1K4ns=
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3/go.mod h1:NbCUVmiS4foBGBHOYlCT25+YmGpJ32dZPi75pGEUpj4=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
@@ -243,15 +241,10 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
@@ -464,7 +457,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/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.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=

View File

@@ -32,6 +32,19 @@ spec:
securityContext:
{{- toYaml . | nindent 8 }}
{{- end }}
initContainers:
- name: {{ .Chart.Name }}-migrations
{{- with .Values.securityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
- migrate
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
{{- with .Values.securityContext }}

View File

@@ -32,22 +32,24 @@ type JWT struct {
type AccountParams struct{}
type AccountData struct {
Username string
Password string
Email string
UUID string
}
func (c *AccountController) Create(ctx context.Context, data *AccountData) (string, error) {
log := logger.FromContext(ctx)
data.UUID = uuid.New().String()
passwordHash, err := hash.HashPassword(data.Password, int(c.HashCost))
if err != nil {
log.Error(err, "Couldn't crate the password hash")
return "", nil
}
query := "INSERT INTO users (uuid, username, email, password_hash) VALUES ($1, $2, $3, $4)"
if _, err := c.DB.Query(query, data.UUID, data.Username, data.Email, passwordHash); err != nil {
query := "INSERT INTO users (uuid, email, password_hash) VALUES ($1, $2, $3)"
if _, err := c.DB.Query(query, data.UUID, data.Email, passwordHash); err != nil {
log.Error(err, "Couldn't create a user in the database")
return "", err
}

View File

@@ -1,9 +1,7 @@
CREATE TABLE IF NOT EXISTS users (
uuid UUID PRIMARY KEY,
username VARCHAR(10) NOT NULL
CHECK (username ~ '^[a-z0-9]{1,10}$') UNIQUE,
email VARCHAR(255) NOT NULL
CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'),
CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$') UNIQUE,
password_hash TEXT NOT NULL,
email_verified BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP