Пример #1
0
        /// <summary>
        /// Private constructor.
        /// </summary>
        /// <param name="jwtString">The encoded JWT string.</param>
        /// <exception cref="FormatException">Thrown if the JWT format is invalid.</exception>
        private Jwt(string jwtString)
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(jwtString), nameof(jwtString));

            this.jwtString = jwtString;

            // Encoded JWTs are formatted as three URL encoded Base64URL encoded strings
            // separated by periods.  The first two strings are actually JSON objects
            // and the last holds the signature bytes:
            //
            //      1. JWT header
            //      2. JWT payload (with the claims)
            //      3. JWT signature
            //
            // We're going to verify that these JSON objects exist and then parse
            // them as Newtonsoft [JObject] instances.

            var parts = jwtString.Split('.');

            if (parts.Length != 3)
            {
                throw new FormatException("JWT must have three parts separated by periods.");
            }

            try
            {
                Header    = JObject.Parse(Encoding.UTF8.GetString(NeonHelper.Base64UrlDecode(parts[0])));
                Payload   = JObject.Parse(Encoding.UTF8.GetString(NeonHelper.Base64UrlDecode(parts[1])));
                Signature = NeonHelper.Base64UrlDecode(parts[2]);
            }
            catch (Exception e)
            {
                throw new FormatException("Cannot parse JWT JSON parts.", e);
            }
        }
Пример #2
0
        public void Base64UrlEncoding()
        {
            // Verify that known values can be encoded with padding.

            Assert.Equal("", NeonHelper.Base64UrlEncode(Array.Empty <byte>(), retainPadding: true));
            Assert.Equal("AA%3D%3D", NeonHelper.Base64UrlEncode(new byte[] { 0 }, retainPadding: true));
            Assert.Equal("AAE%3D", NeonHelper.Base64UrlEncode(new byte[] { 0, 1 }, retainPadding: true));
            Assert.Equal("AAEC", NeonHelper.Base64UrlEncode(new byte[] { 0, 1, 2 }, retainPadding: true));
            Assert.Equal("AAECAw%3D%3D", NeonHelper.Base64UrlEncode(new byte[] { 0, 1, 2, 3 }, retainPadding: true));
            Assert.Equal("AAECAwQ%3D", NeonHelper.Base64UrlEncode(new byte[] { 0, 1, 2, 3, 4 }, retainPadding: true));

            // Verify that known values can be encoded without padding.

            Assert.Equal("", NeonHelper.Base64UrlEncode(Array.Empty <byte>()));
            Assert.Equal("AA", NeonHelper.Base64UrlEncode(new byte[] { 0 }));
            Assert.Equal("AAE", NeonHelper.Base64UrlEncode(new byte[] { 0, 1 }));
            Assert.Equal("AAEC", NeonHelper.Base64UrlEncode(new byte[] { 0, 1, 2 }));
            Assert.Equal("AAECAw", NeonHelper.Base64UrlEncode(new byte[] { 0, 1, 2, 3 }));
            Assert.Equal("AAECAwQ", NeonHelper.Base64UrlEncode(new byte[] { 0, 1, 2, 3, 4 }));

            // Verify that we can decode known values with padding.

            Assert.Equal(Array.Empty <byte>(), NeonHelper.Base64UrlDecode(""));
            Assert.Equal(new byte[] { 0 }, NeonHelper.Base64UrlDecode("AA%3D%3D"));
            Assert.Equal(new byte[] { 0, 1 }, NeonHelper.Base64UrlDecode("AAE%3D"));
            Assert.Equal(new byte[] { 0, 1, 2 }, NeonHelper.Base64UrlDecode("AAEC"));
            Assert.Equal(new byte[] { 0, 1, 2, 3 }, NeonHelper.Base64UrlDecode("AAECAw%3D%3D"));
            Assert.Equal(new byte[] { 0, 1, 2, 3, 4 }, NeonHelper.Base64UrlDecode("AAECAwQ%3D"));

            // Verify that we can decode known values without URL encoded padding.

            Assert.Equal(Array.Empty <byte>(), NeonHelper.Base64UrlDecode(""));
            Assert.Equal(new byte[] { 0 }, NeonHelper.Base64UrlDecode("AA"));
            Assert.Equal(new byte[] { 0, 1 }, NeonHelper.Base64UrlDecode("AAE"));
            Assert.Equal(new byte[] { 0, 1, 2 }, NeonHelper.Base64UrlDecode("AAEC"));
            Assert.Equal(new byte[] { 0, 1, 2, 3 }, NeonHelper.Base64UrlDecode("AAECAw"));
            Assert.Equal(new byte[] { 0, 1, 2, 3, 4 }, NeonHelper.Base64UrlDecode("AAECAwQ"));

            // Verify that we can decode known values with standard '=' padding.

            Assert.Equal(Array.Empty <byte>(), NeonHelper.Base64UrlDecode(""));
            Assert.Equal(new byte[] { 0 }, NeonHelper.Base64UrlDecode("AA=="));
            Assert.Equal(new byte[] { 0, 1 }, NeonHelper.Base64UrlDecode("AAE="));
            Assert.Equal(new byte[] { 0, 1, 2 }, NeonHelper.Base64UrlDecode("AAEC"));
            Assert.Equal(new byte[] { 0, 1, 2, 3 }, NeonHelper.Base64UrlDecode("AAECAw=="));
            Assert.Equal(new byte[] { 0, 1, 2, 3, 4 }, NeonHelper.Base64UrlDecode("AAECAwQ="));
        }