From dbd76752b8bc2d9d27aa8bea99210ccbf6d2446e Mon Sep 17 00:00:00 2001 From: Michael Lehenbauer Date: Sat, 19 Jan 2013 12:28:49 -0800 Subject: [PATCH] Miscellaneous improvements. * Use System.Web.Script.Serialization.JavaScriptSerializer instead of NewtonSoft.Json (just to avoid external dependencies). * Target the full 3.5 profile instead of the client profile, since JavaScriptSerializer requires it (the nuget package was targetting the full profile already anyway). * Add DecodeToObject() method to deserialize the JSON payload. * Throw custom exception on invalid signature instead of InvalidOperationException. * Add doc comments to methods. * Add installation / usage details to Readme.md. * Bump version number to 1.2. --- JWT.nuspec | 9 +- JWT/JWT.cs | 65 +- JWT/JWT.csproj | 14 +- JWT/Properties/AssemblyInfo.cs | 4 +- JWT/packages.config | 4 - README.md | 47 +- .../lib/net20/Newtonsoft.Json.dll | Bin 375296 -> 0 bytes .../lib/net20/Newtonsoft.Json.xml | 7859 ----------------- .../lib/net35/Newtonsoft.Json.dll | Bin 335360 -> 0 bytes .../lib/net35/Newtonsoft.Json.xml | 6982 --------------- .../lib/net40/Newtonsoft.Json.dll | Bin 358400 -> 0 bytes .../lib/net40/Newtonsoft.Json.xml | 7141 --------------- .../lib/sl3-wp/Newtonsoft.Json.dll | Bin 305152 -> 0 bytes .../lib/sl3-wp/Newtonsoft.Json.xml | 6574 -------------- .../sl4-windowsphone71/Newtonsoft.Json.dll | Bin 305152 -> 0 bytes .../sl4-windowsphone71/Newtonsoft.Json.xml | 6574 -------------- .../lib/sl4/Newtonsoft.Json.dll | Bin 308736 -> 0 bytes .../lib/sl4/Newtonsoft.Json.xml | 6604 -------------- packages/repositories.config | 4 - 19 files changed, 98 insertions(+), 41783 deletions(-) delete mode 100644 JWT/packages.config delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/net20/Newtonsoft.Json.dll delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/net20/Newtonsoft.Json.xml delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/net35/Newtonsoft.Json.dll delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/net35/Newtonsoft.Json.xml delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/net40/Newtonsoft.Json.dll delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/net40/Newtonsoft.Json.xml delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/sl3-wp/Newtonsoft.Json.dll delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/sl3-wp/Newtonsoft.Json.xml delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/sl4-windowsphone71/Newtonsoft.Json.dll delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/sl4-windowsphone71/Newtonsoft.Json.xml delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/sl4/Newtonsoft.Json.dll delete mode 100644 packages/Newtonsoft.Json.4.0.5/lib/sl4/Newtonsoft.Json.xml delete mode 100644 packages/repositories.config diff --git a/JWT.nuspec b/JWT.nuspec index 54ef408f9..23b50c422 100644 --- a/JWT.nuspec +++ b/JWT.nuspec @@ -2,14 +2,11 @@ JWT - 1.1.1 - John Sheehan + 1.2.0 + John Sheehan, Michael Lehenbauer JWT (JSON Web Token) Implementation for .NET (Public Domain) en-US http://github.com/johnsheehan/jwt jwt json - - - - \ No newline at end of file + diff --git a/JWT/JWT.cs b/JWT/JWT.cs index 477046b09..a1aa3c461 100644 --- a/JWT/JWT.cs +++ b/JWT/JWT.cs @@ -2,8 +2,7 @@ using System.Collections.Generic; using System.Security.Cryptography; using System.Text; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Web.Script.Serialization; namespace JWT { @@ -14,9 +13,13 @@ public enum JwtHashAlgorithm HS512 } - public class JsonWebToken + /// + /// Provides methods for encoding and decoding JSON Web Tokens. + /// + public static class JsonWebToken { private static Dictionary> HashAlgorithms; + private static JavaScriptSerializer jsonSerializer = new JavaScriptSerializer(); static JsonWebToken() { @@ -28,13 +31,20 @@ static JsonWebToken() }; } + /// + /// Creates a JWT given a payload, the signing key, and the algorithm to use. + /// + /// An arbitrary payload (must be serializable to JSON via ). + /// The key used to sign the token. + /// The hash algorithm to use. + /// The generated JWT. public static string Encode(object payload, string key, JwtHashAlgorithm algorithm) { var segments = new List(); var header = new { typ = "JWT", alg = algorithm.ToString() }; - byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None)); - byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None)); + byte[] headerBytes = Encoding.UTF8.GetBytes(jsonSerializer.Serialize(header)); + byte[] payloadBytes = Encoding.UTF8.GetBytes(jsonSerializer.Serialize(payload)); segments.Add(Base64UrlEncode(headerBytes)); segments.Add(Base64UrlEncode(payloadBytes)); @@ -50,12 +60,15 @@ public static string Encode(object payload, string key, JwtHashAlgorithm algorit return string.Join(".", segments.ToArray()); } - public static string Decode(string token, string key) - { - return Decode(token, key, true); - } - - public static string Decode(string token, string key, bool verify) + /// + /// Given a JWT, decode it and return the JSON payload. + /// + /// The JWT. + /// The key that was used to sign the JWT. + /// Whether to verify the signature (default is true). + /// A string containing the JSON payload. + /// Thrown if the verify parameter was true and the signature was NOT valid or if the JWT was signed with an unsupported algorithm. + public static string Decode(string token, string key, bool verify = true) { var parts = token.Split('.'); var header = parts[0]; @@ -63,9 +76,8 @@ public static string Decode(string token, string key, bool verify) byte[] crypto = Base64UrlDecode(parts[2]); var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header)); - var headerData = JObject.Parse(headerJson); + var headerData = jsonSerializer.Deserialize>(headerJson); var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload)); - var payloadData = JObject.Parse(payloadJson); if (verify) { @@ -79,11 +91,26 @@ public static string Decode(string token, string key, bool verify) if (decodedCrypto != decodedSignature) { - throw new ApplicationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature)); + throw new SignatureVerificationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature)); } } - return payloadData.ToString(); + return payloadJson; + } + + /// + /// Given a JWT, decode it and return the payload as an object (by deserializing it with ). + /// + /// The JWT. + /// The key that was used to sign the JWT. + /// Whether to verify the signature (default is true). + /// An object representing the payload. + /// Thrown if the verify parameter was true and the signature was NOT valid or if the JWT was signed with an unsupported algorithm. + public static object DecodeToObject(string token, string key, bool verify = true) + { + var payloadJson = JsonWebToken.Decode(token, key, verify); + var payloadData = jsonSerializer.Deserialize>(payloadJson); + return payloadData; } private static JwtHashAlgorithm GetHashAlgorithm(string algorithm) @@ -93,7 +120,7 @@ private static JwtHashAlgorithm GetHashAlgorithm(string algorithm) case "HS256": return JwtHashAlgorithm.HS256; case "HS384": return JwtHashAlgorithm.HS384; case "HS512": return JwtHashAlgorithm.HS512; - default: throw new InvalidOperationException("Algorithm not supported."); + default: throw new SignatureVerificationException("Algorithm not supported."); } } @@ -125,4 +152,10 @@ private static byte[] Base64UrlDecode(string input) } } + public class SignatureVerificationException : Exception + { + public SignatureVerificationException(string message) : base(message) + { + } + } } diff --git a/JWT/JWT.csproj b/JWT/JWT.csproj index 63762416b..5892bbe24 100644 --- a/JWT/JWT.csproj +++ b/JWT/JWT.csproj @@ -12,7 +12,8 @@ JWT v3.5 512 - Client + + true @@ -32,23 +33,14 @@ 4 - - ..\packages\Newtonsoft.Json.4.0.5\lib\net35\Newtonsoft.Json.dll - - - - - + - - -