Working login, register, logout

This commit is contained in:
Lilleman auf Larv 2022-04-22 16:58:02 +02:00
parent ec708a7723
commit 96e884f0a2
8 changed files with 74 additions and 29 deletions

View File

@ -9,7 +9,7 @@ services:
- POSTGRES_DB=auth - POSTGRES_DB=auth
auth-api-db-migrate: auth-api-db-migrate:
image: lilleman/auth-api-db-migrate:0.3.3 image: lilleman/auth-api-db-migrate:0.3.7
environment: environment:
- DATABASE_URL=postgres://postgres:postgres@postgres:5432/auth?sslmode=disable - DATABASE_URL=postgres://postgres:postgres@postgres:5432/auth?sslmode=disable
command: ["--wait", "up"] command: ["--wait", "up"]
@ -18,7 +18,7 @@ services:
- postgres - postgres
auth-api: auth-api:
image: lilleman/auth-api:0.3.3 image: lilleman/auth-api:0.3.7
environment: environment:
- ADMIN_API_KEY=hihi - ADMIN_API_KEY=hihi
- DATABASE_URL=postgres://postgres:postgres@postgres:5432/auth?sslmode=disable - DATABASE_URL=postgres://postgres:postgres@postgres:5432/auth?sslmode=disable

View File

@ -22,7 +22,7 @@ func (api Api) Call(method string, path string, payload []byte) (ApiRes, error)
req, err := http.NewRequest(method, api.URL+path, bytes.NewBuffer(payload)) req, err := http.NewRequest(method, api.URL+path, bytes.NewBuffer(payload))
if err != nil { if err != nil {
api.Log.Error("Could not create request", "method", method, "err", err.Error()) api.Log.Error("Could not create request", "method", method, "path", path, "err", err.Error())
return ApiRes{}, err return ApiRes{}, err
} }
req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Type", "application/json")
@ -31,22 +31,22 @@ func (api Api) Call(method string, path string, payload []byte) (ApiRes, error)
httpClient := &http.Client{} httpClient := &http.Client{}
res, err := httpClient.Do(req) res, err := httpClient.Do(req)
if err != nil { if err != nil {
api.Log.Error("Could not call backend API", "err", err.Error()) api.Log.Error("Could not call backend API", "method", method, "path", path, "err", err.Error())
return ApiRes{}, err return ApiRes{}, err
} }
defer res.Body.Close() defer res.Body.Close()
api.Log.Debug(api.URL+path+" res status", "status", res.StatusCode) api.Log.Debug("API call res status", "method", method, "path", path, "status", res.StatusCode)
respObj.StatusCode = res.StatusCode respObj.StatusCode = res.StatusCode
if strconv.Itoa(res.StatusCode)[0:1] == "5" { if strconv.Itoa(res.StatusCode)[0:1] == "5" {
api.Log.Error("API gave internal server error", "statusCode", res.StatusCode) api.Log.Error("API gave internal server error", "method", method, "path", path, "statusCode", res.StatusCode)
return ApiRes{}, errors.New("API gave internal server error") return ApiRes{}, errors.New("API gave internal server error")
} }
body, err := ioutil.ReadAll(res.Body) body, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
api.Log.Error("Could not read res body", "err", err.Error()) api.Log.Error("Could not read res body", "method", method, "path", path, "err", err.Error())
return ApiRes{}, err return ApiRes{}, err
} }

View File

@ -19,7 +19,20 @@ type LoginUser struct {
// Index GET // Index GET
func (h Handlers) Index(c *fiber.Ctx) error { func (h Handlers) Index(c *fiber.Ctx) error {
c.Set(fiber.HeaderContentType, fiber.MIMETextHTML) c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
return c.SendString(views.Index(views.IndexData{}))
user, userLoggedIn := c.Locals("user").(utils.AuthClaims)
if !userLoggedIn {
user = utils.AuthClaims{}
}
userData := views.UserData{
Name: user.AccountName,
}
return c.SendString(views.Index(views.IndexData{
UserData: userData,
UserLoggedIn: userLoggedIn,
}))
} }
// Index POST // Index POST
@ -45,8 +58,6 @@ func (h Handlers) IndexPost(c *fiber.Ctx) error {
return c.Status(500).SendString(views.Error500()) return c.Status(500).SendString(views.Error500())
} }
h.Log.Debug("API res status", "status", apiRes.StatusCode)
if apiRes.StatusCode == 200 { if apiRes.StatusCode == 200 {
err = utils.SetTokenCookies(apiRes.Body, c, h.Log) err = utils.SetTokenCookies(apiRes.Body, c, h.Log)
if err != nil { if err != nil {
@ -54,10 +65,15 @@ func (h Handlers) IndexPost(c *fiber.Ctx) error {
return c.Status(500).SendString(views.Error500()) return c.Status(500).SendString(views.Error500())
} }
userToken := c.Cookies("userToken") tokens, err := utils.ParseTokenApiResBody(apiRes.Body, h.Log)
parsed, err := utils.ParseAndValidateToken(userToken, h.Api.JwtSharedSecret, h.Log) if err != nil {
return c.Status(500).SendString(views.Error500())
}
parsed, err := utils.ParseAndValidateToken(tokens.Jwt, h.Api.JwtSharedSecret, h.Log)
if err != nil { if err != nil {
h.Log.Error("Could not parse and validate new user token after renewal", "err", err.Error()) h.Log.Error("Could not parse and validate new user token after renewal", "err", err.Error())
h.Log.Debug("Broken token", "tokens.Jwt", tokens.Jwt, "apiRes.Body", string(apiRes.Body))
return c.Status(500).SendString(views.Error500()) return c.Status(500).SendString(views.Error500())
} }
@ -66,6 +82,7 @@ func (h Handlers) IndexPost(c *fiber.Ctx) error {
return c.SendString(views.Index(views.IndexData{ return c.SendString(views.Index(views.IndexData{
OkMsg: "User logged in!", OkMsg: "User logged in!",
Title: "Dashboard", Title: "Dashboard",
UserLoggedIn: true,
})) }))
} else if strconv.Itoa(apiRes.StatusCode)[0:1] == "4" { } else if strconv.Itoa(apiRes.StatusCode)[0:1] == "4" {
var jsonResp []api.ApiResError var jsonResp []api.ApiResError

View File

@ -2,6 +2,7 @@ package handlers
import ( import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"gitlab.larvit.se/power-plan/auth-ui/src/views"
) )
// Logout // Logout
@ -10,6 +11,6 @@ func (h Handlers) LogoutPost(c *fiber.Ctx) error {
c.ClearCookie("renewalToken") c.ClearCookie("renewalToken")
c.Locals("user", "") c.Locals("user", "")
c.Redirect("/") c.Set(fiber.HeaderContentType, fiber.MIMETextHTML)
return nil return c.SendString(views.Logout())
} }

View File

@ -58,6 +58,8 @@ func (h Handlers) HandleCookieTokens(c *fiber.Ctx) error {
return c.Status(500).SendString(views.Error500()) return c.Status(500).SendString(views.Error500())
} }
h.Log.Debug("Setting new token cookies from", "apiRes.Body", apiRes.Body)
err = utils.SetTokenCookies(apiRes.Body, c, h.Log) err = utils.SetTokenCookies(apiRes.Body, c, h.Log)
if err != nil { if err != nil {
h.Log.Error("Could not unmarshal body from auth API", "err", err.Error()) h.Log.Error("Could not unmarshal body from auth API", "err", err.Error())

View File

@ -41,15 +41,15 @@ func GetLog() *zap.SugaredLogger {
return log return log
} }
type authClaims struct { type AuthClaims struct {
jwt.StandardClaims jwt.StandardClaims
AccountId string `json:"accountId"` AccountId string `json:"accountId"`
AccountFields map[string][]string `json:"accountFields"` AccountFields map[string][]string `json:"accountFields"`
AccountName string `json:"accountName"` AccountName string `json:"accountName"`
} }
func ParseAndValidateToken(token string, jwtSecret string, log *zap.SugaredLogger) (authClaims, error) { func ParseAndValidateToken(token string, jwtSecret string, log *zap.SugaredLogger) (AuthClaims, error) {
var claims authClaims var claims AuthClaims
_, err := jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) { _, err := jwt.ParseWithClaims(token, &claims, func(token *jwt.Token) (interface{}, error) {
_, ok := token.Method.(*jwt.SigningMethodHMAC) _, ok := token.Method.(*jwt.SigningMethodHMAC)
@ -65,7 +65,7 @@ func ParseAndValidateToken(token string, jwtSecret string, log *zap.SugaredLogge
} else { } else {
log.Error("could not parse token with claims", "err", err.Error()) log.Error("could not parse token with claims", "err", err.Error())
} }
return authClaims{}, err return AuthClaims{}, err
} }
return claims, nil return claims, nil
@ -76,14 +76,25 @@ type AuthRes struct {
RenewalToken string `json:"renewalToken"` RenewalToken string `json:"renewalToken"`
} }
func SetTokenCookies(apiResBody []byte, c *fiber.Ctx, log *zap.SugaredLogger) error { func ParseTokenApiResBody(apiResBody []byte, log *zap.SugaredLogger) (AuthRes, error) {
var authRes AuthRes var authRes AuthRes
err := json.Unmarshal(apiResBody, &authRes) err := json.Unmarshal(apiResBody, &authRes)
if err != nil { if err != nil {
log.Error("Could not unmarshal body from auth API", "err", err.Error()) log.Error("Could not unmarshal body from auth API", "err", err.Error())
return AuthRes{}, err
}
return authRes, nil
}
func SetTokenCookies(apiResBody []byte, c *fiber.Ctx, log *zap.SugaredLogger) error {
authRes, err := ParseTokenApiResBody(apiResBody, log)
if err != nil {
return err return err
} }
log.Debug("setting cookies", "userToken", authRes.Jwt, "len(renewalToken)", len(authRes.RenewalToken))
c.Cookie(&fiber.Cookie{ c.Cookie(&fiber.Cookie{
Name: "userToken", Name: "userToken",
Value: authRes.Jwt, Value: authRes.Jwt,

View File

@ -23,12 +23,16 @@ func Index(data IndexData) string {
if data.UserLoggedIn { if data.UserLoggedIn {
content = ` content = `
<h1 class="main-title">Welcome ` + data.UserData.Name + `</h1>` <h1 class="main-title">Welcome ` + data.UserData.Name + `</h1>
<form method="post" action="/logout">
<button type="submit">Logout</button>
</form>
`
} else { } else {
content = ` content = `
<h1 class="main-title">Login</h1> <h1 class="main-title">Login</h1>
<form method="post" class="pure-form pure-form-aligned primary-form"> <form method="post" class="pure-form pure-form-aligned primary-form">
` + vu.TernStr(len(data.OkMsg) != 0, "<p>"+data.OkMsg+" <a href=\"/\">Login</a></p>", "") + ` ` + vu.TernStr(len(data.OkMsg) != 0, "<p>"+data.OkMsg+"</p>", "") + `
<fieldset> <fieldset>
<div class="pure-control-group"> <div class="pure-control-group">
<label for="username">Username</label> <label for="username">Username</label>
@ -39,19 +43,13 @@ func Index(data IndexData) string {
<label for="password">Password</label> <label for="password">Password</label>
<input type="password" placeholder="Password" name="password" id="password" /> <input type="password" placeholder="Password" name="password" id="password" />
</div> </div>
` + vu.TernStr(len(data.ErrMsg) != 0, "<p>ERROR! "+data.ErrMsg+"<p>", "") + ` ` + vu.TernStr(len(data.ErrMsg) != 0, "<p>ERROR! "+data.ErrMsg+"<p>", "") + `
<div class="pure-controls"> <div class="pure-controls">
<a href="/register" class="pure-button">Register</a> <a href="/register" class="pure-button">Register</a>
<button type="submit" class="pure-button pure-button-primary">Login</button> <button type="submit" class="pure-button pure-button-primary">Login</button>
</div> </div>
</fieldset> </fieldset>
</form> </form>
<form method="post" action="/logout">
<button type="submit">Logout</button>
</form>
` `
} }

16
src/views/logout.go Normal file
View File

@ -0,0 +1,16 @@
package views
import (
"gitlab.larvit.se/power-plan/auth-ui/src/views/layouts"
)
func Logout() string {
content := `
<h1 class="main-title">Logged out</h1>
<a href="/">Login again</a>
`
return layouts.Default(layouts.DefaultData{
Content: content,
Title: "Logged out",
})
}