Mint and verify short-lived RS256 user tokens.

ExApps sign after AppAPI auth; Microservices check a static public key or an OIDC issuer and forward the same bearer.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-28 14:03:52 +02:00
co-authored by Cursor
parent 92feaa6915
commit f082561cc6
13 changed files with 1091 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
package usertoken
import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
)
func readPrivateKeyFile(path string) (*rsa.PrivateKey, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read private key: %w", err)
}
return parsePrivateKey(b)
}
func readPublicKeyFile(path string) (*rsa.PublicKey, error) {
b, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read public key: %w", err)
}
return parsePublicKey(b)
}
func parsePrivateKey(pemBytes []byte) (*rsa.PrivateKey, error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
return nil, fmt.Errorf("private key pem")
}
if key, err := x509.ParsePKCS1PrivateKey(block.Bytes); err == nil {
return key, nil
}
parsed, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("parse private key: %w", err)
}
key, ok := parsed.(*rsa.PrivateKey)
if !ok {
return nil, fmt.Errorf("private key is not RSA")
}
return key, nil
}
func parsePublicKey(pemBytes []byte) (*rsa.PublicKey, error) {
block, _ := pem.Decode(pemBytes)
if block == nil {
return nil, fmt.Errorf("public key pem")
}
if key, err := x509.ParsePKCS1PublicKey(block.Bytes); err == nil {
return key, nil
}
parsed, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("parse public key: %w", err)
}
key, ok := parsed.(*rsa.PublicKey)
if !ok {
return nil, fmt.Errorf("public key is not RSA")
}
return key, nil
}