Skip to content

Commit

Permalink
feat: Add support for decoding and verifying JSON Web Tokens (JWT)
Browse files Browse the repository at this point in the history
  • Loading branch information
nmaguiar committed Jul 2, 2024
1 parent bfdb298 commit 1b18492
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 0 deletions.
40 changes: 40 additions & 0 deletions src/docs/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ List of data input types that can be auto-detected (through the file extension o
| ini | INI/Properties format |
| json | A JSON format (auto-detected) |
| jsonschema | Given a JSON schema format tries to generate sample data for it |
| jwt | Decodes and/or verifies a JSON Web Token (JWT) |
| lines | A given string/text to be processed line by line |
| llm | A large language model input (uses 'llmenv' or 'llmoptions') |
| llmmodels | Lists the large language models available (using 'llmenv' or 'llmoptions') |
Expand Down Expand Up @@ -147,6 +148,7 @@ List of available formats to use with the _output_ option:
| html | An HTML format |
| ini | A INI/Properties format (arrays are not supported) |
| json | A JSON format without spacing |
| jwt | Signs map data into a JSON Web Token (JWT) |
| log | If input has Logstash compatible fields outputs a human-readable log |
| map | A rectangle map format |
| md | A Markdown format |
Expand Down Expand Up @@ -224,6 +226,20 @@ List of options to use when _in=json_:

---

### 🧾 JWT input options

List of options to use when _in=jwt_:

| Option | Type | Description |
|--------|------|-------------|
| injwtverify | Boolean | If true the boolean entry '__verified' will be added to the result. |
| injwtsecret | String | A string secret for using HS256, HS384 or HS512 depending on secret size used to verify. |
| injwtpubkey | String | A public key file used to verify (might require specifying the injwtalg). |
| injwtalg | String | Specifies the algorithm used to verify the JWT (HS* or RSA by default). Depends on available algorithms on the current JVM. |
| injwtraw | Boolean | If true it won't try to convert Unix epoch timestamps to dates. |

---

### 🧾 Lines input options

List of options to use when _in=lines_:
Expand Down Expand Up @@ -525,6 +541,30 @@ echo On the operating system: $_OAFP_os_name

---

### 🧾 JWT output options

List of options to use when _out=jwt_:

| Option | Type | Description |
|--------|------|-------------|
| jwtsecret | String | A string secret for using HS256, HS384 or HS512 depending on secret size used to sign the JWT. |
| jwtprivkey | String | A private key file used to sign (might require specifying the jwtalg). |
| jwtalg | String | Specifies the algorithm used to sign the JWT (HS* or RSA by default). Depends on available algorithms on the current JVM. |

The data map to sign can have the following entries:

* audience (String)
* claims (Map)
* expiration (Date)
* headers (Map)
* issuer (String)
* id (String)
* issuedAt (Daterrrr)
* notBefore (Date)
* subject (String)

---

### 🧾 Grid output options

List of options to use when _out=grid_:
Expand Down
30 changes: 30 additions & 0 deletions src/include/inputFns.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,36 @@ var _inputFns = new Map([
}
_$o(_r, options)
}],
["jwt", (r, options) => {
ow.loadServer()
var _r, verify
if (toBoolean(params.injwtverify)) {
if (isUnDef(params.injwtsecret) && isUnDef(params.injwtpubkey)) _exit(-1, "injwtsecret or injwtpubkey is not defined.")
try {
if (isDef(params.injwtpubkey)) {
ow.loadJava()
var c = new ow.java.cipher()
_r = ow.server.jwt.verify(c.readKey4File(params.injwtpubkey, false, params.injwtalg), r)
} else {
ow.server.jwt.verify(params.injwtsecret, r)
}
verify = true
} catch(e) {
if (isDef(e.javaException)) printErr(e.javaException.getMessage())
verify = false
}
}

_r = ow.server.jwt.decode(r)
if (isDef(verify)) _r.__verified = verify
if (!toBoolean(params.injwtraw) && isDef(_r) && isMap(_r.claims)) {
if (isDef(_r.claims.exp)) _r.claims.exp = new Date(_r.claims.exp * 1000)
if (isDef(_r.claims.iat)) _r.claims.iat = new Date(_r.claims.iat * 1000)
if (isDef(_r.claims.nbf)) _r.claims.nbf = new Date(_r.claims.nbf * 1000)

}
_$o(_r, options)
}],
["sql", (r, options) => {
if (isString(r)) {
if (toBoolean(params.sqlparse)) {
Expand Down
17 changes: 17 additions & 0 deletions src/include/outputFns.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,23 @@ var _outputFns = new Map([

_print(af.fromBytes2String(af.toBase64Bytes(io.gzip(af.fromString2Bytes(_o)))))
}],
["jwt", (r, options) => {
if (isMap(r)) {
if (isUnDef(params.jwtsecret) && isUnDef(params.jwtprivkey)) _exit(-1, "For out=jwt you need to provide a jwtsecret or a jwtprivkey")
//if (isDef(params.jwtalg)) _exit(-1, "For out=jwt you need to provide a jwtalg")
ow.loadServer()

if (isDef(params.jwtprivkey)) {
ow.loadJava()
var c = new ow.java.cipher()
_print(ow.server.jwt.sign(c.readKey4File(params.jwtprivkey, true, params.jwtalg), r))
} else {
_print(ow.server.jwt.sign(params.jwtsecret, r))
}
} else {
_exit(-1, "For out=jwt input needs to be a map.")
}
}],
["grid" , (r, options) => {
if (isUnDef(params.grid)) _exit(-1, "For out=grid you need to provide a grid=...")
let _f = _fromJSSLON(_$(params.grid, "grid").isString().$_())
Expand Down

0 comments on commit 1b18492

Please sign in to comment.