Update mjwt

This commit is contained in:
Melon 2024-11-03 10:31:12 +00:00
parent 37e7b56659
commit 130374a4ce
Signed by: melon
GPG Key ID: 6C9D970C50D26A25
6 changed files with 70 additions and 36 deletions

View File

@ -60,7 +60,7 @@ export class RestTable<T extends object> implements IPromiseLike<RestTable<T>> {
async addItem(item: T): Promise<void> {
let f = await LOGIN.clientRequest(this.apiUrl, {method: "POST", body: JSON.stringify(item)});
if (f.status !== 201) throw new Error("Unexpected status code: " + f.status);
if (f.status !== 200 && f.status !== 201) throw new Error("Unexpected status code: " + f.status);
this.rows.push(new RestItem(this, item));
this.updateSubs();
}

View File

@ -15,9 +15,13 @@
active: false,
};
let createPopup: boolean = false;
let createErrorMessage = "";
function createRoute() {
targetManagement.createItem(createItem);
createErrorMessage = "";
targetManagement.createItem(createItem).catch(x => {
createErrorMessage = x;
});
}
</script>
@ -34,6 +38,9 @@
<div><Flags bind:value={createItem.flags} editable keys={routeKeys} /></div>
<div>Active</div>
<div><input type="checkbox" bind:checked={createItem.active} /></div>
{#if createErrorMessage}
<div>{createErrorMessage}</div>
{/if}
</ActionPopup>
</div>

View File

@ -18,8 +18,8 @@
let table = new TargetTable<T>(apiUrl, (item: T) => "");
export function createItem(t: T) {
table.addItem(t);
export function createItem(t: T): Promise<void> {
return table.addItem(t);
}
function rowOrdering(rows: RestItem<T>[], domain: string): RestItem<T>[] {

View File

@ -1,18 +1,22 @@
module test_sever
go 1.21.3
go 1.23.2
require (
github.com/MrMelon54/mjwt v0.1.1
github.com/1f349/mjwt v0.4.1
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/google/uuid v1.3.1
github.com/rs/cors v1.10.1
github.com/google/uuid v1.6.0
github.com/rs/cors v1.11.1
)
require github.com/becheran/wildmatch-go v1.0.0 // indirect
require (
github.com/1f349/mjwt v0.2.1
github.com/becheran/wildmatch-go v1.0.0 // indirect
github.com/1f349/rsa-helper v0.0.2 // indirect
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/spf13/afero v1.11.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/text v0.16.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

View File

@ -1,27 +1,40 @@
github.com/1f349/mjwt v0.2.0 h1:1c3+J05RRBsClGxA91SzT3I2DkwasGA4OgLcIeXWmq4=
github.com/1f349/mjwt v0.2.0/go.mod h1:KEs6jd9JjWrQW+8feP2pGAU7pdA3aYTqjkT/YQr73PU=
github.com/1f349/mjwt v0.2.1 h1:REdiM/MaNjYQwHvI39LaMPhlvMg4Vy9SgomWMsKTNz8=
github.com/1f349/mjwt v0.2.1/go.mod h1:KEs6jd9JjWrQW+8feP2pGAU7pdA3aYTqjkT/YQr73PU=
github.com/MrMelon54/mjwt v0.1.1 h1:m+aTpxbhQCrOPKHN170DQMFR5r938LkviU38unob5Jw=
github.com/MrMelon54/mjwt v0.1.1/go.mod h1:oYrDBWK09Hju98xb+bRQ0wy+RuAzacxYvKYOZchR2Tk=
github.com/1f349/mjwt v0.4.1 h1:ooCroMMw2kcL5c9L3sLbdtxI0H4/QC8RfTxiloKr+4Y=
github.com/1f349/mjwt v0.4.1/go.mod h1:qwnzokkqc7Z9YmKA1m9beI3OZL1GvGYHOQU2rOwoV1M=
github.com/1f349/rsa-helper v0.0.2 h1:N/fLQqg5wrjIzG6G4zdwa5Xcv9/jIPutCls9YekZr9U=
github.com/1f349/rsa-helper v0.0.2/go.mod h1:VUQ++1tYYhYrXeOmVFkQ82BegR24HQEJHl5lHbjg7yg=
github.com/becheran/wildmatch-go v1.0.0 h1:mE3dGGkTmpKtT4Z+88t8RStG40yN9T+kFEGj2PZFSzA=
github.com/becheran/wildmatch-go v1.0.0/go.mod h1:gbMvj0NtVdJ15Mg/mH9uxk2R1QCistMyU7d9KFzroX4=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
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.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=
github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@ -1,7 +1,6 @@
package main
import (
"crypto/rand"
"encoding/json"
"fmt"
"log"
@ -12,7 +11,6 @@ import (
"github.com/1f349/mjwt"
"github.com/1f349/mjwt/auth"
"github.com/1f349/mjwt/claims"
"github.com/golang-jwt/jwt/v4"
"github.com/google/uuid"
"github.com/rs/cors"
@ -20,18 +18,19 @@ import (
func main() {
log.Println("Starting test server")
signer, err := mjwt.NewMJwtSignerFromFileOrCreate("Test SSO Service", "private.key.local", rand.Reader, 2048)
parentKid := uuid.NewString()
signer, err := mjwt.NewIssuer("Test SSO Service", parentKid, jwt.SigningMethodRS512)
if err != nil {
log.Fatal(err)
}
go ssoServer(signer)
go apiServer(signer)
go ssoServer(signer, parentKid)
go apiServer(signer.KeyStore())
done := make(chan struct{})
<-done
}
func ssoServer(signer mjwt.Signer) {
func ssoServer(signer *mjwt.Issuer, parentKid string) {
r := http.NewServeMux()
r.HandleFunc("/authorize", func(w http.ResponseWriter, r *http.Request) {
// request url: http://localhost:9090/authorize?response_type=token&redirect_uri=http://localhost:5173/&scope=openid%20profile%20name&client_id=b5a9a8df-827c-4925-b1c1-1940abcf356b
@ -49,17 +48,18 @@ func ssoServer(signer mjwt.Signer) {
panic("invalid client_id")
}
ps := claims.NewPermStorage()
ps := auth.NewPermStorage()
ps.Set("violet:route")
ps.Set("violet:redirect")
ps.Set("azalea:domains")
ps.Set("domain:owns=example.com")
ps.Set("domain:owns=example.org")
accessToken, err := signer.GenerateJwt("81b99bd7-bf74-4cc2-9133-80ed2393dfe6", uuid.NewString(), jwt.ClaimStrings{"b5a9a8df-827c-4925-b1c1-1940abcf356b"}, 15*time.Minute, auth.AccessTokenClaims{
accessToken, err := signer.GenerateJwt("81b99bd7-bf74-4cc2-9133-80ed2393dfe6", parentKid, jwt.ClaimStrings{"b5a9a8df-827c-4925-b1c1-1940abcf356b"}, 15*time.Minute, auth.AccessTokenClaims{
Perms: ps,
})
if err != nil {
http.Error(w, "Failed to generate access token", http.StatusInternalServerError)
log.Println("Error:", err)
return
}
v := url.Values{}
@ -103,7 +103,7 @@ var serveApiCors = cors.New(cors.Options{
AllowCredentials: true,
})
func apiServer(verify mjwt.Verifier) {
func apiServer(verify *mjwt.KeyStore) {
subdomains := []string{
"",
"www.",
@ -115,7 +115,7 @@ func apiServer(verify mjwt.Verifier) {
}
r := http.NewServeMux()
r.Handle("/v1/violet/route", hasPerm(verify, "violet:route", func(rw http.ResponseWriter, req *http.Request) {
r.Handle("GET /v1/violet/route", hasPerm(verify, "violet:route", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) {
m := make([]map[string]any, 0, len(subdomains)*2)
for _, i := range subdomains {
m = append(m, map[string]any{
@ -135,7 +135,17 @@ func apiServer(verify mjwt.Verifier) {
}
json.NewEncoder(rw).Encode(m)
}))
r.Handle("/v1/violet/redirect", hasPerm(verify, "violet:redirect", func(rw http.ResponseWriter, req *http.Request) {
r.Handle("POST /v1/violet/route", hasPerm(verify, "violet:route", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) {
j := make(map[string]any)
json.NewDecoder(req.Body).Decode(&j)
keys:= b.Claims.Perms.Search("domain:owns=*")
strings.Split() j.src
fmt.Printf("%#v\n", j)
fmt.Printf("%#v\n", b.Claims.Perms.Dump())
b.Claims.Perms.
}))
r.Handle("/v1/violet/redirect", hasPerm(verify, "violet:redirect", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) {
m := make([]map[string]any, 0, len(subdomains)*2)
for _, i := range subdomains {
m = append(m, map[string]any{
@ -157,7 +167,7 @@ func apiServer(verify mjwt.Verifier) {
}
json.NewEncoder(rw).Encode(m)
}))
r.Handle("/v1/orchid/owned", hasPerm(verify, "orchid:cert", func(rw http.ResponseWriter, req *http.Request) {
r.Handle("/v1/orchid/owned", hasPerm(verify, "orchid:cert", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) {
m := make([]map[string]any, 0, len(subdomains)*2)
for i := 0; i < len(subdomains); i++ {
u := subdomains[i] + "example.com"
@ -191,7 +201,7 @@ func apiServer(verify mjwt.Verifier) {
}
json.NewEncoder(rw).Encode(m)
}))
r.Handle("/v1/azalea/domains", hasPerm(verify, "domains:manage", func(rw http.ResponseWriter, req *http.Request) {
r.Handle("/v1/azalea/domains", hasPerm(verify, "domains:manage", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) {
type Zone struct {
ID int64 `json:"id"`
Name string `json:"name"`
@ -201,7 +211,7 @@ func apiServer(verify mjwt.Verifier) {
{ID: 2, Name: "example.org."},
})
}))
r.Handle("/v1/azalea/domains/example.com/records", hasPerm(verify, "domains:manage", func(rw http.ResponseWriter, req *http.Request) {
r.Handle("/v1/azalea/domains/example.com/records", hasPerm(verify, "domains:manage", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) {
fmt.Fprintln(rw, `[
{
"Hdr": {
@ -261,7 +271,7 @@ func apiServer(verify mjwt.Verifier) {
}
]`)
}))
r.Handle("/v1/azalea/domains/example.org/records", hasPerm(verify, "domains:manage", func(rw http.ResponseWriter, req *http.Request) {
r.Handle("/v1/azalea/domains/example.org/records", hasPerm(verify, "domains:manage", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) {
fmt.Fprintln(rw, `[
{
"Hdr": {
@ -331,7 +341,7 @@ func apiServer(verify mjwt.Verifier) {
}
]`)
}))
r.Handle("/v1/sites", hasPerm(verify, "sites:manage", func(rw http.ResponseWriter, req *http.Request) {
r.Handle("/v1/sites", hasPerm(verify, "sites:manage", func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims]) {
if req.Method == http.MethodPost {
defer req.Body.Close()
dec := json.NewDecoder(req.Body)
@ -372,7 +382,7 @@ func apiServer(verify mjwt.Verifier) {
log.Println("[API Server]", http.ListenAndServe(":9090", r))
}
func hasPerm(verify mjwt.Verifier, perm string, next func(rw http.ResponseWriter, req *http.Request)) http.Handler {
func hasPerm(verify *mjwt.KeyStore, perm string, next func(rw http.ResponseWriter, req *http.Request, b mjwt.BaseTypeClaims[auth.AccessTokenClaims])) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
a := req.Header.Get("Authorization")
if !strings.HasPrefix(a, "Bearer ") {
@ -385,10 +395,10 @@ func hasPerm(verify mjwt.Verifier, perm string, next func(rw http.ResponseWriter
log.Println("Invalid token:", err)
return
}
if !b.Claims.Perms.Has("violet:route") {
if !b.Claims.Perms.Has(perm) {
http.Error(rw, "Missing permission", http.StatusForbidden)
return
}
next(rw, req)
next(rw, req, b)
})
}