| 58 | |
| 59 | |
| 60 | Try<JWT::Header> parse_header(const string& component) |
| 61 | { |
| 62 | Try<JSON::Object> header = decode(component); |
| 63 | |
| 64 | if (header.isError()) { |
| 65 | return Error("Failed to decode token header: " + header.error()); |
| 66 | } |
| 67 | |
| 68 | // Validate JOSE header. |
| 69 | |
| 70 | Option<string> typ = None(); |
| 71 | |
| 72 | const Result<JSON::Value> typ_json = header->find<JSON::Value>("typ"); |
| 73 | |
| 74 | if (typ_json.isSome()) { |
| 75 | if (!typ_json->is<JSON::String>()) { |
| 76 | return Error("Token 'typ' is not a string"); |
| 77 | } |
| 78 | |
| 79 | typ = typ_json->as<JSON::String>().value; |
| 80 | } |
| 81 | |
| 82 | const Result<JSON::Value> alg_json = header->find<JSON::Value>("alg"); |
| 83 | |
| 84 | if (alg_json.isNone()) { |
| 85 | return Error("Failed to locate 'alg' in token JSON header"); |
| 86 | } |
| 87 | |
| 88 | if (alg_json.isError()) { |
| 89 | return Error( |
| 90 | "Error when extracting 'alg' field from token JSON header: " + |
| 91 | alg_json.error()); |
| 92 | } |
| 93 | |
| 94 | if (!alg_json->is<JSON::String>()) { |
| 95 | return Error("Token 'alg' field is not a string"); |
| 96 | } |
| 97 | |
| 98 | const string alg_value = alg_json->as<JSON::String>().value; |
| 99 | |
| 100 | JWT::Alg alg; |
| 101 | |
| 102 | if (alg_value == "none") { |
| 103 | alg = JWT::Alg::None; |
| 104 | } else if (alg_value == "HS256") { |
| 105 | alg = JWT::Alg::HS256; |
| 106 | } else if (alg_value == "RS256") { |
| 107 | alg = JWT::Alg::RS256; |
| 108 | } else { |
| 109 | return Error("Unsupported token algorithm: " + alg_value); |
| 110 | } |
| 111 | |
| 112 | const Result<JSON::Value> crit_json = header->find<JSON::Value>("crit"); |
| 113 | |
| 114 | // The 'crit' header parameter indicates extensions that must be understood. |
| 115 | // As we're not supporting any extensions, the JWT header is deemed to be |
| 116 | // invalid upon the presence of this parameter. |
| 117 | if (crit_json.isSome()) { |