AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Authentication

skill-jkaninda-okapi-skills-authentication · by jkaninda

A Claude skill from jkaninda/okapi-skills.

No reviews yet
0 installs
28 views
0.0% view→install

Install

$ agentstack add skill-jkaninda-okapi-skills-authentication

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-jkaninda-okapi-skills-authentication)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Authentication? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Okapi Authentication & CORS

JWT Authentication

JWTAuth extracts the token, verifies the signature, optionally enforces claims, and stores claims in the context.

jwtAuth := okapi.JWTAuth{
    SigningSecret: []byte("supersecret"),   // HMAC (HS256/384/512)
    RsaKey:        publicKey,               // RSA (RS256/384/512)
    JwksUrl:       "https://issuer.example.com/.well-known/jwks.json",
    JwksFile:      jwks,                    // from okapi.LoadJWKSFromFile(...)

    Algorithms:  []string{"RS256", "ES256"}, // accepted signing algorithms
    Audience:    "my-api",                   // expected "aud"
    Issuer:      "https://issuer.example.com", // expected "iss"
    TokenLookup: "header:Authorization,cookie:jwt", // sources, tried in order

    ContextKey: "user",                      // store the full claims under this key
    ForwardClaims: map[string]string{        // copy selected claims into the store
        "email": "user.email",
        "role":  "realm_access.roles.0",
    },

    ClaimsExpression: "Equals(`email_verified`, `true`) && OneOf(`user.role`, `admin`, `owner`)",
    ValidateClaims:   func(c *okapi.Context, claims jwt.Claims) error { return nil },
    OnUnauthorized:   func(c *okapi.Context) error { return c.ErrorUnauthorized("Nope") },
}

api := o.Group("/api", jwtAuth.Middleware).WithBearerAuth()

Configure at least one verification mechanism: SigningSecret, RsaKey, JwksUrl, or JwksFile.

| Field | Notes | |-------|-------| | SigningSecret []byte | HMAC key. Supersedes the deprecated SecretKey. | | RsaKey *rsa.PublicKey | RSA public key. | | JwksUrl string | Remote JWKS endpoint for key discovery. | | JwksFile *Jwks | Static JWKS from file or base64 (okapi.LoadJWKSFromFile). | | Algorithms []string | Accepted algorithms. Defaults to RS256, HS256, ES256. Supersedes the deprecated single-valued Algo. | | Audience / Issuer | Validated aud / iss claims. | | TokenLookup string | Comma-separated source:name list; the first non-empty hit wins. Default header:Authorization. | | ContextKey string | Key holding the full jwt.MapClaims. | | ForwardClaims map[string]string | contextKey -> claim.path (dot notation, numeric indices allowed). | | ClaimsExpression string | Expression DSL (below). | | ValidateClaims func(*Context, jwt.Claims) error | Custom validation; supersedes the deprecated ValidateRole. | | OnUnauthorized HandlerFunc | Custom response for any auth failure. |

Token sourcesheader:Authorization (a Bearer prefix is stripped), query:token, cookie:jwt. Combine them:

TokenLookup: "header:Authorization,query:token,cookie:jwt"

Status codes — a missing/expired/malformed token gives 401; a token that verifies but fails ClaimsExpression or ValidateClaims gives 403. OnUnauthorized overrides both.

Validate a token by hand (outside the middleware):

claims, err := jwtAuth.ValidateToken(c) // (jwt.MapClaims, error)

Claims Expression DSL

ClaimsExpression is a string parsed into an AST.

| Function | Description | |----------|-------------| | Equals(field, value) | Exact equality (compares against scalars and array members) | | Prefix(field, prefix) | String prefix match | | Contains(field, v1, v2, ...) | Field contains all listed values (substring or array membership) | | OneOf(field, v1, v2, ...) | Field equals any listed value |

Operators: ! (NOT), && (AND), || (OR) — && binds tighter than ||. Field names and literals use backticks; dot notation drills into nested claims.

ClaimsExpression: "Equals(`email_verified`, `true`) && (OneOf(`user.role`, `admin`, `owner`) || Contains(`tags`, `vip`))"

Programmatic equivalents (useful for composing expressions in code):

expr := okapi.And(
    okapi.Equals("email_verified", "true"),
    okapi.Or(
        okapi.OneOf("user.role", "admin", "owner"),
        okapi.Contains("tags", "vip"),
    ),
)
ok, err := expr.Evaluate(claims)          // claims is jwt.MapClaims

parsed, err := okapi.ParseExpression("Prefix(`sub`, `user_`) && !Equals(`banned`, `true`)")

Types: AndExpr, OrExpr, NotExpr, EqualsExpr, PrefixExpr, ContainsExpr, OneOfExpr — all implement Expression.

Reading Claims in a Handler

// Full claims via ContextKey
if v, ok := c.Get("user"); ok {
    claims := v.(jwt.MapClaims)
    sub, _ := claims["sub"].(string)
}

// Individual forwarded claims (stored as strings)
email := c.GetString("email")
role  := c.GetString("role")

Custom Claim Validation

jwtAuth.ValidateClaims = func(c *okapi.Context, claims jwt.Claims) error {
    mc, ok := claims.(jwt.MapClaims)
    if !ok {
        return errors.New("invalid claims type")
    }
    if v, _ := mc["email_verified"].(bool); !v {
        return errors.New("email not verified")
    }
    return nil
}

Custom Unauthorized Response

jwtAuth.OnUnauthorized = func(c *okapi.Context) error {
    return c.ErrorUnauthorized("Custom unauthorized payload")
}

Token Generation

token, err := okapi.GenerateJwtToken([]byte(secret), jwt.MapClaims{
    "sub":  "123",
    "role": "admin",
}, 24*time.Hour)

JWKS Loading

jwks, err := okapi.LoadJWKSFromFile("path/to/jwks.json") // also accepts a base64-encoded JWKS
jwtAuth.JwksFile = jwks

// Or discover keys remotely
jwtAuth.JwksUrl = "https://issuer.example.com/.well-known/jwks.json"

Jwks holds Keys []Jwk; Jwk carries Kid, Kty, N/E (RSA) and Crv/X/Y (EC).

Basic Authentication

basicAuth := okapi.BasicAuth{
    Username:   "admin",
    Password:   "secret",
    Realm:      "Admin Area",
    ContextKey: "user", // where the username is stored; default "username"
}

o.Use(basicAuth.Middleware)                              // global
admin := o.Group("/admin", basicAuth.Middleware).WithBasicAuth() // group + docs
o.Get("/dashboard", h).Use(basicAuth.Middleware)         // per route

Credentials are compared in constant time; failures return 401 with a WWW-Authenticate header. (BasicAuthMiddleware is a deprecated alias of BasicAuth.)

CORS

o.WithCORS(okapi.Cors{
    AllowedOrigins:   []string{"https://app.example.com", "https://*.example.com"},
    AllowedHeaders:   []string{"Content-Type", "Authorization"},
    AllowMethods:     []string{"GET", "POST", "PUT", "DELETE"},
    ExposeHeaders:    []string{"X-Request-ID"},
    Headers:          map[string]string{"X-Frame-Options": "DENY"}, // extra response headers
    MaxAge:           3600,  // preflight cache seconds; <= 0 omits the header
    AllowCredentials: true,
})

// As an option at construction
o := okapi.New(okapi.WithCors(corsConfig))

Origin matching:

  • "*" — any origin. With AllowCredentials: true the request origin is echoed verbatim so credentialed requests still work.
  • "https://*.example.com" — scheme + wildcard subdomain.
  • Exact origins are matched case-insensitively.

Empty AllowedHeaders / AllowMethods echo back Access-Control-Request-Headers / Access-Control-Request-Method on preflight.

Real preflights (OPTIONS with Access-Control-Request-Method) are short-circuited with 204; plain OPTIONS requests fall through to your handler. The middleware can also be attached directly as corsConfig.CORSHandler.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.