JWT
JSON Web Token
a Base64 encoded JSON object
with a cryptographic signature
Login
Regular Request
Inter Service
Benefits
- fewer database operations
- lower latency
- better scalability
Usable in
- URL:s
- HTTP headers (Bearer)
- HTTP body (application/jwt)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
const data =
const key = crypto.subtle.importKey("raw", key,
{ name: "HMAC", hash: { name: "SHA-" + this.length } },
false, [ "sign", "verify" ])
const signature = await crypto.subtle.sign("HMAC", await key, data)
const header = {
alg: "HS256",
typ: "JWT"
}
Issue Token
const payload = {
sub: "1234567890",
name: "John Doe",
iat: 1516239022
}
const data = Base64.encode(new TextEncoder().encode(JSON.stringify(header))) + "." +
Base64.encode(new TextEncoder().encode(JSON.stringify(payload)))
const key = crypto.subtle.importKey("raw", key,
{ name: "HMAC", hash: { name: "SHA-" + this.length } }, false,[ "sign", "verify" ])
const signature = await crypto.subtle.sign("HMAC", await key, data)
const token = data + "." + signature
Header
{
"typ":"JWT",
"alg":"HS256"
}
{
"typ":"JWT",
"alg":"RS256"
}
algorithms:
- none
- HS - HMAC
- RS - RSA
- ES
- PS
- EdDSA - CFRG Elliptic Curve Signatures - RFC8037
bit lengths:
- 256
- 384
- 512
Payload Claims
Registered Claims:
- iss - issuer
- sub - subject
- aud - audience
- exp - expiration time
- nbf - not before
- iat - issued at
- jti - JWT ID
Authly
github.com/payfunc/authly · MIT license
Benefits
- supports browser and Node.js
- verifies alg header
- encrypted properties
Drawbacks
- few users
- binary dependency when using Node.JS
Signature Algorithms
- None
- HMAC - HS256, HS384, HS512
- RSA - RS256, RS384, RS512
Usage
import * as authly from "authly"
const algorithm = authly.Algorithm.HS256(process.env.apiKeySecret)
const verifier = authly.Verifier.create("audience", algorithm)
const issuer = authly.Issuer.create("issuer", algorithm)
const token = await issuer.issue({
sub: "1234567890",
name: "John Doe",
admin: true,
iat: 1516239022,
aud: "audience"
})
const payload = await verifier.verify(token)
npm install -S authly
Property Encryption
import * as authly from "authly"
const algorithm = authly.Algorithm.HS256(process.env.apiKeySecret)
const verifier = authly.Verifier.create("audience", algorithm).add(process.env.propertySecret, "property0", "property1")
const issuer = authly.Issuer.create("issuer", algorithm).add(process.env.propertySecret, "property0", "property2")
const token = await issuer.issue(payload)
const payload = await verifier.verify(token)
Usage
Encryption
const secret = this.secret + payload.sub + payload.iat + property.join(".")
const key = new Uint8Array(await crypto.subtle.digest("SHA-512", new TextEncoder().encode(secret)))
const data = preprocess(payload[property[0]])
const processed = new Uint8Array(data.length)
for (let index = 0; index < data.length; index++)
processed[index] = data[index] ^ key[index]
result = postprocess(processed)
Limitation
property must be shorter then 512 bits
PayFunc Usage
API Key
- public vs private audience
- contains all useful merchant configuration
- property encryption for back end credentials
Signing Orders
- merchant sets number
- successfull orders signed
- public key signature
References
Authly
By Simon Mika
Authly
Authly
- 429