{
	"info": {
		"_postman_id": "826bc415-ab82-4dc5-bbb9-a5a0e081639a",
		"name": "Customer Collection",
		"schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json",
		"_exporter_id": "1007249"
	},
	"item": [
		{
			"name": "User Registration",
			"item": [
				{
					"name": "Auth Token",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									"tests[\"Should return a response status of 200 OK\"] = responseCode.code === 200;",
									"",
									"let jsonData = JSON.parse(responseBody);",
									"",
									"tests[\"AccessToken should be returned\"] = jsonData.hasOwnProperty('access_token');",
									"tests[\"Token type should be returned\"] = jsonData.hasOwnProperty('token_type');",
									"tests[\"Token type should be of type Bearer\"] = jsonData.token_type === 'Bearer';",
									"",
									"if (responseCode.code !== 200) {",
									"    return;",
									"}",
									"",
									"pm.collectionVariables.set(\"context.auth.access-token\", jsonData.access_token);",
									"pm.collectionVariables.set(\"context.user_id\", jwt_decode(jsonData.access_token).sub);",
									"",
									"function jwt_decode(jwt){",
									"    var parts = null;",
									"    try{",
									"        parts = decode_b64(jwt.split('.')[1]);",
									"    } catch (e){",
									"        console.log(\"error parsing JWT\");",
									"        throw (e);",
									"    }",
									"",
									"    if (parts){",
									"        return JSON.parse(parts);",
									"    }",
									"    return {};",
									"}",
									"",
									"function InvalidCharacterError(message) {",
									"  this.message = message;",
									"}",
									"",
									"InvalidCharacterError.prototype = new Error();",
									"InvalidCharacterError.prototype.name = 'InvalidCharacterError';",
									"",
									"function atob (input) {",
									"  var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';",
									"  var str = String(input).replace(/=+$/, '');",
									"  if (str.length % 4 == 1) {",
									"    throw new InvalidCharacterError(\"'atob' failed: The string to be decoded is not correctly encoded.\");",
									"  }",
									"  for (",
									"    // initialize result and counters",
									"    var bc = 0, bs, buffer, idx = 0, output = '';",
									"    // get next character",
									"    buffer = str.charAt(idx++);",
									"    // character found in table? initialize bit storage and add its ascii value;",
									"    ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,",
									"      // and if not first of each 4 characters,",
									"      // convert the first 8 bits to one ascii character",
									"      bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0",
									"  ) {",
									"    // try to find character in table (0-63, not found => -1)",
									"    buffer = chars.indexOf(buffer);",
									"  }",
									"  return output;",
									"}",
									"function b64DecodeUnicode(str) {",
									"  return decodeURIComponent(atob(str).replace(/(.)/g, function (m, p) {",
									"    var code = p.charCodeAt(0).toString(16).toUpperCase();",
									"    if (code.length < 2) {",
									"      code = '0' + code;",
									"    }",
									"    return '%' + code;",
									"  }));",
									"}",
									"",
									"function decode_b64(str) {",
									"  var output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");",
									"  switch (output.length % 4) {",
									"    case 0:",
									"      break;",
									"    case 2:",
									"      output += \"==\";",
									"      break;",
									"    case 3:",
									"      output += \"=\";",
									"      break;",
									"    default:",
									"      throw \"Illegal base64url string!\";",
									"  }",
									"",
									"  try{",
									"    return b64DecodeUnicode(output);",
									"  } catch (err) {",
									"    return atob(output);",
									"  }",
									"}"
								],
								"type": "text/javascript",
								"packages": {}
							}
						},
						{
							"listen": "prerequest",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript",
								"packages": {}
							}
						}
					],
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\r\n    \"username\":\"{{my_username}}\",\r\n    \"password\":\"{{my_password}}\"\r\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": "{{urls.lytx-external-kong-api}}/login",
						"description": "Global Outputted Variables:\n\n<b>\"context.auth.access-token\"</b>:  JWT Access Token<br />\n<b>\"context.auth.refresh-token\"</b>:  Refresh token for extending JWT<br />\n<b>\"context.auth.session-id\"</b>:  HBS Session Id of Logged in User<br />\n<b>\"context.auth.user-id\"</b>:  User Id of logged in User<br />\n<b>\"context.auth.company-id\"</b>:  Company Id for logged in User<br />\n<b>\"context.auth.root-group-id\"</b>:  Group Id for logged in User<br />\n<b>\"context.auth.stack-id\"</b>:  Stack Id for logged in User<br />\n<b>\"context.auth.client-id\"</b>:  Client Id used during authentication<br />"
					},
					"response": []
				},
				{
					"name": "Register User",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									"pm.test(\"Status code is 200\", function () {\r",
									"  pm.response.to.have.status(200);\r",
									"});\r",
									"\r",
									"if (responseCode.code === 200) {\r",
									"    try {\r",
									"        tests[\"Response is not empty\"] = (responseBody!==null || responseBody.length!==0);\r",
									"            let jsonData = JSON.parse(responseBody);\r",
									"            pm.test(\"Expect value types are accurate\", function() {\r",
									"                pm.expect(jsonData.header.alg).to.be.a('string');\r",
									"                pm.expect(jsonData.header.alg).to.be.equal(\"RS256\");\r",
									"                pm.expect(jsonData.header.typ).to.be.a('string');\r",
									"                pm.expect(jsonData.header.typ).to.be.equal(\"JWT\");\r",
									"                pm.expect(jsonData.header.iss).to.be.a('string');\r",
									"                pm.expect(jsonData.payload.name).to.be.a('string');\r",
									"                pm.expect(jsonData.payload.user_id).to.be.a('string');\r",
									"                pm.expect(jsonData.payload.co_id).to.be.a('string');\r",
									"                pm.expect(jsonData.payload.rootgroupid).to.be.a('string');\r",
									"                pm.expect(jsonData.payload.roles).to.be.a('string');\r",
									"                pm.expect(jsonData.payload.roles).to.be.equal(\"Developer\");\r",
									"                pm.expect(jsonData.payload.exp).to.be.a('number');\r",
									"            });\r",
									"        }\r",
									"    catch (e) {\r",
									"        tests[e.message] = (e === true);\r",
									"        throw false;\r",
									"        }\r",
									"    }\r",
									"    else {\r",
									"        tests[\"Expected 200 but received \" + responseCode.code  + responseBody ] = (responseCode.code === 200);\r",
									"    }"
								],
								"type": "text/javascript",
								"packages": {}
							}
						}
					],
					"request": {
						"auth": {
							"type": "bearer",
							"bearer": {
								"token": "{{context.auth.access-token}}"
							}
						},
						"method": "POST",
						"header": [],
						"body": {
							"mode": "formdata",
							"formdata": [
								{
									"key": "Username",
									"value": "{{my_username}}",
									"type": "text"
								},
								{
									"key": "CustomId",
									"value": "{{context.user_id}}",
									"type": "text"
								},
								{
									"key": "RSAPublicKey",
									"type": "file",
									"src": "public.pem"
								}
							]
						},
						"url": "{{urls.lytx-external-kong-api}}/users"
					},
					"response": []
				}
			],
			"event": [
				{
					"listen": "prerequest",
					"script": {
						"type": "text/javascript",
						"exec": [
							""
						]
					}
				},
				{
					"listen": "test",
					"script": {
						"type": "text/javascript",
						"exec": [
							""
						]
					}
				}
			]
		},
		{
			"name": "Short Lived Token",
			"event": [
				{
					"listen": "test",
					"script": {
						"exec": [
							"tests[\"Should return a response status of 200 OK\"] = responseCode.code === 200;\r",
							"\r",
							"let jsonData = JSON.parse(responseBody);\r",
							"\r",
							"tests[\"AccessToken should be returned\"] = jsonData.hasOwnProperty('access_token');\r",
							"tests[\"RefreshToken should be returned\"] = jsonData.hasOwnProperty('expires_in');\r",
							"tests[\"Token type should be returned\"] = jsonData.hasOwnProperty('token_type');\r",
							"tests[\"Token type should be of type Bearer\"] = jsonData.token_type === 'Bearer';\r",
							"\r",
							"if (responseCode.code !== 200) {\r",
							"    return;\r",
							"}\r",
							"\r",
							"pm.collectionVariables.set(\"signed.access-token\", jsonData.access_token);\r",
							"\r",
							"let decryptedJwt = jwt_decode(jsonData.access_token);\r",
							"\r",
							"console.log(decryptedJwt);\r",
							"\r",
							"function jwt_decode(jwt){\r",
							"    var parts = null;\r",
							"    try{\r",
							"        parts = decode_b64(jwt.split('.')[1]);\r",
							"    } catch (e){\r",
							"        console.log(\"error parsing JWT\");\r",
							"        throw (e);\r",
							"    }\r",
							"    console.log(parts);\r",
							"    if (parts){\r",
							"        return JSON.parse(parts);\r",
							"    }\r",
							"    return {};\r",
							"}\r",
							"\r",
							"function InvalidCharacterError(message) {\r",
							"  this.message = message;\r",
							"}\r",
							"\r",
							"InvalidCharacterError.prototype = new Error();\r",
							"InvalidCharacterError.prototype.name = 'InvalidCharacterError';\r",
							"\r",
							"function atob (input) {\r",
							"  var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\r",
							"  var str = String(input).replace(/=+$/, '');\r",
							"  if (str.length % 4 == 1) {\r",
							"    throw new InvalidCharacterError(\"'atob' failed: The string to be decoded is not correctly encoded.\");\r",
							"  }\r",
							"  for (\r",
							"    // initialize result and counters\r",
							"    var bc = 0, bs, buffer, idx = 0, output = '';\r",
							"    // get next character\r",
							"    buffer = str.charAt(idx++);\r",
							"    // character found in table? initialize bit storage and add its ascii value;\r",
							"    ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,\r",
							"      // and if not first of each 4 characters,\r",
							"      // convert the first 8 bits to one ascii character\r",
							"      bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0\r",
							"  ) {\r",
							"    // try to find character in table (0-63, not found => -1)\r",
							"    buffer = chars.indexOf(buffer);\r",
							"  }\r",
							"  return output;\r",
							"}\r",
							"function b64DecodeUnicode(str) {\r",
							"  return decodeURIComponent(atob(str).replace(/(.)/g, function (m, p) {\r",
							"    var code = p.charCodeAt(0).toString(16).toUpperCase();\r",
							"    if (code.length < 2) {\r",
							"      code = '0' + code;\r",
							"    }\r",
							"    return '%' + code;\r",
							"  }));\r",
							"}\r",
							"\r",
							"function decode_b64(str) {\r",
							"  var output = str.replace(/-/g, \"+\").replace(/_/g, \"/\");\r",
							"  switch (output.length % 4) {\r",
							"    case 0:\r",
							"      break;\r",
							"    case 2:\r",
							"      output += \"==\";\r",
							"      break;\r",
							"    case 3:\r",
							"      output += \"=\";\r",
							"      break;\r",
							"    default:\r",
							"      throw \"Illegal base64url string!\";\r",
							"  }\r",
							"\r",
							"  try{\r",
							"    return b64DecodeUnicode(output);\r",
							"  } catch (err) {\r",
							"    return atob(output);\r",
							"  }\r",
							"}"
						],
						"type": "text/javascript",
						"packages": {}
					}
				}
			],
			"request": {
				"auth": {
					"type": "bearer",
					"bearer": {
						"token": "{{thirdparty.access-token}}"
					}
				},
				"method": "GET",
				"header": [],
				"url": "{{urls.lytx-auth-token}}"
			},
			"response": []
		}
	],
	"event": [
		{
			"listen": "prerequest",
			"script": {
				"type": "text/javascript",
				"exec": [
					""
				]
			}
		},
		{
			"listen": "test",
			"script": {
				"type": "text/javascript",
				"exec": [
					""
				]
			}
		}
	],
	"variable": [
		{
			"key": "urls.lytx-external-kong-api",
			"value": "https://api.aws.drivecam.net/api/v1/authenticate",
			"type": "string"
		},
		{
			"key": "urls.lytx-auth-token",
			"value": "https://api.lytx.com/v1/authenticate/token",
			"type": "string"
		},
		{
			"key": "context.auth.access-token",
			"value": "POSTMAN_GENERATED",
			"type": "string"
		},
		{
			"key": "context.user_id",
			"value": "POSTMAN_GENERATED",
			"type": "string"
		},
		{
			"key": "signed.access-token",
			"value": "POSTMAN_GENERATED",
			"type": "string"
		},
		{
			"key": "my_username",
			"value": "REPLACE_ME",
			"type": "string"
		},
		{
			"key": "my_password",
			"value": "REPLACE_ME",
			"type": "string"
		},
		{
			"key": "thirdparty.access-token",
			"value": "GENERATE_ON_JWT.IO",
			"type": "string"
		},
		{
			"key": "groupId",
			"value": "OPTIONAL_REPLACE_ME_TO_USE_SINGLE_AND_DESCENDANT_ENDPOINTS",
			"type": "string"
		}
	]
}