MCPcopy Index your code
hub / github.com/chartmuseum/auth

github.com/chartmuseum/auth @v0.6.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.6.0 ↗ · + Follow
47 symbols 137 edges 8 files 8 documented · 17% 1 cross-repo links
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

chartmuseum/auth

GitHub Actions status Go Report Card GoDoc

Go library for generating ChartMuseum JWT Tokens, authorizing HTTP requests, etc.

How to Use

Generating a JWT token (example)

Source

Clone this repo and run go run testcmd/getjwt/main.go to run this example

package main

import (
    "fmt"
    "time"

    cmAuth "github.com/chartmuseum/auth"
)

func main() {

    // This should be the private key associated with the public key used
    // in ChartMuseum server configuration (server.pem)
    cmTokenGenerator, err := cmAuth.NewTokenGenerator(&cmAuth.TokenGeneratorOptions{
        PrivateKeyPath: "./testdata/server.key",
    })
    if err != nil {
        panic(err)
    }

    // Example:
    // Generate a token which allows the user to push to the "org1/repo1"
    // repository, and expires in 5 minutes
    access := []cmAuth.AccessEntry{
        {
            Name:    "org1/repo1",
            Type:    cmAuth.AccessEntryType,
            Actions: []string{cmAuth.PushAction},
        },
    }
    signedString, err := cmTokenGenerator.GenerateToken(access, time.Minute*5)
    if err != nil {
        panic(err)
    }

    // Prints a JWT token which you can use to make requests to ChartMuseum
    fmt.Println(signedString)
}

This token will be formatted as a valid JSON Web Token (JWT) and resemble the following:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NDM5NTk3OTMsImlhdCI6MTU0Mzk1OTQ5MywiYWNjZXNzIjpbeyJ0eXBlIjoiYXJ0aWZhY3QtcmVwb3NpdG9yeSIsIm5hbWUiOiJvcmcxL3JlcG8xIiwiYWN0aW9ucyI6WyJwdXNoIl19XX0.giLd83d8eK8QbTFnCLmgATV2ohiIb59dIhrg35XYFz-6EHqvirUsfZBdWXMRy2sQUOOIHouVEamv_qErKPbFQYGYureJ9BJmVKA3N2SL8aSiXaa8ZasyjRmayOqri55gNf-LE1XddtO8al6-e6vcXe_0YnkGyfw-ODej83wdoLHjB3VgLGXDdbTyXMJEs0aULmBUxbnyaGFTNWgowfqr8W3Sk64LgRvEJ3gJtTN5r_vjgDDVyMX9SIk0yvlCATN7fJvbiVotoLJTGRKV6PVRN79A16SqSGYsN3Nvym8BUwJgXLPM24ozngje1y2s6YmwOOnKItTIXwU12IqbzlmGRg

You can decode this token on https://jwt.io or with something like jwt-cli.

The decoded payload of this token will look like the following:

{
  "exp": 1543959726,
  "iat": 1543959426,
  "access": [
    {
      "type": "artifact-repository",
      "name": "org1/repo1",
      "actions": [
        "push"
      ]
    }
  ]
}

Making requests to ChartMuseum

First, obtain the token with the necessary access entries (see example above).

Then use this token to make requests to ChartMuseum, passing it in the Authorization header:

> GET /api/charts HTTP/1.1
> Host: localhost:8080
> Authorization: Bearer <token>

Validating a JWT token (example)

Source

Clone this repo and run go run testcmd/decodejwt/main.go <token> to run this example

package main

import (
    "encoding/json"
    "fmt"
    "os"

    cmAuth "github.com/chartmuseum/auth"

    "github.com/golang-jwt/jwt/v4"
)

func main() {
    signedString := os.Args[1]

    // This should be the public key associated with the private key used
    // to sign the token
    cmTokenDecoder, err := cmAuth.NewTokenDecoder(&cmAuth.TokenDecoderOptions{
        PublicKeyPath: "./testdata/server.pem",
    })
    if err != nil {
        panic(err)
    }

    token, err := cmTokenDecoder.DecodeToken(signedString)
    if err != nil {
        panic(err)
    }

    // Inspect the token claims as JSON
    c := token.Claims.(jwt.MapClaims)
    byteData, err := json.MarshalIndent(c, "", "  ")
    if err != nil {
        panic(err)
    }
    fmt.Println(string(byteData))
}

Authorizing an incoming request (example)

Source

Clone this repo and run go run testcmd/authorizer/main.go <token> to run this example

package main

import (
    "fmt"
    "os"

    cmAuth "github.com/chartmuseum/auth"
)

func main() {

    // We are grabbing this from command line, but this should be obtained
    // by inspecting the "Authorization" header of an incoming HTTP request
    signedString := os.Args[1]
    authHeader := fmt.Sprintf("Bearer %s", signedString)

    cmAuthorizer, err := cmAuth.NewAuthorizer(&cmAuth.AuthorizerOptions{
        Realm:         "https://my.site.io/oauth2/token",
        Service:       "my.site.io",
        PublicKeyPath: "./testdata/server.pem",
    })
    if err != nil {
        panic(err)
    }

    // Example:
    // Check if the auth header provided allows access to push to org1/repo1
    permissions, err := cmAuthorizer.Authorize(authHeader, cmAuth.PushAction, "org1/repo1")
    if err != nil {
        panic(err)
    }

    if permissions.Allowed {
        fmt.Println("ACCESS GRANTED")
    } else {

        // If access is not allowed, the WWWAuthenticateHeader will be populated
        // which should be sent back to the client in the "WWW-Authenticate" header
        fmt.Println("ACCESS DENIED")
        fmt.Println(fmt.Sprintf("WWW-Authenticate: %s", permissions.WWWAuthenticateHeader))
    }
}

If access denied, the WWW-Authenticate header returned will resemble the following:

WWW-Authenticate: Bearer realm="https://my.site.io/oauth2/token",service="my.site.io",scope="artifact-repository:org1/repo1:push"

Using a custom access entry type

By default, the "Type" of each claim checked for upon authorization is artifact-repository.

If you wish, you may customize this field upon construction of the Authorizer:

For example, for custom type "myartifact", you do the following:

myAuthorizer, err = NewAuthorizer(&AuthorizerOptions{
    Realm:           "https://my.site.io/oauth2/token",
    Service:         "my.site.io",
    PublicKeyPath:   myPublicKey,
    AccessEntryType: "myartifact", // <-------
})

Adding aud and iss fields to token claims

If you wish to add the aud and iss fields to token claims (Audience and Issuer), you may construct the TokenGenerator like so:

cmTokenGenerator, err := cmAuth.NewTokenGenerator(&cmAuth.TokenGeneratorOptions{
    PrivateKeyPath: "./testdata/server.key",
    Audience:       "registry.my.site.io", // <-------
    Issuer:         "auth.my.site.io",     // <-------
})

Adding kid field to token header

The kid header is a fingerprint representing the ID of the key which was used to sign the token.

If you wish to add this to generate tokens, you can do it like so:

cmTokenGenerator, err := cmAuth.NewTokenGenerator(&cmAuth.TokenGeneratorOptions{
    PrivateKeyPath: "./testdata/server.key",
    AddKIDHeader:   true, // <-------
})

Supported JWT Signing Algorithms

  • RS256

Core symbols most depended-on inside this repo

Authorize
called by 28
authorization.go
GenerateToken
called by 16
token.go
NewAuthorizer
called by 10
authorization.go
DecodeToken
called by 5
token.go
NewTokenGenerator
called by 4
token.go
NewTokenDecoder
called by 4
token.go
generateBasicAuthHeader
called by 3
util.go
getPemFromPathOrKey
called by 2
util.go

Shape

Method 19
Function 16
Struct 11
TypeAlias 1

Languages

Go100%

Modules by API surface

authorization_test.go11 symbols
token.go10 symbols
util.go8 symbols
authorization.go8 symbols
token_test.go7 symbols
testcmd/getjwt/main.go1 symbols
testcmd/decodejwt/main.go1 symbols
testcmd/authorizer/main.go1 symbols

Used by 1 indexed graphs manifest dependencies, hub-wide

For agents

$ claude mcp add auth \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact