Fetch userinfo in auth middleware

This commit is contained in:
2024-10-22 22:58:09 +08:00
parent 406031b966
commit 0f4112e08b
13 changed files with 320 additions and 150 deletions

5
pkg/nex/const.go Normal file
View File

@ -0,0 +1,5 @@
package nex
const (
ServiceTypeAuth = "id"
)

35
pkg/nex/sec/info.go Normal file
View File

@ -0,0 +1,35 @@
package sec
import (
"git.solsynth.dev/hypernet/nexus/pkg/nex"
"git.solsynth.dev/hypernet/nexus/pkg/proto"
"github.com/goccy/go-json"
)
// UserInfo is the basic of userinfo, you can add anything above it.
// Full data from id service was stored in the metadata field.
type UserInfo struct {
ID uint `json:"id"`
Name string `json:"name"`
PermNodes map[string]any `json:"perm_nodes"`
Metadata map[string]any `json:"metadata"`
}
func NewUserInfoFromProto(in *proto.UserInfo) UserInfo {
return UserInfo{
ID: uint(in.Id),
Name: in.Name,
PermNodes: nex.DecodeMap(in.PermNodes),
Metadata: nex.DecodeMap(in.Metadata),
}
}
func NewUserInfoFromBytes(in []byte) (UserInfo, error) {
var info UserInfo
err := json.Unmarshal(in, &info)
return info, err
}
func (v UserInfo) Encode() []byte {
return nex.EncodeMap(v)
}

View File

@ -0,0 +1,108 @@
package sec
import (
"crypto/ed25519"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"github.com/golang-jwt/jwt/v5"
"os"
"time"
)
type InternalTokenWriter struct {
pk *ed25519.PrivateKey
}
func NewInternalTokenWriter(fp string) (*InternalTokenWriter, error) {
rawKey, err := os.ReadFile(fp)
if err != nil {
return nil, err
}
block, _ := pem.Decode(rawKey)
if block == nil || block.Type != "PRIVATE KEY" {
return nil, fmt.Errorf("failed to decode PEM block containing private key")
}
anyPk, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
pk, ok := anyPk.(*ed25519.PrivateKey)
if !ok {
return nil, fmt.Errorf("not an Ed25519 private key")
}
return &InternalTokenWriter{
pk: pk,
}, nil
}
func (v *InternalTokenWriter) WriteUserInfoJwt(in UserInfo, audiences ...string) (string, error) {
rawData := base64.StdEncoding.EncodeToString(in.Encode())
claims := jwt.RegisteredClaims{
NotBefore: jwt.NewNumericDate(time.Now()),
IssuedAt: jwt.NewNumericDate(time.Now()),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(5 * time.Minute)),
Audience: audiences,
Issuer: "nexus",
Subject: rawData,
}
token := jwt.NewWithClaims(jwt.SigningMethodEdDSA, claims)
return token.SignedString(v.pk)
}
type InternalTokenReader struct {
pk *ed25519.PublicKey
}
func NewInternalTokenReader(fp string) (*InternalTokenReader, error) {
rawKey, err := os.ReadFile(fp)
if err != nil {
return nil, err
}
block, _ := pem.Decode(rawKey)
if block == nil || block.Type != "PUBLIC KEY" {
return nil, fmt.Errorf("failed to decode PEM block containing private key")
}
anyPk, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
pk, ok := anyPk.(*ed25519.PublicKey)
if !ok {
return nil, fmt.Errorf("not an Ed25519 public key")
}
return &InternalTokenReader{
pk: pk,
}, nil
}
func (v *InternalTokenReader) ReadUserInfoJwt(in string) (*UserInfo, error) {
token, err := jwt.ParseWithClaims(in, &jwt.RegisteredClaims{}, func(token *jwt.Token) (interface{}, error) {
return v.pk, nil
})
if err != nil {
return nil, err
}
if !token.Valid {
return nil, fmt.Errorf("invalid token")
}
claims, ok := token.Claims.(*jwt.RegisteredClaims)
if !ok {
return nil, fmt.Errorf("invalid claims")
}
rawData, err := base64.StdEncoding.DecodeString(claims.Subject)
if err != nil {
return nil, err
}
info, err := NewUserInfoFromBytes(rawData)
return &info, err
}

View File

@ -14,12 +14,12 @@ type JwtReader struct {
}
func NewJwtReader(fp string) (*JwtReader, error) {
privateKeyBytes, err := os.ReadFile(fp)
rawKey, err := os.ReadFile(fp)
if err != nil {
return nil, err
}
block, _ := pem.Decode(privateKeyBytes)
block, _ := pem.Decode(rawKey)
if block == nil || block.Type != "PUBLIC KEY" {
return nil, fmt.Errorf("failed to decode PEM block containing private key")
}

View File

@ -14,12 +14,12 @@ type JwtWriter struct {
}
func NewJwtWriter(fp string) (*JwtWriter, error) {
rawPk, err := os.ReadFile(fp)
rawKey, err := os.ReadFile(fp)
if err != nil {
return nil, err
}
block, _ := pem.Decode(rawPk)
block, _ := pem.Decode(rawKey)
if block == nil || block.Type != "PRIVATE KEY" {
return nil, fmt.Errorf("failed to decode PEM block containing private key")
}
@ -41,9 +41,5 @@ func NewJwtWriter(fp string) (*JwtWriter, error) {
func WriteJwt[T jwt.Claims](v *JwtWriter, in T) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodRS256, in)
ss, err := token.SignedString(v.key)
if err != nil {
return "", err
}
return ss, nil
return token.SignedString(v.key)
}