snapshot of https://github.com/mountain-loop/yaak.git (main, 2026-09-23; blobs > 131072B omitted)
This commit is contained in:
54
plugins/auth-jwt/README.md
Normal file
54
plugins/auth-jwt/README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# JSON Web Token (JWT) Authentication
|
||||
|
||||
A [JSON Web Token](https://datatracker.ietf.org/doc/html/rfc7519) (JWT) authentication
|
||||
plugin that supports token generation, signing, and automatic header management.
|
||||
|
||||

|
||||
|
||||
## Overview
|
||||
|
||||
This plugin provides JWT authentication support for API requests. JWT is a compact,
|
||||
URL-safe means of representing claims between two parties, commonly used for
|
||||
authentication and information exchange in modern web applications and APIs.
|
||||
|
||||
## How JWT Authentication Works
|
||||
|
||||
JWT authentication involves creating a signed token containing claims about the user or
|
||||
application. The token is sent in the `Authorization` header:
|
||||
|
||||
```
|
||||
Authorization: Bearer <jwt-token>
|
||||
```
|
||||
|
||||
A JWT consists of three parts separated by dots:
|
||||
|
||||
- **Header**: Contains the token type and signing algorithm
|
||||
- **Payload**: Contains the claims (user data, permissions, expiration, etc.)
|
||||
- **Signature**: Ensures the token hasn't been tampered with
|
||||
|
||||
## Usage
|
||||
|
||||
1. Configure the request, folder, or workspace to use JWT Authentication
|
||||
2. Set up your signing algorithm and secret/key
|
||||
3. Add custom JWT header fields if needed
|
||||
4. Configure the required claims for your JWT payload
|
||||
5. The plugin will generate, sign, and include the JWT in your requests
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
JWT authentication is commonly used for:
|
||||
|
||||
- **Microservices Authentication**: Service-to-service communication
|
||||
- **API Gateway Integration**: Authenticating with API gateways
|
||||
- **Single Sign-On (SSO)**: Sharing authentication across applications
|
||||
- **Stateless Authentication**: No server-side session storage required
|
||||
- **Mobile App APIs**: Secure authentication for mobile applications
|
||||
- **Third-party Integrations**: Authenticating with external services
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Invalid Signature**: Check your secret/key and algorithm configuration
|
||||
- **Token Expired**: Verify expiration time settings
|
||||
- **Invalid Claims**: Ensure required claims are properly configured
|
||||
- **Algorithm Mismatch**: Verify the algorithm matches what the API expects
|
||||
- **Key Format Issues**: Ensure RSA keys are in the correct PEM format
|
||||
22
plugins/auth-jwt/package.json
Normal file
22
plugins/auth-jwt/package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "@yaak/auth-jwt",
|
||||
"displayName": "JSON Web Tokens",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "Authenticate requests using JSON web tokens (JWT)",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mountain-loop/yaak.git",
|
||||
"directory": "plugins/auth-jwt"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "yaakcli build",
|
||||
"dev": "yaakcli dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonwebtoken": "^9.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jsonwebtoken": "^9.0.7"
|
||||
}
|
||||
}
|
||||
148
plugins/auth-jwt/src/index.ts
Normal file
148
plugins/auth-jwt/src/index.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import type { PluginDefinition } from "@yaakapp/api";
|
||||
import jwt from "jsonwebtoken";
|
||||
|
||||
const algorithms = [
|
||||
"HS256",
|
||||
"HS384",
|
||||
"HS512",
|
||||
"RS256",
|
||||
"RS384",
|
||||
"RS512",
|
||||
"PS256",
|
||||
"PS384",
|
||||
"PS512",
|
||||
"ES256",
|
||||
"ES384",
|
||||
"ES512",
|
||||
"none",
|
||||
] as const;
|
||||
|
||||
const defaultAlgorithm = algorithms[0];
|
||||
|
||||
export const plugin: PluginDefinition = {
|
||||
authentication: {
|
||||
name: "jwt",
|
||||
label: "JWT Bearer",
|
||||
shortLabel: "JWT",
|
||||
args: [
|
||||
{
|
||||
type: "select",
|
||||
name: "algorithm",
|
||||
label: "Algorithm",
|
||||
hideLabel: true,
|
||||
defaultValue: defaultAlgorithm,
|
||||
options: algorithms.map((value) => ({ label: value === "none" ? "None" : value, value })),
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "secret",
|
||||
label: "Secret or Private Key",
|
||||
password: true,
|
||||
optional: true,
|
||||
multiLine: true,
|
||||
},
|
||||
{
|
||||
type: "checkbox",
|
||||
name: "secretBase64",
|
||||
label: "Secret is base64 encoded",
|
||||
},
|
||||
{
|
||||
type: "editor",
|
||||
name: "payload",
|
||||
label: "JWT Payload",
|
||||
language: "json",
|
||||
defaultValue: '{\n "foo": "bar"\n}',
|
||||
placeholder: "{ }",
|
||||
},
|
||||
{
|
||||
type: "accordion",
|
||||
label: "Advanced",
|
||||
inputs: [
|
||||
{
|
||||
type: "editor",
|
||||
name: "headers",
|
||||
label: "JWT Header",
|
||||
description: "Merged with auto-generated header fields like alg (e.g., kid)",
|
||||
language: "json",
|
||||
defaultValue: "{}",
|
||||
placeholder: "{ }",
|
||||
optional: true,
|
||||
},
|
||||
{
|
||||
type: "select",
|
||||
name: "location",
|
||||
label: "Behavior",
|
||||
defaultValue: "header",
|
||||
options: [
|
||||
{ label: "Insert Header", value: "header" },
|
||||
{ label: "Append Query Parameter", value: "query" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "h_stack",
|
||||
inputs: [
|
||||
{
|
||||
type: "text",
|
||||
name: "name",
|
||||
label: "Header Name",
|
||||
defaultValue: "Authorization",
|
||||
optional: true,
|
||||
description: "The name of the header to add to the request",
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "headerPrefix",
|
||||
label: "Header Prefix",
|
||||
optional: true,
|
||||
defaultValue: "Bearer",
|
||||
},
|
||||
],
|
||||
dynamic(_ctx, args) {
|
||||
if (args.values.location === "query") {
|
||||
return {
|
||||
hidden: true,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
name: "name",
|
||||
label: "Parameter Name",
|
||||
description: "The name of the query parameter to add to the request",
|
||||
defaultValue: "token",
|
||||
optional: true,
|
||||
dynamic(_ctx, args) {
|
||||
if (args.values.location !== "query") {
|
||||
return {
|
||||
hidden: true,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
async onApply(_ctx, { values }) {
|
||||
const { algorithm, secret: _secret, secretBase64, payload, headers } = values;
|
||||
const secret = secretBase64 ? Buffer.from(`${_secret}`, "base64") : `${_secret}`;
|
||||
|
||||
const parsedHeaders = headers ? JSON.parse(`${headers}`) : undefined;
|
||||
|
||||
const token = jwt.sign(`${payload}`, secret, {
|
||||
algorithm: algorithm as (typeof algorithms)[number],
|
||||
// Extra header fields are merged with the auto-generated header (which includes alg)
|
||||
header: parsedHeaders as jwt.JwtHeader | undefined,
|
||||
});
|
||||
|
||||
if (values.location === "query") {
|
||||
const paramName = String(values.name || "token");
|
||||
return { setQueryParameters: [{ name: paramName, value: token }] };
|
||||
}
|
||||
const headerPrefix = values.headerPrefix != null ? values.headerPrefix : "Bearer";
|
||||
const headerName = String(values.name || "Authorization");
|
||||
const headerValue = `${headerPrefix} ${token}`.trim();
|
||||
return { setHeaders: [{ name: headerName, value: headerValue }] };
|
||||
},
|
||||
},
|
||||
};
|
||||
3
plugins/auth-jwt/tsconfig.json
Normal file
3
plugins/auth-jwt/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json"
|
||||
}
|
||||
Reference in New Issue
Block a user