private async Task <IEnumerable <(User user, IPermissionScope permissionScope)> > GetOrCreatePermissionUsers(string userId, CancellationToken ct)
        {
            // Create a user creation task for each of the permission type - i.e. a user for read-only, a user for read-write etc.
            var permissionUserTasks = KnownPermissionScopes
                                      .Select(permissionScope => GetOrCreateUser(userId, permissionScope, ct));

            // Run user creations in parallel.
            return(await Task.WhenAll(permissionUserTasks));
        }
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "broker")] HttpRequest req,
            ILogger log)
        {
            // Extracting the Access Token from the http request from the client
            string accessToken = null;

            try
            {
                accessToken = req?.Headers?["Authorization"].ToString()?.Replace("Bearer ", string.Empty);

                if (string.IsNullOrEmpty(accessToken))
                {
                    return(LogErrorAndReturnBadObjectResult("Access token is missing", log));
                }
            }
            catch (Exception ex)
            {
                return(LogErrorAndReturnBadObjectResult("Unable to read Authorization header", log, ex));
            }


            // Decrypting and reading the Access Token
            JwtSecurityToken token = null;

            try
            {
                var handler = new JwtSecurityTokenHandler();

                token = handler.ReadJwtToken(accessToken);

                log.Log(LogLevel.Information, $"Jwt: {token}");

                if (!handler.CanValidateToken)
                {
                    return(LogErrorAndReturnBadObjectResult($"Unable to validate token: {accessToken}", log));
                }
            }
            catch (Exception ex)
            {
                return(LogErrorAndReturnBadObjectResult($"Unable to read JWT token: {accessToken}", log, ex));
            }

#if DEBUG
            var expires = token.ValidTo;

            var ignoreExpires = req?.Headers?["IgnoreExpires"].ToString().ToLower() == "true";

            if (DateTime.UtcNow > expires && !ignoreExpires)
            {
                return(LogErrorAndReturnBadObjectResult("The access token have expired. " +
                                                        "Note this error is for debug mode only, for use when testing. " +
                                                        "In production access token validity is handled by Azure Functions configuration.", log));
            }
#endif

            // Getting the user object id from the Access Token
            var userObjectId = token?.Subject;

            if (string.IsNullOrEmpty(userObjectId))
            {
                return(LogErrorAndReturnBadObjectResult("No subject defined in access token", log));
            }

            // Getting the permission scope from the Access Token to determine the permission mode.
            var accessTokenScopes = token?.Claims.FirstOrDefault(c => c.Type.ToLowerInvariant() == "scp")?.Value.Split(' ');

            if (!accessTokenScopes?.Any() ?? false)
            {
                return(LogErrorAndReturnBadObjectResult("No scopes defined", log));
            }


            // Extracting the known scopes only.
            var permissionScopes = accessTokenScopes?.Select(scope => KnownPermissionScopes?.FirstOrDefault(ks => ks?.Scope == scope));

            if (!permissionScopes?.Any() ?? false)
            {
                return(LogErrorAndReturnBadObjectResult($"No known scopes: " +
                                                        $"{string.Join(", ", accessTokenScopes)}. " +
                                                        $"Known scopes are: " +
                                                        $"{string.Join(", ", KnownPermissionScopes.Select(ks => ks.Scope))}", log));
            }

            try
            {
                await using var brokerService = new ResourceTokenBrokerService(_cosmosHostUrl, _cosmosKey, _cosmosDatabaseId, _cosmosCollectionId);

                // Getting the Resource Permission Tokens
                var permissionToken = await brokerService.Get(userObjectId, permissionScopes);

                return((IActionResult) new JsonResult(permissionToken, new JsonSerializerSettings {
                    TypeNameHandling = TypeNameHandling.All
                }));
            }
            catch (Exception ex)
            {
                return(LogErrorAndReturnBadObjectResult($"Unable to acquire resource token from Cosmos DB " +
                                                        $"for user with id: {userObjectId} " +
                                                        $"for permission scopes: {string.Join(", ", permissionScopes)}.", log, ex));
            }
        }