private JwtPayloadDocument(JwtDocument document, byte control, int issIdx) { _document = document; _control = control; _iss = issIdx < 0 ? default : new JwtElement(_document, issIdx); }
internal JwtDocument() { _isDisposable = false; _utf8Json = new byte[1]; _disposableRegistry = new List <IDisposable>(0); _root = new JwtElement(this, 0); }
internal bool TryGetNamedPropertyValue(ReadOnlySpan <char> propertyName, out JwtElement value) { JsonRow row; int maxBytes = Utf8.GetMaxByteCount(propertyName.Length); int endIndex = _parsedData.Length; if (maxBytes < JsonConstants.StackallocThreshold) { Span <byte> utf8Name = stackalloc byte[JsonConstants.StackallocThreshold]; int len = JsonReaderHelper.GetUtf8FromText(propertyName, utf8Name); utf8Name = utf8Name.Slice(0, len); return(TryGetNamedPropertyValue( endIndex, utf8Name, out value)); } // Unescaping the property name will make the string shorter (or the same) // So the first viable candidate is one whose length in bytes matches, or // exceeds, our length in chars. // // The maximal escaping seems to be 6 -> 1 ("\u0030" => "0"), but just transcode // and switch once one viable long property is found. int minBytes = propertyName.Length; for (int candidateIndex = 0; candidateIndex <= endIndex; candidateIndex += JsonRow.Size * 2) { row = _parsedData.Get(candidateIndex); Debug.Assert(row.TokenType == JsonTokenType.PropertyName); if (row.Length >= minBytes) { byte[] tmpUtf8 = ArrayPool <byte> .Shared.Rent(maxBytes); Span <byte> utf8Name = default; try { int len = JsonReaderHelper.GetUtf8FromText(propertyName, tmpUtf8); utf8Name = tmpUtf8.AsSpan(0, len); return(TryGetNamedPropertyValue( candidateIndex, utf8Name, out value)); } finally { ArrayPool <byte> .Shared.Return(tmpUtf8); } } } // None of the property names were within the range that the UTF-8 encoding would have been. value = default; return(false); }
/// <summary>Gets the value associated with the specified key.</summary> public bool TryGetProperty(string key, out JwtElement value) { if (key == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } return(_root.TryGetProperty(key, out value)); }
internal bool TryGetNamedPropertyValue(ReadOnlySpan <byte> propertyName, out JwtElement value) { int endIndex = _parsedData.Length; return(TryGetNamedPropertyValue( endIndex, propertyName, out value)); }
/// <summary>Parse the <see cref="JwtElement"/> into its <see cref="SignatureAlgorithm"/> representation.</summary> /// <param name="value"></param> /// <param name="algorithm"></param> public static bool TryParse(JwtElement value, [NotNullWhen(true)] out CompressionAlgorithm?algorithm) { if (value.ValueEquals(Def.Utf8Name)) { algorithm = Def; return(true); } algorithm = null; return(false); }
private JwtHeaderDocument(JwtDocument document, int algIdx, int encIdx, int kidIdx, int critIdx) { _document = document; _alg = algIdx < 0 ? default : new JwtElement(_document, algIdx); _enc = encIdx < 0 ? default : new JwtElement(_document, encIdx); _kid = kidIdx < 0 ? default : new JwtElement(_document, kidIdx); _crit = critIdx < 0 ? default : new JwtElement(_document, critIdx); }
internal JwtDocument(ReadOnlyMemory <byte> utf8Json, JsonMetadata parsedData, byte[]?extraRentedBytes, bool isDisposable = true) { Debug.Assert(!utf8Json.IsEmpty); _utf8Json = utf8Json; _parsedData = parsedData; _extraRentedBytes = extraRentedBytes; _root = new JwtElement(this, 0); _isDisposable = isDisposable; _disposableRegistry = new List <IDisposable>(); // extraRentedBytes better be null if we're not disposable. Debug.Assert(isDisposable || extraRentedBytes == null); }
private bool TryGetPolicy(JwtElement issuer, [NotNullWhen(true)] out SignatureValidationPolicy?policy) { for (int i = 0; i < _policies.Length; i++) { var current = _policies[i]; if (issuer.ValueEquals(current.Key)) { policy = current.Value; return(true); } } policy = null; return(false); }
/// <summary>Parse the <see cref="JwtElement"/> into its <see cref="SignatureAlgorithm"/> representation.</summary> public static bool TryParse(JwtElement value, [NotNullWhen(true)] out CompressionAlgorithm?algorithm) { if (value.ValueEquals(Def.Utf8Name)) { algorithm = Def; return(true); } #if NET5_0_OR_GREATER Unsafe.SkipInit(out algorithm); #else algorithm = default; #endif return(false); }
/// <summary>Parses the <see cref="JwtElement"/> into its <see cref="EncryptionAlgorithm"/> representation.</summary> public static bool TryParse(JwtElement value, [NotNullWhen(true)] out EncryptionAlgorithm?algorithm) { bool found; if (value.ValueEquals(A128CbcHS256._utf8Name.EncodedUtf8Bytes)) { algorithm = A128CbcHS256; found = true; } else if (value.ValueEquals(A192CbcHS384._utf8Name.EncodedUtf8Bytes)) { algorithm = A192CbcHS384; found = true; } else if (value.ValueEquals(A256CbcHS512._utf8Name.EncodedUtf8Bytes)) { algorithm = A256CbcHS512; found = true; } else if (value.ValueEquals(A128Gcm._utf8Name.EncodedUtf8Bytes)) { algorithm = A128Gcm; found = true; } else if (value.ValueEquals(A192Gcm._utf8Name.EncodedUtf8Bytes)) { algorithm = A192Gcm; found = true; } else if (value.ValueEquals(A256Gcm._utf8Name.EncodedUtf8Bytes)) { algorithm = A256Gcm; found = true; } else { #if NET5_0_OR_GREATER Unsafe.SkipInit(out algorithm); #else algorithm = default; #endif found = false; } return(found); }
private bool TryGetPolicy(JwtElement issuer, [NotNullWhen(true)] out SignatureValidationPolicy?policy) { for (int i = 0; i < _policies.Length; i++) { var current = _policies[i]; if (issuer.ValueEquals(current.Key)) { policy = current.Value; return(true); } } #if NET5_0_OR_GREATER Unsafe.SkipInit(out policy); #else policy = default; #endif return(false); }
/// <summary>Parses the <see cref="JwtElement"/> into its <see cref="EncryptionAlgorithm"/> representation.</summary> /// <param name="value"></param> /// <param name="algorithm"></param> public static bool TryParse(JwtElement value, [NotNullWhen(true)] out EncryptionAlgorithm?algorithm) { bool found; if (value.ValueEquals(A128CbcHS256._utf8Name.EncodedUtf8Bytes)) { algorithm = A128CbcHS256; found = true; } else if (value.ValueEquals(A192CbcHS384._utf8Name.EncodedUtf8Bytes)) { algorithm = A192CbcHS384; found = true; } else if (value.ValueEquals(A256CbcHS512._utf8Name.EncodedUtf8Bytes)) { algorithm = A256CbcHS512; found = true; } else if (value.ValueEquals(A128Gcm._utf8Name.EncodedUtf8Bytes)) { algorithm = A128Gcm; found = true; } else if (value.ValueEquals(A192Gcm._utf8Name.EncodedUtf8Bytes)) { algorithm = A192Gcm; found = true; } else if (value.ValueEquals(A256Gcm._utf8Name.EncodedUtf8Bytes)) { algorithm = A256Gcm; found = true; } else { algorithm = null; found = false; } return(found); }
public Jwk[] GetKeys(JwtElement kid) { if (kid.IsEmpty) { return(_keys.ToArray()); } var keys = GetIdentifiedKeys(); for (int i = 0; i < keys.Length; i++) { var key = keys[i]; if (kid.ValueEquals(key.Key.EncodedUtf8Bytes)) { return(key.Value); } } return(Array.Empty <Jwk>()); }
internal JwtMemberElement(JwtElement value, string?name = null) { Value = value; _name = name; }
internal bool TryGetProperty(ReadOnlySpan <byte> utf8PropertyName, out JwtElement value) => _parent.TryGetNamedPropertyValue(utf8PropertyName, out value);
private bool TryGetNamedPropertyValue( int endIndex, ReadOnlySpan <byte> propertyName, out JwtElement value) { ReadOnlySpan <byte> documentSpan = _utf8Json.Span; Span <byte> utf8UnescapedStack = stackalloc byte[JsonConstants.StackallocThreshold]; // Move to the row before the EndObject int index = 0; while (index < endIndex) { JsonRow row = _parsedData.Get(index); Debug.Assert(row.TokenType == JsonTokenType.PropertyName); ReadOnlySpan <byte> currentPropertyName = documentSpan.Slice(row.Location, row.Length); if (row.NeedUnescaping) { // An escaped property name will be longer than an unescaped candidate, so only unescape // when the lengths are compatible. if (currentPropertyName.Length > propertyName.Length) { int idx = currentPropertyName.IndexOf(JsonConstants.BackSlash); Debug.Assert(idx >= 0); // If everything up to where the property name has a backslash matches, keep going. if (propertyName.Length > idx && currentPropertyName.Slice(0, idx).SequenceEqual(propertyName.Slice(0, idx))) { int remaining = currentPropertyName.Length - idx; int written = 0; byte[]? rented = null; try { Span <byte> utf8Unescaped = remaining <= utf8UnescapedStack.Length ? utf8UnescapedStack : (rented = ArrayPool <byte> .Shared.Rent(remaining)); // Only unescape the part we haven't processed. JsonReaderHelper.Unescape(currentPropertyName.Slice(idx), utf8Unescaped, 0, out written); // If the unescaped remainder matches the input remainder, it's a match. if (utf8Unescaped.Slice(0, written).SequenceEqual(propertyName.Slice(idx))) { // If the property name is a match, the answer is the next element. value = new JwtElement(this, index + JsonRow.Size); return(true); } } finally { if (rented != null) { rented.AsSpan(0, written).Clear(); ArrayPool <byte> .Shared.Return(rented); } } } } } else if (currentPropertyName.SequenceEqual(propertyName)) { // If the property name is a match, the answer is the next element. value = new JwtElement(this, index + JsonRow.Size); return(true); } // Move to the previous value index += JsonRow.Size * 2; } value = default; return(false); }
/// <summary> /// Looks for a claim named <paramref name="claimName"/> in the current JWT, returning /// whether or not such a claim existed. When the claim exists <paramref name="value"/> /// is assigned to the value of that claim. /// </summary> /// <param name="claimName">Name of the claim to find.</param> /// <param name="value">Receives the value of the located claim.</param> /// <returns> /// <see langword="true"/> if the claim was found, <see langword="false"/> otherwise. /// </returns> /// <exception cref="InvalidOperationException"> /// This value is not <see cref="JsonValueKind.Object"/>. /// </exception> /// <exception cref="ObjectDisposedException"> /// The parent <see cref="JwtDocument"/> has been disposed. /// </exception> public bool TryGetClaim(string claimName, out JwtElement value) => _document.TryGetProperty(claimName, out value);
/// <summary> /// Looks for a header parameter named <paramref name="headerParameterName"/> in the current JWT, returning /// whether or not such a parameter existed. When the parameter exists <paramref name="value"/> /// is assigned to the value of that parameter. /// </summary> /// <param name="headerParameterName">Name of the parameter to find.</param> /// <param name="value">Receives the value of the located parameter.</param> /// <returns> /// <see langword="true"/> if the parameter was found, <see langword="false"/> otherwise. /// </returns> /// <exception cref="InvalidOperationException"> /// This value is not <see cref="JsonValueKind.Object"/>. /// </exception> public bool TryGetHeaderParameter(ReadOnlySpan <byte> headerParameterName, out JwtElement value) => _document.TryGetProperty(headerParameterName, out value);
/// <summary> /// Looks for a header parameter named <paramref name="headerParameterName"/> in the current JWT, returning /// whether or not such a parameter existed. When the parameter exists <paramref name="value"/> /// is assigned to the value of that parameter. /// </summary> /// <param name="headerParameterName">Name of the parameter to find.</param> /// <param name="value">Receives the value of the located parameter.</param> /// <returns> /// <see langword="true"/> if the parameter was found, <see langword="false"/> otherwise. /// </returns> /// <exception cref="InvalidOperationException"> /// This value is not <see cref="JsonValueKind.Object"/>. /// </exception> public bool TryGetHeaderParameter(JsonEncodedText headerParameterName, out JwtElement value) => _document.TryGetProperty(headerParameterName.EncodedUtf8Bytes, out value);
internal bool TryGetProperty(ReadOnlySpan <char> propertyName, out JwtElement value) => _parent.TryGetNamedPropertyValue(propertyName, out value);
/// <summary> /// Looks for a claim named <paramref name="claimName"/> in the current JWT, returning /// whether or not such a claim existed. When the claim exists <paramref name="value"/> /// is assigned to the value of that claim. /// </summary> /// <param name="claimName">Name of the claim to find.</param> /// <param name="value">Receives the value of the located claim.</param> /// <returns> /// <see langword="true"/> if the claim was found, <see langword="false"/> otherwise. /// </returns> /// <exception cref="InvalidOperationException"> /// This value is not <see cref="JsonValueKind.Object"/>. /// </exception> /// <exception cref="ObjectDisposedException"> /// The parent <see cref="JwtDocument"/> has been disposed. /// </exception> public bool TryGetClaim(ReadOnlySpan <byte> claimName, out JwtElement value) => _document.TryGetProperty(claimName, out value);
/// <summary> /// Looks for a claim named <paramref name="claimName"/> in the current JWT, returning /// whether or not such a claim existed. When the claim exists <paramref name="value"/> /// is assigned to the value of that claim. /// </summary> /// <param name="claimName">Name of the claim to find.</param> /// <param name="value">Receives the value of the located claim.</param> /// <returns> /// <see langword="true"/> if the claim was found, <see langword="false"/> otherwise. /// </returns> /// <exception cref="InvalidOperationException"> /// This value is not <see cref="JsonValueKind.Object"/>. /// </exception> /// <exception cref="ObjectDisposedException"> /// The parent <see cref="JwtDocument"/> has been disposed. /// </exception> public bool TryGetClaim(JsonEncodedText claimName, out JwtElement value) => _document.TryGetProperty(claimName.EncodedUtf8Bytes, out value);
/// <summary>Gets the value associated with the specified key.</summary> public bool TryGetProperty(ReadOnlySpan <byte> key, [NotNullWhen(true)] out JwtElement value) => _root.TryGetProperty(key, out value);
/// <summary> /// Looks for a header parameter named <paramref name="headerParameterName"/> in the current JWT, returning /// whether or not such a parameter existed. When the parameter exists <paramref name="value"/> /// is assigned to the value of that parameter. /// </summary> /// <param name="headerParameterName">Name of the header parameter to find.</param> /// <param name="value">Receives the value of the located parameter.</param> /// <returns> /// <see langword="true"/> if the parameter was found, <see langword="false"/> otherwise. /// </returns> /// <exception cref="InvalidOperationException"> /// This value is not <see cref="JsonValueKind.Object"/>. /// </exception> public bool TryGetHeaderParameter(string headerParameterName, out JwtElement value) => _document.TryGetProperty(headerParameterName, out value);
/// <summary>Parses the <see cref="JwtElement"/> into its <see cref="KeyManagementAlgorithm"/> representation.</summary> public static bool TryParse(JwtElement value, [NotNullWhen(true)] out KeyManagementAlgorithm?algorithm) { if (value.ValueEquals(Dir._utf8Name.EncodedUtf8Bytes)) { algorithm = Dir; goto Found; } else if (value.ValueEquals(A128KW._utf8Name.EncodedUtf8Bytes)) { algorithm = A128KW; goto Found; } else if (value.ValueEquals(A192KW._utf8Name.EncodedUtf8Bytes)) { algorithm = A192KW; goto Found; } else if (value.ValueEquals(A256KW._utf8Name.EncodedUtf8Bytes)) { algorithm = A256KW; goto Found; } else if (value.ValueEquals(Rsa1_5._utf8Name.EncodedUtf8Bytes)) { algorithm = Rsa1_5; goto Found; } else if (value.ValueEquals(EcdhEs._utf8Name.EncodedUtf8Bytes)) { algorithm = EcdhEs; goto Found; } else if (value.ValueEquals(RsaOaep._utf8Name.EncodedUtf8Bytes)) { algorithm = RsaOaep; goto Found; } else if (value.ValueEquals(A128GcmKW._utf8Name.EncodedUtf8Bytes)) { algorithm = A128GcmKW; goto Found; } else if (value.ValueEquals(A192GcmKW._utf8Name.EncodedUtf8Bytes)) { algorithm = A192GcmKW; goto Found; } else if (value.ValueEquals(A256GcmKW._utf8Name.EncodedUtf8Bytes)) { algorithm = A256GcmKW; goto Found; } else if (value.ValueEquals(RsaOaep256._utf8Name.EncodedUtf8Bytes)) { algorithm = RsaOaep256; goto Found; } else if (value.ValueEquals(RsaOaep384._utf8Name.EncodedUtf8Bytes)) { algorithm = RsaOaep384; goto Found; } else if (value.ValueEquals(RsaOaep512._utf8Name.EncodedUtf8Bytes)) { algorithm = RsaOaep512; goto Found; } else if (value.ValueEquals(EcdhEsA128KW._utf8Name.EncodedUtf8Bytes)) { algorithm = EcdhEsA128KW; goto Found; } else if (value.ValueEquals(EcdhEsA192KW._utf8Name.EncodedUtf8Bytes)) { algorithm = EcdhEsA192KW; goto Found; } else if (value.ValueEquals(EcdhEsA256KW._utf8Name.EncodedUtf8Bytes)) { algorithm = EcdhEsA256KW; goto Found; } else if (value.ValueEquals(Pbes2HS256A128KW._utf8Name.EncodedUtf8Bytes)) { algorithm = Pbes2HS256A128KW; goto Found; } else if (value.ValueEquals(Pbes2HS384A192KW._utf8Name.EncodedUtf8Bytes)) { algorithm = Pbes2HS384A192KW; goto Found; } else if (value.ValueEquals(Pbes2HS512A256KW._utf8Name.EncodedUtf8Bytes)) { algorithm = Pbes2HS512A256KW; goto Found; } algorithm = null; return(false); Found: return(true); }
internal bool TryGetProperty(string propertyName, out JwtElement value) => TryGetProperty(propertyName.AsSpan(), out value);