initiate keycloak token checking
This commit is contained in:
+7
-1
@@ -29,4 +29,10 @@ DB_ANTRIAN_PASSWORD=stim*RS54
|
||||
DB_ANTRIAN_HOST=10.10.123.165
|
||||
DB_ANTRIAN_DATABASE=satu_db
|
||||
DB_ANTRIAN_PORT=5000
|
||||
DB_ANTRIAN_SSLMODE=disable
|
||||
DB_ANTRIAN_SSLMODE=disable
|
||||
|
||||
#KEYCLOAK CREDENTIAL
|
||||
KEYCLOAK_BASE_URL=https://keycloak.example.com
|
||||
KEYCLOAK_REALM=myrealm
|
||||
KEYCLOAK_AUDIENCE=my-client-id
|
||||
KEYCLOAK_ISSUER=https://keycloak.example.com/realms/myrealm
|
||||
@@ -5,6 +5,7 @@ go 1.25.3
|
||||
require (
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/Masterminds/squirrel v1.5.4 // indirect
|
||||
github.com/MicahParks/keyfunc v1.9.0 // indirect
|
||||
github.com/bytedance/sonic v1.14.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
@@ -21,6 +22,7 @@ require (
|
||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
|
||||
@@ -3,6 +3,8 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc
|
||||
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
||||
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
|
||||
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||
github.com/MicahParks/keyfunc v1.9.0 h1:lhKd5xrFHLNOWrDc4Tyb/Q1AJ4LCzQ48GVJyVIID3+o=
|
||||
github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x95xuVNtM5jw=
|
||||
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
||||
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
||||
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||
@@ -45,6 +47,8 @@ github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/MicahParks/keyfunc"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
func AuthKeycloak() (gin.HandlerFunc, error) {
|
||||
baseURL := os.Getenv("KEYCLOAK_BASE_URL")
|
||||
realm := os.Getenv("KEYCLOAK_REALM")
|
||||
audience := os.Getenv("KEYCLOAK_AUDIENCE")
|
||||
issuer := os.Getenv("KEYCLOAK_ISSUER")
|
||||
|
||||
jwksURL := fmt.Sprintf(
|
||||
"%s/realms/%s/protocol/openid-connect/certs",
|
||||
baseURL,
|
||||
realm,
|
||||
)
|
||||
|
||||
jwks, err := keyfunc.Get(jwksURL, keyfunc.Options{
|
||||
RefreshInterval: time.Hour,
|
||||
RefreshErrorHandler: func(err error) {
|
||||
fmt.Println("JWKS refresh error:", err)
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return func(c *gin.Context) {
|
||||
auth := c.GetHeader("Authorization")
|
||||
if auth == "" {
|
||||
c.AbortWithStatusJSON(401, gin.H{"message": "missing token"})
|
||||
return
|
||||
}
|
||||
|
||||
tokenStr := strings.TrimPrefix(auth, "Bearer ")
|
||||
|
||||
token, err := jwt.Parse(tokenStr, jwks.Keyfunc)
|
||||
if err != nil || !token.Valid {
|
||||
c.AbortWithStatusJSON(401, gin.H{"message": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
log.Println(claims)
|
||||
|
||||
// validate issuer
|
||||
if claims["iss"] != issuer {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid issuer"})
|
||||
return
|
||||
}
|
||||
|
||||
// validate audience
|
||||
if !claims.VerifyAudience(audience, true) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "invalid audience"})
|
||||
return
|
||||
}
|
||||
|
||||
c.Set("claims", claims)
|
||||
|
||||
c.Next()
|
||||
}, nil
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"antrian-operasi/internal/domain/reference/spesialis"
|
||||
"antrian-operasi/internal/domain/reference/tindakan"
|
||||
"antrian-operasi/internal/middleware"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -34,7 +35,12 @@ func RegisterRoutes(cfg *config.Config, dbService database.Service) *gin.Engine
|
||||
// init middleware
|
||||
router.Use(middleware.SecureCORSConfig(cfg.Security))
|
||||
|
||||
api := router.Group("/api")
|
||||
authKeycloak, err := middleware.AuthKeycloak()
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to initiate keycloak auth")
|
||||
}
|
||||
|
||||
api := router.Group("/api", authKeycloak)
|
||||
|
||||
antrian := api.Group("/antrian-operasi")
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user