From 2f0fdd25d62bdf0297f3b2f28e51713e82718013 Mon Sep 17 00:00:00 2001 From: AKP Date: Sat, 13 Aug 2022 23:01:45 +0100 Subject: Add OIDC support Signed-off-by: AKP --- go.mod | 9 +- go.sum | 25 +++++- walrss/internal/core/users.go | 22 +++++ walrss/internal/http/auth.go | 113 ++++++++++++++++++++++++- walrss/internal/http/http.go | 28 ++++++ walrss/internal/http/views/signin.qtpl.html | 5 ++ walrss/internal/http/views/signin.qtpl.html.go | 13 ++- walrss/internal/state/state.go | 6 ++ walrss/internal/urls/urls.go | 9 +- 9 files changed, 223 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 773c7ff..19a041d 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( github.com/bwmarrin/go-alone v0.0.0-20190806015146-742bb55d1631 github.com/carlmjohnson/requests v0.22.2 + github.com/coreos/go-oidc v2.2.1+incompatible github.com/gofiber/fiber/v2 v2.31.0 github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible github.com/kkyr/fig v0.3.0 @@ -21,6 +22,7 @@ require ( github.com/valyala/fasthttp v1.34.0 github.com/valyala/quicktemplate v1.7.0 golang.org/x/crypto v0.0.0-20220214200702-86341886e292 + golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7 ) require ( @@ -31,6 +33,7 @@ require ( github.com/andybalholm/brotli v1.0.4 // indirect github.com/andybalholm/cascadia v1.1.0 // indirect github.com/fatih/color v1.13.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 // indirect github.com/huandu/xstrings v1.3.2 // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -49,6 +52,7 @@ require ( github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml v1.9.3 // indirect + github.com/pquerna/cachecontrol v0.1.0 // indirect github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect @@ -56,9 +60,12 @@ require ( github.com/valyala/tcplisten v1.0.0 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect + golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect golang.org/x/text v0.3.7 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.28.0 // indirect gopkg.in/russross/blackfriday.v2 v2.0.0 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 4fa2365..f35d214 100644 --- a/go.sum +++ b/go.sum @@ -17,6 +17,8 @@ github.com/bwmarrin/go-alone v0.0.0-20190806015146-742bb55d1631 h1:Xb5rra6jJt5Z1 github.com/bwmarrin/go-alone v0.0.0-20190806015146-742bb55d1631/go.mod h1:P86Dksd9km5HGX5UMIocXvX87sEp2xUARle3by+9JZ4= github.com/carlmjohnson/requests v0.22.2 h1:hccG5g9ITJlnDip54OVa810AkB366kthFjvA90N4owM= github.com/carlmjohnson/requests v0.22.2/go.mod h1:Hw4fFOk3xDlHQbNRTGo4oc52TUTpVEq93sNy/H+mrQM= +github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= +github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -27,7 +29,13 @@ github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYF github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofiber/fiber/v2 v2.31.0 h1:M2rWPQbD5fDVAjcoOLjKRXTIlHesI5Eq7I5FEQPt4Ow= github.com/gofiber/fiber/v2 v2.31.0/go.mod h1:1Ega6O199a3Y7yDGuM9FyXDPYQfv+7/y48wl6WCwUF4= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -86,6 +94,8 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc= +github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= @@ -132,6 +142,7 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -139,8 +150,11 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7 h1:dtndE8FcEta75/4kHF3AbpuWzV6f1LjnLrM4pe2SZrw= +golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -171,11 +185,20 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/russross/blackfriday.v2 v2.0.0 h1:+FlnIV8DSQnT7NZ43hcVKcdJdzZoeCmJj4Ql8gq5keA= gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI= +gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= diff --git a/walrss/internal/core/users.go b/walrss/internal/core/users.go index 5c17251..dfd2c86 100644 --- a/walrss/internal/core/users.go +++ b/walrss/internal/core/users.go @@ -45,12 +45,34 @@ func RegisterUser(st *state.State, email, password string) (*db.User, error) { return u, nil } +func RegisterUserOIDC(st *state.State, email string) (*db.User, error) { + u := &db.User{ + ID: shortuuid.New(), + Email: email, + } + + if _, err := st.Data.NewInsert().Model(u).Exec(context.Background()); err != nil { + if e, ok := err.(*sqlite3.Error); ok { + if e.Code == sqlite3.ErrConstraint { + return nil, NewUserError("email address in use") + } + } + return nil, err + } + + return u, nil +} + func AreUserCredentialsCorrect(st *state.State, email, password string) (bool, error) { user, err := GetUserByEmail(st, email) if err != nil { return false, err } + if len(user.Password) == 0 { + return false, nil + } + if err := bcrypt.CompareHashAndPassword(user.Password, combineStringAndSalt(password, user.Salt)); err != nil { if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) { return false, nil diff --git a/walrss/internal/http/auth.go b/walrss/internal/http/auth.go index a9ceca6..af098fa 100644 --- a/walrss/internal/http/auth.go +++ b/walrss/internal/http/auth.go @@ -1,12 +1,15 @@ package http import ( + "context" "errors" "github.com/codemicro/walrss/walrss/internal/core" "github.com/codemicro/walrss/walrss/internal/http/views" "github.com/codemicro/walrss/walrss/internal/urls" "github.com/gofiber/fiber/v2" "github.com/stevelacy/daz" + "math/rand" + "sync" "time" ) @@ -74,7 +77,8 @@ success: func (s *Server) authSignIn(ctx *fiber.Ctx) error { page := &views.SignInPage{ - Problem: ctx.Query("problem"), + Problem: ctx.Query("problem"), + OIDCEnabled: s.state.Config.OIDC.Enable, } if getCurrentUserID(ctx) != "" { @@ -127,3 +131,110 @@ incorrectUsernameOrPassword: ctx.Status(fiber.StatusUnauthorized) return views.SendPage(ctx, &views.SignInPage{Problem: "Incorrect username or password"}) } + +var ( + knownStates = make(map[string]time.Time) + stateLock sync.Mutex +) + +func init() { + rand.Seed(time.Now().Unix()) + + go func() { + time.Sleep(time.Minute * 5) + stateLock.Lock() + + var toDelete []string + + for k, v := range knownStates { + if !v.After(time.Now().UTC()) { + toDelete = append(toDelete, k) + } + } + + for _, k := range toDelete { + delete(knownStates, k) + } + + stateLock.Unlock() + }() +} + +func (s *Server) authOIDCOutbound(ctx *fiber.Ctx) error { + if !s.state.Config.OIDC.Enable { + return core.NewUserErrorWithStatus(fiber.StatusForbidden, "OIDC is disabled") + } + + b := make([]byte, 30) + for i := 0; i < len(b); i++ { + b[i] = byte(65 + rand.Intn(25)) + } + knownStates[string(b)] = time.Now().UTC().Add(time.Minute * 2) + + return ctx.Redirect(s.oauth2Config.AuthCodeURL(string(b))) +} + +func (s *Server) authOIDCCallback(ctx *fiber.Ctx) error { + if !s.state.Config.OIDC.Enable { + return core.NewUserErrorWithStatus(fiber.StatusForbidden, "OIDC is disabled") + } + + providedState := ctx.Query("state") + stateLock.Lock() + if exp, ok := knownStates[providedState]; ok && exp.After(time.Now().UTC()) { + delete(knownStates, providedState) + stateLock.Unlock() + } else { + stateLock.Unlock() + return core.NewUserError("Invalid state") + } + + oauth2Token, err := s.oauth2Config.Exchange(context.Background(), ctx.Query("code")) + if err != nil { + return err + } + + rawIDToken, ok := oauth2Token.Extra("id_token").(string) + if !ok { + return errors.New("missing ID token") + } + + idToken, err := s.oidcVerifier.Verify(context.Background(), rawIDToken) + if err != nil { + return err + } + + var claims struct { + Email string `json:"email"` + } + if err := idToken.Claims(&claims); err != nil { + return err + } + + user, err := core.GetUserByEmail(s.state, claims.Email) + if err != nil { + if errors.Is(err, core.ErrNotFound) { + if s.state.Config.Platform.DisableRegistration { + return core.NewUserError("Cannot register user on-demand as registrations are disabled.") + } + user, err = core.RegisterUserOIDC(s.state, claims.Email) + if err != nil { + return err + } + } else { + return err + } + } + + token := core.GenerateSessionToken(user.ID) + + ctx.Cookie(&fiber.Cookie{ + Name: sessionCookieKey, + Value: token, + Expires: time.Now().UTC().Add(sessionDuration), + Secure: s.state.Config.EnableSecureCookies(), + HTTPOnly: true, + }) + + return ctx.Redirect(urls.Index) +} diff --git a/walrss/internal/http/http.go b/walrss/internal/http/http.go index 36255bc..892b261 100644 --- a/walrss/internal/http/http.go +++ b/walrss/internal/http/http.go @@ -1,15 +1,19 @@ package http import ( + "context" "github.com/codemicro/walrss/walrss/internal/core" "github.com/codemicro/walrss/walrss/internal/http/views" "github.com/codemicro/walrss/walrss/internal/state" "github.com/codemicro/walrss/walrss/internal/static" "github.com/codemicro/walrss/walrss/internal/urls" + "github.com/coreos/go-oidc" "github.com/gofiber/fiber/v2" "github.com/rs/zerolog/log" "github.com/stevelacy/daz" + "golang.org/x/oauth2" "net/url" + "strings" "time" ) @@ -22,6 +26,10 @@ const ( type Server struct { state *state.State app *fiber.App + + oidcProvider *oidc.Provider + oidcVerifier *oidc.IDTokenVerifier + oauth2Config *oauth2.Config } func New(st *state.State) (*Server, error) { @@ -53,6 +61,23 @@ func New(st *state.State) (*Server, error) { app: app, } + if st.Config.OIDC.Enable { + provider, err := oidc.NewProvider(context.Background(), st.Config.OIDC.Issuer) + if err != nil { + return nil, err + } + + s.oidcProvider = provider + s.oidcVerifier = provider.Verifier(&oidc.Config{ClientID: st.Config.OIDC.ClientID}) + s.oauth2Config = &oauth2.Config{ + ClientID: st.Config.OIDC.ClientID, + ClientSecret: st.Config.OIDC.ClientSecret, + Endpoint: provider.Endpoint(), + RedirectURL: strings.TrimSuffix(st.Config.Server.ExternalURL, "/") + urls.AuthOIDCCallback, + Scopes: []string{"email", "profile", "openid"}, + } + } + s.registerHandlers() return s, nil @@ -78,6 +103,9 @@ func (s *Server) registerHandlers() { s.app.Get(urls.AuthSignIn, s.authSignIn) s.app.Post(urls.AuthSignIn, s.authSignIn) + s.app.Get(urls.AuthOIDCOutbound, s.authOIDCOutbound) + s.app.Get(urls.AuthOIDCCallback, s.authOIDCCallback) + s.app.Put(urls.EditEnabledState, s.editEnabledState) s.app.Put(urls.EditTimings, s.editTimings) diff --git a/walrss/internal/http/views/signin.qtpl.html b/walrss/internal/http/views/signin.qtpl.html index 3022f7f..b0c7d4a 100644 --- a/walrss/internal/http/views/signin.qtpl.html +++ b/walrss/internal/http/views/signin.qtpl.html @@ -3,6 +3,7 @@ {% code type SignInPage struct { BasePage Problem string + OIDCEnabled bool } %} {% func (p *SignInPage) Title() %}Sign in{% endfunc %} @@ -29,5 +30,9 @@
No account? Click here to register +
+ {% if p.OIDCEnabled %} + Click here to login with OIDC + {% endif %} {% endfunc %} \ No newline at end of file diff --git a/walrss/internal/http/views/signin.qtpl.html.go b/walrss/internal/http/views/signin.qtpl.html.go index ba433dd..35e9fb7 100644 --- a/walrss/internal/http/views/signin.qtpl.html.go +++ b/walrss/internal/http/views/signin.qtpl.html.go @@ -18,7 +18,8 @@ var ( type SignInPage struct { BasePage - Problem string + Problem string + OIDCEnabled bool } func (p *SignInPage) StreamTitle(qw422016 *qt422016.Writer) { @@ -73,6 +74,16 @@ func (p *SignInPage) StreamBody(qw422016 *qt422016.Writer) { No account? Click here to register +
+ `) + if p.OIDCEnabled { + qw422016.N().S(` + Click here to login with OIDC + `) + } + qw422016.N().S(` `) } diff --git a/walrss/internal/state/state.go b/walrss/internal/state/state.go index a65a261..227f49e 100644 --- a/walrss/internal/state/state.go +++ b/walrss/internal/state/state.go @@ -37,6 +37,12 @@ type Config struct { DisableRegistration bool `fig:"disableRegistration"` DisableSecureCookies bool `fig:"disableSecureCookies"` } + OIDC struct { + Enable bool `fig:"enable"` + ClientID string `fig:"clientID"` + ClientSecret string `fig:"clientSecret"` + Issuer string `fig:"issuer"` + } Debug bool `fig:"debug"` } diff --git a/walrss/internal/urls/urls.go b/walrss/internal/urls/urls.go index 5cf166b..5b2fc69 100644 --- a/walrss/internal/urls/urls.go +++ b/walrss/internal/urls/urls.go @@ -8,9 +8,12 @@ import ( const ( Index = "/" - Auth = "/auth" - AuthSignIn = Auth + "/signin" - AuthRegister = Auth + "/register" + Auth = "/auth" + AuthSignIn = Auth + "/signin" + AuthRegister = Auth + "/register" + AuthOIDC = Auth + "/oidc" + AuthOIDCOutbound = AuthOIDC + "/outbound" + AuthOIDCCallback = AuthOIDC + "/callback" Edit = "/edit" EditEnabledState = Edit + "/enabled" -- cgit v1.2.3-70-g09d2