Compare commits

..

No commits in common. "master" and "v0.1.4" have entirely different histories.

8 changed files with 20 additions and 101 deletions

View File

@ -13,21 +13,11 @@ 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
@ -50,7 +40,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(ctx, 5*time.Second) ctx, cancel := context.WithTimeout(r.Context(), 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)
@ -134,7 +124,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(), ctxKeyClaims, claims) ctx := context.WithValue(r.Context(), "claims", claims)
next.ServeHTTP(w, r.WithContext(ctx)) next.ServeHTTP(w, r.WithContext(ctx))
return return
} }
@ -146,13 +136,3 @@ 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
}

View File

@ -1,31 +0,0 @@
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
View File

@ -6,10 +6,8 @@ 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
@ -28,6 +26,7 @@ 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
View File

@ -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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/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=

View File

@ -1,8 +1,5 @@
ListenAddr = ":8082" ListenAddr = ":8082"
UserServiceBaseURL = "http://mf-users:8080" NATSAddr = "nats:4222"
BaseSubject = "microfilm.auth.v1"
[NATS] UserServiceBaseURL = "http://mf-users:8080"
Enabled = true
Addr = "nats://nats1:4222,nats://nats2:4222,nats://nats3:4222"
NKeySeed = "SUAOUHJPINF4CK6TSNZMRR5G4DKGW5S76XRNIYURPEISNMWXJIXSVWIO7Y"
Subject = "microfilm.auth.v1"

View File

@ -7,20 +7,13 @@ import (
) )
type Config struct { type Config struct {
ListenAddr string `toml:"ListenAddr"` ListenAddr string `toml:"ListenAddr"`
NATS *NATSConfig `toml:"NATS"` NATSAddr string `toml:"NATSAddr"`
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

View File

@ -20,7 +20,6 @@ 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"
@ -73,34 +72,16 @@ func NewServer(config *Config) (*Server, error) {
srv.store = store.NewMemoryAuthStore() srv.store = store.NewMemoryAuthStore()
if config.NATS.Enabled { conn, err := nats.Connect(config.NATSAddr)
var opts []nats.Option if err != nil {
if config.NATS.NKeySeed != "" { return nil, err
keys, err := nkeys.FromSeed([]byte(config.NATS.NKeySeed)) }
if err != nil { encoded, err := nats.NewEncodedConn(conn, "json")
return nil, err if err != nil {
} 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

View File

@ -1,3 +1,3 @@
package auth package auth
const Version = "v0.1.6" const Version = "v0.1.4"