Keine Beschreibung
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

UniWebViewAuthenticationUtils.cs 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. //
  2. // UniWebViewAuthenticationUtils.cs
  3. // Created by Wang Wei (@onevcat) on 2022-06-25.
  4. //
  5. // This file is a part of UniWebView Project (https://uniwebview.com)
  6. // By purchasing the asset, you are allowed to use this code in as many as projects
  7. // you want, only if you publish the final products under the name of the same account
  8. // used for the purchase.
  9. //
  10. // This asset and all corresponding files (such as source code) are provided on an
  11. // “as is” basis, without warranty of any kind, express of implied, including but not
  12. // limited to the warranties of merchantability, fitness for a particular purpose, and
  13. // noninfringement. In no event shall the authors or copyright holders be liable for any
  14. // claim, damages or other liability, whether in action of contract, tort or otherwise,
  15. // arising from, out of or in connection with the software or the use of other dealing in the software.
  16. //
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Collections.Specialized;
  20. using System.Linq;
  21. using System.Security.Cryptography;
  22. using System.Text;
  23. using UnityEngine.Networking;
  24. /// <summary>
  25. /// This class provides some helper utils for performing the authentication flow.
  26. ///
  27. /// They are used inside the built-in flows, but you can also use them to implement your own flow.
  28. /// </summary>
  29. public class UniWebViewAuthenticationUtils {
  30. internal static Dictionary<string, string> ParseFormUrlEncodedString(string input) {
  31. var result = new Dictionary<string, string>();
  32. if (input.StartsWith("?") || input.StartsWith("#")) {
  33. input = input.Substring(1);
  34. }
  35. var pairs = input.Split('&');
  36. foreach (var pair in pairs) {
  37. var kv = pair.Split('=');
  38. result.Add(UnityWebRequest.UnEscapeURL(kv[0]), UnityWebRequest.UnEscapeURL(kv[1]));
  39. }
  40. return result;
  41. }
  42. /// <summary>
  43. /// Generates a random Base64 encoded string.
  44. /// </summary>
  45. /// <returns>A random Base64 encoded string.</returns>
  46. public static string GenerateRandomBase64String() {
  47. var randomNumber = new byte[32];
  48. string value = "";
  49. using (var rng = RandomNumberGenerator.Create()) {
  50. rng.GetBytes(randomNumber);
  51. value = Convert.ToBase64String(randomNumber);
  52. }
  53. return value;
  54. }
  55. /// <summary>
  56. /// Generates a random Base64URL encoded string.
  57. /// </summary>
  58. /// <returns>A random Base64URL encoded string.</returns>
  59. public static string GenerateRandomBase64URLString() {
  60. var value = GenerateRandomBase64String();
  61. return ConvertToBase64URLString(value);
  62. }
  63. static readonly char[] padding = { '=' };
  64. /// <summary>
  65. /// Converts a Base64 encoded string to a Base64URL encoded string.
  66. /// </summary>
  67. /// <param name="input">The Base64 encoded string.</param>
  68. /// <returns>A string with Base64URL encoded for the input.</returns>
  69. public static string ConvertToBase64URLString(string input) {
  70. return input.TrimEnd(padding).Replace('+', '-').Replace('/', '_');
  71. }
  72. /// <summary>
  73. /// Converts a Base64URL encoded string to a Base64 encoded string.
  74. /// </summary>
  75. /// <param name="input">The Base64URL encoded string.</param>
  76. /// <returns>A string with Base64 encoded for the input.</returns>
  77. public static string ConvertToBase64String(string input) {
  78. string result = input.Replace('_', '/').Replace('-', '+');
  79. switch (input.Length % 4) {
  80. case 2:
  81. result += "==";
  82. break;
  83. case 3:
  84. result += "=";
  85. break;
  86. }
  87. return result;
  88. }
  89. /// <summary>
  90. /// Generates a code verifier for PKCE usage.
  91. /// </summary>
  92. /// <param name="length">The length of the target code verifier. Default is 64.</param>
  93. /// <returns>A generated code verifier for PKCE usage.</returns>
  94. public static string GenerateCodeVerifier(int length = 64) {
  95. var randomNumber = new byte[32];
  96. string value = "";
  97. using (var rng = RandomNumberGenerator.Create()) {
  98. rng.GetBytes(randomNumber);
  99. String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
  100. Random random = new Random(System.BitConverter.ToInt32(randomNumber, 0));
  101. value = new String(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
  102. }
  103. return value;
  104. }
  105. /// <summary>
  106. /// Calculates the code challenge for PKCE usage, with a given code verifier and hash method.
  107. /// </summary>
  108. /// <param name="codeVerifier">The code verifier you generated.</param>
  109. /// <param name="method">The hash method you want to use.</param>
  110. /// <returns>The result of the code challenge.</returns>
  111. public static string CalculateCodeChallenge(string codeVerifier, UniWebViewAuthenticationPKCE method) {
  112. switch (method) {
  113. case UniWebViewAuthenticationPKCE.None:
  114. throw new ArgumentOutOfRangeException(nameof(method), method, null);
  115. case UniWebViewAuthenticationPKCE.S256:
  116. var sha256 = SHA256.Create();
  117. var hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(codeVerifier));
  118. return ConvertToBase64URLString(System.Convert.ToBase64String(hash));
  119. case UniWebViewAuthenticationPKCE.Plain:
  120. return codeVerifier;
  121. default:
  122. throw new ArgumentOutOfRangeException(nameof(method), method, null);
  123. }
  124. }
  125. public static string ConvertPKCEToString(UniWebViewAuthenticationPKCE method) {
  126. switch (method) {
  127. case UniWebViewAuthenticationPKCE.None:
  128. return null;
  129. case UniWebViewAuthenticationPKCE.S256:
  130. return "S256";
  131. case UniWebViewAuthenticationPKCE.Plain:
  132. return "plain";
  133. }
  134. return null;
  135. }
  136. public static string ConvertIntentUri(string input) {
  137. var uri = new Uri(input);
  138. if (uri.Scheme != "intent") {
  139. return input;
  140. }
  141. var host = uri.Host;
  142. string scheme = null;
  143. var fragmentPairs = new Dictionary<string, string>();
  144. var fragments = uri.Fragment;
  145. fragments.Split(';').ToList().ForEach(fragment => {
  146. var kv = fragment.Split('=');
  147. if (kv.Length == 2 && kv[0] == "scheme") {
  148. scheme = kv[1];
  149. }
  150. });
  151. if (!String.IsNullOrEmpty(scheme)) {
  152. return scheme + "://" + host;
  153. }
  154. return input;
  155. }
  156. public static string CreateQueryString(NameValueCollection collection) {
  157. int count = collection.Count;
  158. if (count == 0) {
  159. return "";
  160. }
  161. StringBuilder sb = new StringBuilder();
  162. string [] keys = collection.AllKeys;
  163. for (int i = 0; i < count; i++) {
  164. sb.AppendFormat ("{0}={1}&", keys[i], UnityWebRequest.EscapeURL(collection[keys[i]]));
  165. }
  166. if (sb.Length > 0) {
  167. sb.Length--;
  168. }
  169. return sb.ToString();
  170. }
  171. }
  172. public enum UniWebViewAuthenticationPKCE
  173. {
  174. None,
  175. S256,
  176. Plain
  177. }