Finish cleaning dependencies
This commit is contained in:
parent
02d6f3bd79
commit
308ff98830
@ -1,16 +1,18 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"git.javil.eu/jacob1123/budgeteer/http"
|
"git.javil.eu/jacob1123/budgeteer/http"
|
||||||
|
"git.javil.eu/jacob1123/budgeteer/jwt"
|
||||||
"git.javil.eu/jacob1123/budgeteer/postgres"
|
"git.javil.eu/jacob1123/budgeteer/postgres"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
us := &postgres.UserService{}
|
us := &postgres.UserService{}
|
||||||
|
tv := &jwt.TokenVerifier{}
|
||||||
|
|
||||||
h := &http.Handler{UserService=us}
|
h := &http.Handler{
|
||||||
|
UserService: us,
|
||||||
|
TokenVerifier: tv,
|
||||||
|
}
|
||||||
h.Serve()
|
h.Serve()
|
||||||
}
|
}
|
||||||
|
55
http/http.go
55
http/http.go
@ -2,6 +2,7 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"git.javil.eu/jacob1123/budgeteer"
|
"git.javil.eu/jacob1123/budgeteer"
|
||||||
|
|
||||||
@ -10,25 +11,30 @@ import (
|
|||||||
|
|
||||||
// Handler handles incoming requests
|
// Handler handles incoming requests
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
UserService budgeteer.UserService
|
UserService budgeteer.UserService
|
||||||
|
TokenVerifier budgeteer.TokenVerifier
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) Serve() {
|
const (
|
||||||
|
expiration = 72
|
||||||
|
authCookie = "authentication"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *Handler) Serve() {
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
|
|
||||||
router.LoadHTMLGlob("./templates/*")
|
router.LoadHTMLGlob("./templates/*")
|
||||||
router.Static("/static", "./static")
|
router.Static("/static", "./static")
|
||||||
|
|
||||||
router.GET("/", func(c *gin.Context) { c.HTML(http.StatusOK, "index", nil) })
|
router.GET("/", func(c *gin.Context) { c.HTML(http.StatusOK, "index", nil) })
|
||||||
router.GET("/login", login)
|
router.GET("/login", h.login)
|
||||||
api := router.Group("/api/v1")
|
api := router.Group("/api/v1")
|
||||||
{
|
{
|
||||||
api.GET("/logout", logout)
|
api.GET("/logout", logout)
|
||||||
api.GET("/login", func(c *gin.Context) {
|
api.GET("/login", func(c *gin.Context) {
|
||||||
c.Redirect(http.StatusPermanentRedirect, "/login")
|
c.Redirect(http.StatusPermanentRedirect, "/login")
|
||||||
})
|
})
|
||||||
api.POST("/login", loginPost)
|
api.POST("/login", h.loginPost)
|
||||||
|
|
||||||
// Unauthenticated routes
|
// Unauthenticated routes
|
||||||
api.GET("/check", func(c *gin.Context) {
|
api.GET("/check", func(c *gin.Context) {
|
||||||
@ -42,34 +48,41 @@ func (h *Handler) Serve() {
|
|||||||
r := api.Group("/restricted")
|
r := api.Group("/restricted")
|
||||||
{
|
{
|
||||||
//r.Use(middleware.JWT([]byte(secret)))
|
//r.Use(middleware.JWT([]byte(secret)))
|
||||||
r.GET("", restricted)
|
r.GET("", h.restricted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
router.Run(":1323")
|
router.Run(":1323")
|
||||||
}
|
}
|
||||||
|
|
||||||
func restricted(c *gin.Context) {
|
func (h *Handler) restricted(c *gin.Context) {
|
||||||
claims, ok := verifyLogin(c)
|
token, err := h.verifyLogin(c)
|
||||||
if !ok {
|
if err != nil {
|
||||||
c.Redirect(http.StatusTemporaryRedirect, "/login")
|
c.Redirect(http.StatusTemporaryRedirect, "/login")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
name := claims["name"].(string)
|
name := token.GetName()
|
||||||
c.String(http.StatusOK, "Welcome "+name+"!")
|
c.String(http.StatusOK, "Welcome "+name+"!")
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyLogin(c *gin.Context) error {
|
func (h *Handler) verifyLogin(c *gin.Context) (budgeteer.Token, error) {
|
||||||
tokenString, err := c.Cookie(authCookie)
|
tokenString, err := c.Cookie(authCookie)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
token, err := h.TokenVerifier.VerifyToken(tokenString)
|
||||||
|
if err != nil {
|
||||||
|
c.SetCookie(authCookie, "", -1, "", "", false, false)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func login(c *gin.Context) {
|
func (h *Handler) login(c *gin.Context) {
|
||||||
if _, ok := verifyLogin(c); ok {
|
if _, err := h.verifyLogin(c); err == nil {
|
||||||
c.Redirect(http.StatusTemporaryRedirect, "/api/v1/hello")
|
c.Redirect(http.StatusTemporaryRedirect, "/api/v1/hello")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -81,7 +94,11 @@ func logout(c *gin.Context) {
|
|||||||
clearLogin(c)
|
clearLogin(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loginPost(c *gin.Context) {
|
func clearLogin(c *gin.Context) {
|
||||||
|
c.SetCookie(authCookie, "", -1, "", "", false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) loginPost(c *gin.Context) {
|
||||||
username, _ := c.GetPostForm("username")
|
username, _ := c.GetPostForm("username")
|
||||||
password, _ := c.GetPostForm("password")
|
password, _ := c.GetPostForm("password")
|
||||||
|
|
||||||
@ -90,5 +107,15 @@ func loginPost(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
loginSuccess(c, username, "Jan Bader")
|
t, err := h.TokenVerifier.CreateToken(username, "Jan Bader")
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithStatus(http.StatusUnauthorized)
|
||||||
|
}
|
||||||
|
|
||||||
|
maxAge := (int)((expiration * time.Hour).Seconds())
|
||||||
|
c.SetCookie(authCookie, t, maxAge, "", "", false, true)
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, map[string]string{
|
||||||
|
"token": t,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
70
jwt/login.go
70
jwt/login.go
@ -2,25 +2,44 @@ package jwt
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.javil.eu/jacob1123/budgeteer"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"github.com/dgrijalva/jwt-go"
|
||||||
"gopkg.in/gin-gonic/gin.v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TokenVerifier verifies Tokens
|
||||||
|
type TokenVerifier struct {
|
||||||
|
}
|
||||||
|
type Token struct {
|
||||||
|
username string
|
||||||
|
name string
|
||||||
|
expiry float64
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
expiration = 72
|
expiration = 72
|
||||||
secret = "uditapbzuditagscwxuqdflgzpbu´ßiaefnlmzeßtrubiadern"
|
secret = "uditapbzuditagscwxuqdflgzpbu´ßiaefnlmzeßtrubiadern"
|
||||||
authCookie = "authentication"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func verifyLogin(c *gin.Context) (jwt.MapClaims, error) {
|
// CreateToken creates a new token from username and name
|
||||||
tokenString, err := c.Cookie(authCookie)
|
func (tv *TokenVerifier) CreateToken(username string, name string) (string, error) {
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||||
|
"usr": username,
|
||||||
|
"name": name,
|
||||||
|
"exp": time.Now().Add(time.Hour * expiration).Unix(),
|
||||||
|
})
|
||||||
|
|
||||||
|
// Generate encoded token and send it as response.
|
||||||
|
t, err := token.SignedString([]byte(secret))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tv *TokenVerifier) VerifyToken(tokenString string) (budgeteer.Token, error) {
|
||||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||||
@ -28,17 +47,20 @@ func verifyLogin(c *gin.Context) (jwt.MapClaims, error) {
|
|||||||
return []byte(secret), nil
|
return []byte(secret), nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.SetCookie(authCookie, "", -1, "", "", false, false)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
claims, err := verifyToken(token)
|
claims, err := verifyToken(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.SetCookie(authCookie, "", -1, "", "", false, false)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return claims, nil
|
tkn := &Token{
|
||||||
|
username: claims["usr"].(string),
|
||||||
|
name: claims["name"].(string),
|
||||||
|
expiry: claims["exp"].(float64),
|
||||||
|
}
|
||||||
|
return tkn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyToken(token *jwt.Token) (jwt.MapClaims, error) {
|
func verifyToken(token *jwt.Token) (jwt.MapClaims, error) {
|
||||||
@ -58,28 +80,14 @@ func verifyToken(token *jwt.Token) (jwt.MapClaims, error) {
|
|||||||
return claims, nil
|
return claims, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loginSuccess(c *gin.Context, username string, name string) {
|
func (t *Token) GetName() string {
|
||||||
// Create token
|
return t.name
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
|
||||||
"usr": username,
|
|
||||||
"name": name,
|
|
||||||
"exp": time.Now().Add(time.Hour * expiration).Unix(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Generate encoded token and send it as response.
|
|
||||||
t, err := token.SignedString([]byte(secret))
|
|
||||||
if err != nil {
|
|
||||||
c.AbortWithStatus(http.StatusUnauthorized)
|
|
||||||
}
|
|
||||||
|
|
||||||
maxAge := (int)((expiration * time.Hour).Seconds())
|
|
||||||
c.SetCookie(authCookie, t, maxAge, "", "", false, true)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, map[string]string{
|
|
||||||
"token": t,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearLogin(c *gin.Context) {
|
func (t *Token) GetUsername() string {
|
||||||
c.SetCookie(authCookie, "", -1, "", "", false, true)
|
return t.username
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Token) GetExpiry() float64 {
|
||||||
|
return t.expiry
|
||||||
}
|
}
|
||||||
|
9
token.go
9
token.go
@ -3,5 +3,12 @@ package budgeteer
|
|||||||
// Token contains data that authenticates a user
|
// Token contains data that authenticates a user
|
||||||
type Token interface {
|
type Token interface {
|
||||||
GetUsername() string
|
GetUsername() string
|
||||||
GetExpiry() int
|
GetName() string
|
||||||
|
GetExpiry() float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// TokenVerifier verifies a Token
|
||||||
|
type TokenVerifier interface {
|
||||||
|
VerifyToken(string) (Token, error)
|
||||||
|
CreateToken(string, string) (string, error)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user