1 module ddata.jwt.encode; 2 3 import std.json; 4 import std.base64; 5 6 import ddata.jwt.algorithm; 7 import ddata.jwt.sign; 8 9 /** 10 Encodes a jwt with the current payload and specified algorithm 11 */ 12 public string encode(const JSONValue payload, string key, Algorithm algorithm = Algorithm.hs256, JSONValue header = null) @safe { 13 return encode(cast(ubyte[]) payload.toString().dup, key, algorithm, header); 14 } 15 16 private string encode(const(ubyte)[] payload, string key, Algorithm algorithm = Algorithm.hs256, JSONValue header = null) @safe { 17 if (header.type == JSONType.null_) { 18 header = (JSONValue[string]).init; 19 } 20 header["alg"] = cast(string) algorithm; 21 header["typ"] = "JWT"; 22 const headerString = header.toString; 23 24 const encodedHeader = Base64URLNoPadding.encode(cast(ubyte[])headerString.dup); 25 const encodedPayload = Base64URLNoPadding.encode(payload); 26 27 const signingInput = encodedHeader ~ "." ~ encodedPayload; 28 const signatureInput = sign(signingInput.idup, key, algorithm); 29 const signature = Base64URLNoPadding.encode(cast(ubyte[])signatureInput.dup); 30 31 return (signingInput ~ "." ~ signature).idup; 32 } 33 34 @("should encode json data in to jwt with private rsa key") 35 @safe unittest { 36 immutable key = q"EOS 37 -----BEGIN RSA PRIVATE KEY----- 38 MIIEpQIBAAKCAQEAx80KNM7esDMCGwcLkJfvhLKBZtE1WuS+Q49jNSRDJt/nR2jS 39 0X3lkrT5rTR2l3JQiQ2a7X5mXznOiv/zgs07/wxnBFiCm93NTgaoP/iyRt7oiuN4 40 lwnQd4x8VlPPFt8+FEAF8LjmesqOFxvb2utXhnm72gBiV0KVcT8OJ880jyyn/sx+ 41 lm2KAQE1dtDLPv2iR+oHeX34pHdaF2Pn5LvmkYLutFUB/jWbhUS6G5grns5QvCPF 42 7iI9KvplOn9n/cGNjGuu+686Sa4eWR96jsTi3ubvZpPio13rgaPpj3bp0NiQgOn5 43 OtPFiE/tqBuJRFnRL8rKsJeIV2RriqtyyPX/qQIDAQABAoIBAQCQw2LtuCVpDMwt 44 wQEEFtGYF63iTRqXbLzePnnm+wsck4YDG1QELW+0yCNO94AlYtIvOwhRow+RV1Tr 45 KV/KGeGqfdX2NBsNy7sBGZm2H/8rkj5ywzWQWbANrmA4PCkDrWRRT8H+FDoKJdCl 46 ta2qBHI6IOGWpkiaaMfWcZVUCrFOOgcJwz0FGUiH++gfRyOTiXmTd2VK6Yx8K3o5 47 PyETxOFb5Ct4OUvhWerxz6VW5s1wE9rUMjinTgkhBFNK0ya+Tilihq8sPWRq3C75 48 kBsW8gKOE9quOWYHslXHIEmhCdf36SoZPEzb3GLHuPPvXtMo2PG7EU7SqnnBw9qU 49 IBi2qlIBAoGBAPzVFjGAn1oQeP7j5ATW2bf/hmLFaDZtazO2d38K1MIBm0IftYPv 50 /33QM9GtnkGbApD7bKB28TgZ4tz/RxVu0T4CAU1Xnk+HMZZvaIUlMXQayhZMudFs 51 UCql1t0vZYV+7DinODlEBYu0J9Gxs+Xtu+GvsP9wGJIkpHOB8tn5vurZAoGBAMpN 52 3VcyihNhZtnvNMmKd2NNJl9m8+IOuIdld2fzjg0S0Z3Oadv6pGCKB5MlsGWLzOXb 53 sBGCdJ/NSIFFNouyu2Q3zI70gEalwieogbBuOmHOEBPPy/DRetfybumP2/KvCRQk 54 9yKfsnqWnHSB35dknLbIsbtbylnqC4gGVaE/gplRAoGATxEYWqy9qL3ECPodocHK 55 3nbDgPn5KCQ5xTdH0WwCsxUrh5dA/Zy9Sowk2GqyNhQSzmJCS0BHGWNHBhOzGCnK 56 t9iKrbQ75uUBhekbR6AlAgkqr6SY67wyqdOpCQy8c+4IU4M/2vDBxzm0xigLeVlK 57 Sz7VXFyi4nkhEJpP5wjqQqkCgYEAuXAASNJ5wGQS7AeZInh7ERoB54cuXHNT8EAw 58 4Kde+Vrbq8QuQscP77H2WYo9lAc+jR//1zz2fBimsl/oLMtre+St7AfwoVGFk+ag 59 4kFX4JkLIa3i6d6KtPFze0IzwdNyBfYQVrt91WLDDQSTGGnQQLfcOrpb1Gl1onzz 60 9veJVdECgYEA3/YfFzB7MjWxTtmlgyv5VdOuLLxkw0KV7QhoOv5zbwp9GsJFJWxN 61 OE6Trrq1EYQRe/NqdIRNt9tJMxLV+0E8s8kvT2yQPHvOWxV6lq0O5ypFeBT7wnXp 62 aLVVG9//pbbfefHaMZ4A98GT1b7e08Q/QX89cTUORvaQCM7E7QNqLoo= 63 -----END RSA PRIVATE KEY----- 64 EOS"; 65 66 immutable expectedJwt = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9." 67 ~ "eyJleHAiOjYwMCwiaWF0IjowLCJpc3MiOjExMTF9.WSERqrEL5JSoNO-" 68 ~ "B_G6wt0pGFPYIN3WfTbjMZQEZHznLMkWPqGoQL_iWcF2QHKKVxLUxJTm" 69 ~ "fONccSodJ2j6zQMlmdbU9LXa-DzwZTUYLLP6GiQrFv1IgTiFngjJQ32z" 70 ~ "L6I2SIwMFiPBxyFImku_xrsT2MZu9J6N-VyPqM0LJ6nYPsKso-Nlo-iw" 71 ~ "2PRh01YF5_rrxT8q45lOvHkflyZogESb8BaiJMZqscbey1TmDQq1TgiD" 72 ~ "HRIHzuB3SBQa5E2s24cs9VSIOrnJJeUuWiVTYQrY9c5nwR_xT2W_rHsT" 73 ~ "Pp2sEVePvIQJOfzu8iTraveKF4U0IliUI_wNYytiOVHnovg"; 74 75 const payload = `{"iat": 0, "exp": 600, "iss": 1111}`; 76 const json = parseJSON(payload); 77 const jwt = encode(json, key, Algorithm.rs256); 78 79 assert(jwt == expectedJwt); 80 }