using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace BaronSoftware.SSO { internal static class PKCEUtil { public static string NewVerifier() => B64Url(RandomNumberGenerator.GetBytes(32)); public static string RandomToken() => B64Url(RandomNumberGenerator.GetBytes(16)); public static string Challenge(string verifier) => B64Url(SHA256.HashData(Encoding.ASCII.GetBytes(verifier))); private static string B64Url(byte[] bytes) => Convert.ToBase64String(bytes).TrimEnd('=').Replace('+', '-').Replace('/', '_'); public static Dictionary ParseQuery(string uri) { var result = new Dictionary(StringComparer.OrdinalIgnoreCase); var query = new Uri(uri).Query.TrimStart('?'); foreach (var pair in query.Split('&', StringSplitOptions.RemoveEmptyEntries)) { var kv = pair.Split('=', 2); result[Uri.UnescapeDataString(kv[0])] = kv.Length > 1 ? Uri.UnescapeDataString(kv[1]) : string.Empty; } return result; } } }