Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
9c5865df00 | |||
9c05d2f38a | |||
67716a883d | |||
4afa9a01b6 |
@ -13,11 +13,21 @@ import (
|
|||||||
"git.t-juice.club/microfilm/auth"
|
"git.t-juice.club/microfilm/auth"
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ctxType string
|
||||||
|
|
||||||
|
var ctxKeyClaims ctxType = "claims"
|
||||||
|
|
||||||
|
var ErrNoClaimsInRequest = fmt.Errorf("no claims in request")
|
||||||
|
|
||||||
func VerifyToken(authURL string, permittedRoles []string) func(http.Handler) http.Handler {
|
func VerifyToken(authURL string, permittedRoles []string) func(http.Handler) http.Handler {
|
||||||
fn := func(next http.Handler) http.Handler {
|
fn := func(next http.Handler) http.Handler {
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx, span := otel.GetTracerProvider().Tracer("").Start(r.Context(), "verify-token")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
authHeader := r.Header.Get("Authorization")
|
authHeader := r.Header.Get("Authorization")
|
||||||
if !strings.Contains(authHeader, "Bearer ") {
|
if !strings.Contains(authHeader, "Bearer ") {
|
||||||
// No token, pass if unathorized in permitted
|
// No token, pass if unathorized in permitted
|
||||||
@ -40,7 +50,7 @@ func VerifyToken(authURL string, permittedRoles []string) func(http.Handler) htt
|
|||||||
|
|
||||||
// Fetch current pubkey
|
// Fetch current pubkey
|
||||||
url := fmt.Sprintf("%s/key", authURL)
|
url := fmt.Sprintf("%s/key", authURL)
|
||||||
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||||
@ -124,7 +134,7 @@ func VerifyToken(authURL string, permittedRoles []string) func(http.Handler) htt
|
|||||||
|
|
||||||
// Add claims to request context
|
// Add claims to request context
|
||||||
if claims, ok := token.Claims.(*auth.MicrofilmClaims); ok && token.Valid {
|
if claims, ok := token.Claims.(*auth.MicrofilmClaims); ok && token.Valid {
|
||||||
ctx := context.WithValue(r.Context(), "claims", claims)
|
ctx := context.WithValue(r.Context(), ctxKeyClaims, claims)
|
||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -136,3 +146,13 @@ func VerifyToken(authURL string, permittedRoles []string) func(http.Handler) htt
|
|||||||
|
|
||||||
return fn
|
return fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ClaimsFromCtx(ctx context.Context) (*auth.MicrofilmClaims, error) {
|
||||||
|
rawValue := ctx.Value(ctxKeyClaims)
|
||||||
|
value, ok := rawValue.(*auth.MicrofilmClaims)
|
||||||
|
if ok {
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, ErrNoClaimsInRequest
|
||||||
|
}
|
||||||
|
31
authmw/token_test.go
Normal file
31
authmw/token_test.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package authmw
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.t-juice.club/microfilm/auth"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestClaimsFromContext(t *testing.T) {
|
||||||
|
claims := &auth.MicrofilmClaims{
|
||||||
|
Role: "admin",
|
||||||
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
|
Issuer: "test",
|
||||||
|
Subject: "subject",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(context.Background(), ctxKeyClaims, claims)
|
||||||
|
|
||||||
|
retrieved, err := ClaimsFromCtx(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to retrieve claims")
|
||||||
|
}
|
||||||
|
|
||||||
|
if diff := cmp.Diff(claims, retrieved); diff != "" {
|
||||||
|
t.Fatalf("Claims diff: %s", diff)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
3
go.mod
3
go.mod
@ -6,8 +6,10 @@ require (
|
|||||||
git.t-juice.club/microfilm/users v0.1.2
|
git.t-juice.club/microfilm/users v0.1.2
|
||||||
github.com/go-chi/chi/v5 v5.0.10
|
github.com/go-chi/chi/v5 v5.0.10
|
||||||
github.com/golang-jwt/jwt/v5 v5.0.0
|
github.com/golang-jwt/jwt/v5 v5.0.0
|
||||||
|
github.com/google/go-cmp v0.6.0
|
||||||
github.com/google/uuid v1.3.1
|
github.com/google/uuid v1.3.1
|
||||||
github.com/nats-io/nats.go v1.31.0
|
github.com/nats-io/nats.go v1.31.0
|
||||||
|
github.com/nats-io/nkeys v0.4.5
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0
|
github.com/pelletier/go-toml/v2 v2.1.0
|
||||||
github.com/urfave/cli/v2 v2.25.7
|
github.com/urfave/cli/v2 v2.25.7
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0
|
||||||
@ -26,7 +28,6 @@ require (
|
|||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.0 // indirect
|
github.com/klauspost/compress v1.17.0 // indirect
|
||||||
github.com/nats-io/nkeys v0.4.5 // indirect
|
|
||||||
github.com/nats-io/nuid v1.0.1 // indirect
|
github.com/nats-io/nuid v1.0.1 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
|
4
go.sum
4
go.sum
@ -24,8 +24,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
|||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
ListenAddr = ":8082"
|
ListenAddr = ":8082"
|
||||||
NATSAddr = "nats:4222"
|
UserServiceBaseURL = "http://mf-users:8080"
|
||||||
BaseSubject = "microfilm.auth.v1"
|
|
||||||
|
|
||||||
UserServiceBaseURL = "http://mf-users:8080"
|
[NATS]
|
||||||
|
Enabled = true
|
||||||
|
Addr = "nats://nats1:4222,nats://nats2:4222,nats://nats3:4222"
|
||||||
|
NKeySeed = "SUAOUHJPINF4CK6TSNZMRR5G4DKGW5S76XRNIYURPEISNMWXJIXSVWIO7Y"
|
||||||
|
Subject = "microfilm.auth.v1"
|
@ -7,13 +7,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ListenAddr string `toml:"ListenAddr"`
|
ListenAddr string `toml:"ListenAddr"`
|
||||||
NATSAddr string `toml:"NATSAddr"`
|
NATS *NATSConfig `toml:"NATS"`
|
||||||
BaseSubject string `toml:"BaseSubject"`
|
BaseSubject string `toml:"BaseSubject"`
|
||||||
|
|
||||||
UserServiceBaseURL string `toml:"UserServiceBaseURL"`
|
UserServiceBaseURL string `toml:"UserServiceBaseURL"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NATSConfig struct {
|
||||||
|
Enabled bool `toml:"Enabled"`
|
||||||
|
NKeySeed string `toml:"NKeySeed"`
|
||||||
|
Addr string `toml:"Addr"`
|
||||||
|
Subject string `toml:"Subject"`
|
||||||
|
}
|
||||||
|
|
||||||
func ConfigFromReader(r io.Reader) (*Config, error) {
|
func ConfigFromReader(r io.Reader) (*Config, error) {
|
||||||
decoder := toml.NewDecoder(r)
|
decoder := toml.NewDecoder(r)
|
||||||
var c Config
|
var c Config
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/nats-io/nats.go"
|
"github.com/nats-io/nats.go"
|
||||||
|
"github.com/nats-io/nkeys"
|
||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
|
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
|
||||||
"go.opentelemetry.io/otel/propagation"
|
"go.opentelemetry.io/otel/propagation"
|
||||||
@ -72,16 +73,34 @@ func NewServer(config *Config) (*Server, error) {
|
|||||||
|
|
||||||
srv.store = store.NewMemoryAuthStore()
|
srv.store = store.NewMemoryAuthStore()
|
||||||
|
|
||||||
conn, err := nats.Connect(config.NATSAddr)
|
if config.NATS.Enabled {
|
||||||
if err != nil {
|
var opts []nats.Option
|
||||||
return nil, err
|
if config.NATS.NKeySeed != "" {
|
||||||
}
|
keys, err := nkeys.FromSeed([]byte(config.NATS.NKeySeed))
|
||||||
encoded, err := nats.NewEncodedConn(conn, "json")
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
|
pubkey, err := keys.PublicKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
srv.Logger.Debug("NATS enabled with NKeys", "pubkey", pubkey)
|
||||||
|
creds := nats.Nkey(pubkey, keys.Sign)
|
||||||
|
opts = append(opts, creds)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := nats.Connect(config.NATS.Addr, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
encoded, err := nats.NewEncodedConn(conn, "json")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
srv.nats = encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
srv.nats = encoded
|
|
||||||
srv.userClient = NewUserClient(config.UserServiceBaseURL)
|
srv.userClient = NewUserClient(config.UserServiceBaseURL)
|
||||||
|
|
||||||
// Generate keys
|
// Generate keys
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
const Version = "v0.1.4"
|
const Version = "v0.1.6"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user