/* * Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ using System; using System.Text; using System.Collections.Generic; using System.Security.Cryptography; using System.Reflection; using Amazon.Runtime; using Amazon.CognitoIdentityProvider.Model; namespace Amazon.Extensions.CognitoAuthentication.Util { internal static class CognitoAuthHelper { [ThreadStatic] private static SHA256 sha256 = null; private static string assemblyFileVersion = null; /// /// Property to access the thread-safe SHA256 member variable. /// Creates a SHA256 instance if one does not exist. /// internal static SHA256 Sha256 { get { if (sha256 == null) { sha256 = SHA256.Create(); } return sha256; } } internal static string AssemblyFileVersion { get { if (assemblyFileVersion == null) { var assembly = typeof(CognitoAuthHelper).GetTypeInfo().Assembly; AssemblyFileVersionAttribute attribute = assembly.GetCustomAttribute(typeof(AssemblyFileVersionAttribute)) as AssemblyFileVersionAttribute; assemblyFileVersion = attribute == null ? "Unknown" : attribute.Version; } return assemblyFileVersion; } } /// /// Computes the secret hash for the user pool using the corresponding userID, clientID, /// and client secret /// /// The current userID /// The clientID for the client being used /// The client secret of the corresponding clientID /// Returns the secret hash for the user pool using the corresponding /// userID, clientID, and client secret public static string GetUserPoolSecretHash(string userID, string clientID, string clientSecret) { string message = userID + clientID; byte[] keyBytes = Encoding.UTF8.GetBytes(clientSecret); byte[] messageBytes = Encoding.UTF8.GetBytes(message); HMACSHA256 hmacSha256 = new HMACSHA256(keyBytes); byte[] hashMessage = hmacSha256.ComputeHash(messageBytes); return Convert.ToBase64String(hashMessage); } /// /// Creates a byte array which combines all of the byte[] in values in the order of the array /// /// An array of byte[] to be combined /// Returns a byte array which combines all of the byte[] in values internal static byte[] CombineBytes(params byte[][] values) { int combinedLength = 0; byte[] returnBytes; int copyIndex = 0; for (int i = 0; i < values.Length; i++) { combinedLength += values[i].Length; } returnBytes = new byte[combinedLength]; for (int i = 0; i < values.Length; i++) { Buffer.BlockCopy(values[i], 0, returnBytes, copyIndex, values[i].Length); copyIndex += values[i].Length; } return returnBytes; } /// /// Converts a hexadecimal string to a byte array /// /// The hexadecimal string to be converted to a byte array /// Returns the byte array for the corresponding string internal static byte[] StringToByteArray(string hexString) { if (hexString.Length % 2 != 0) { throw new ArgumentException("Malformed hexString.", "hexString"); } int stringLen = hexString.Length; byte[] bytes = new byte[stringLen / 2]; for (int i = 0; i < stringLen; i += 2) { bytes[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16); } return bytes; } /// /// Internal method to convert a dictionary of user attributes to a list of AttributeType /// /// Dictionary containing attributes of type string /// Returns a List of AttributeType objects internal static List CreateAttributeList(IDictionary attributeDict) { List attributeList = new List(); foreach (KeyValuePair data in attributeDict) { AttributeType attribute = new AttributeType() { Name = data.Key, Value = data.Value }; attributeList.Add(attribute); } return attributeList; } /// /// Internal method for handling metrics /// private const string UserAgentHeader = "User-Agent"; internal static void ServiceClientBeforeRequestEvent(object sender, RequestEventArgs e) { Amazon.Runtime.WebServiceRequestEventArgs args = e as Amazon.Runtime.WebServiceRequestEventArgs; if (args == null || !args.Headers.ContainsKey(UserAgentHeader)) return; var metric = " AWSDotNetCognito/" + AssemblyFileVersion; if (!args.Headers[UserAgentHeader].Contains(metric)) { args.Headers[UserAgentHeader] = args.Headers[UserAgentHeader] + metric; } } } }