WIP: Start implementing the internal auth
All checks were successful
ci/woodpecker/push/build Pipeline was successful
All checks were successful
ci/woodpecker/push/build Pipeline was successful
Signed-off-by: Nikolai Rodionov <allanger@badhouseplants.net>
This commit is contained in:
13
Taskfile.yml
13
Taskfile.yml
@@ -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
|
||||
|
||||
@@ -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
2
go.mod
@@ -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
12
go.sum
@@ -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=
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user