Exemplo n.º 1
0
        private void AdjustVMForAuthorization(AuthorizeApiKeysViewModel vm)
        {
            var parsedPermissions = Permission.ToPermissions(vm.Permissions.Split(';')).GroupBy(permission => permission.Policy);

            for (var index = vm.PermissionValues.Count - 1; index >= 0; index--)
            {
                var permissionValue = vm.PermissionValues[index];
                var wanted          = parsedPermissions?.SingleOrDefault(permission =>
                                                                         permission.Key.Equals(permissionValue.Permission,
                                                                                               StringComparison.InvariantCultureIgnoreCase));
                if (vm.Strict && !(wanted?.Any() ?? false))
                {
                    vm.PermissionValues.RemoveAt(index);
                    continue;
                }
                else if (wanted?.Any() ?? false)
                {
                    if (vm.SelectiveStores && Policies.IsStorePolicy(permissionValue.Permission) &&
                        wanted.Any(permission => !string.IsNullOrEmpty(permission.StoreId)))
                    {
                        permissionValue.StoreMode      = AddApiKeyViewModel.ApiKeyStoreMode.Specific;
                        permissionValue.SpecificStores = wanted.Select(permission => permission.StoreId).ToList();
                    }
                    else
                    {
                        permissionValue.StoreMode      = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
                        permissionValue.SpecificStores = new List <string>();
                        permissionValue.Value          = true;
                    }
                }
            }
        }
Exemplo n.º 2
0
        public async Task <IActionResult> AuthorizeAPIKey([FromForm] AuthorizeApiKeysViewModel viewModel)
        {
            await SetViewModelValues(viewModel);

            AdjustVMForAuthorization(viewModel);
            var ar = HandleCommands(viewModel);

            if (ar != null)
            {
                return(ar);
            }

            for (int i = 0; i < viewModel.PermissionValues.Count; i++)
            {
                if (viewModel.PermissionValues[i].Forbidden && viewModel.Strict)
                {
                    viewModel.PermissionValues[i].Value = false;
                    ModelState.AddModelError($"{viewModel.PermissionValues}[{i}].Value",
                                             $"The permission '{viewModel.PermissionValues[i].Title}' is required for this application.");
                }

                if (viewModel.PermissionValues[i].StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific &&
                    !viewModel.SelectiveStores)
                {
                    viewModel.PermissionValues[i].StoreMode = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
                    ModelState.AddModelError($"{viewModel.PermissionValues}[{i}].Value",
                                             $"The permission '{viewModel.PermissionValues[i].Title}' cannot be store specific for this application.");
                }
            }

            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }

            switch (viewModel.Command.ToLowerInvariant())
            {
            case "no":
                return(RedirectToAction("APIKeys"));

            case "yes":
                var key = await CreateKey(viewModel, (viewModel.ApplicationIdentifier, viewModel.RedirectUrl?.Authority));

                if (viewModel.RedirectUrl != null)
                {
                    return(Redirect(GetRedirectToApplicationUrl(viewModel.RedirectUrl, key)));
                }

                TempData.SetStatusMessageModel(new StatusMessageModel()
                {
                    Severity = StatusMessageModel.StatusSeverity.Success,
                    Html     = $"API key generated! <code class='alert-link'>{key.Id}</code>"
                });
                return(RedirectToAction("APIKeys", new { key = key.Id }));

            default:
                return(View(viewModel));
            }
        }
        public async Task <IActionResult> AuthorizeAPIKey(string[] permissions, string applicationName = null, Uri redirect = null,
                                                          bool strict = true, bool selectiveStores = false, string applicationIdentifier = null)
        {
            if (!_btcPayServerEnvironment.IsSecure)
            {
                TempData.SetStatusMessageModel(new StatusMessageModel
                {
                    Severity = StatusMessageModel.StatusSeverity.Error,
                    Message  = "Cannot generate API keys while not on https or using Tor"
                });
                return(RedirectToAction("APIKeys"));
            }

            permissions ??= Array.Empty <string>();

            var requestPermissions = Permission.ToPermissions(permissions).ToList();

            if (redirect?.IsAbsoluteUri is false)
            {
                redirect = null;
            }

            var vm = new AuthorizeApiKeysViewModel
            {
                RedirectUrl           = redirect,
                Label                 = applicationName,
                ApplicationName       = applicationName,
                SelectiveStores       = selectiveStores,
                Strict                = strict,
                Permissions           = string.Join(';', requestPermissions),
                ApplicationIdentifier = applicationIdentifier
            };

            var existingApiKey = await CheckForMatchingApiKey(requestPermissions, vm);

            if (existingApiKey != null)
            {
                vm.ApiKey = existingApiKey.Id;
                return(View("ConfirmAPIKey", vm));
            }

            vm = await SetViewModelValues(vm);

            AdjustVMForAuthorization(vm);

            return(View(vm));
        }
Exemplo n.º 4
0
        public async Task <IActionResult> AuthorizeAPIKey([FromForm] AuthorizeApiKeysViewModel viewModel)
        {
            await SetViewModelValues(viewModel);

            AdjustVMForAuthorization(viewModel);
            var ar = HandleCommands(viewModel);

            if (ar != null)
            {
                return(ar);
            }

            for (int i = 0; i < viewModel.PermissionValues.Count; i++)
            {
                if (viewModel.PermissionValues[i].Forbidden && viewModel.Strict)
                {
                    viewModel.PermissionValues[i].Value = false;
                    ModelState.AddModelError($"{viewModel.PermissionValues}[{i}].Value",
                                             $"The permission '{viewModel.PermissionValues[i].Title}' is required for this application.");
                }

                if (viewModel.PermissionValues[i].StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific &&
                    !viewModel.SelectiveStores)
                {
                    viewModel.PermissionValues[i].StoreMode = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
                    ModelState.AddModelError($"{viewModel.PermissionValues}[{i}].Value",
                                             $"The permission '{viewModel.PermissionValues[i].Title}' cannot be store specific for this application.");
                }
            }

            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }

            var command = viewModel.Command.ToLowerInvariant();

            switch (command)
            {
            case "cancel":
                return(RedirectToAction("APIKeys"));

            case "authorize":
            case "confirm":
                var key = command == "authorize"
                        ? await CreateKey(viewModel, (viewModel.ApplicationIdentifier, viewModel.RedirectUrl?.Authority))
                        : await _apiKeyRepository.GetKey(viewModel.ApiKey);

                if (viewModel.RedirectUrl != null)
                {
                    var permissions = key.GetBlob().Permissions;
                    var redirectVm  = new PostRedirectViewModel()
                    {
                        FormUrl    = viewModel.RedirectUrl.ToString(),
                        Parameters =
                        {
                            new KeyValuePair <string, string>("apiKey", key.Id),
                            new KeyValuePair <string, string>("userId", key.UserId)
                        }
                    };
                    foreach (var permission in permissions)
                    {
                        redirectVm.Parameters.Add(
                            new KeyValuePair <string, string>("permissions[]", permission));
                    }

                    return(View("PostRedirect", redirectVm));
                }

                TempData.SetStatusMessageModel(new StatusMessageModel()
                {
                    Severity = StatusMessageModel.StatusSeverity.Success,
                    Html     = $"API key generated! <code class='alert-link'>{key.Id}</code>"
                });

                return(RedirectToAction("APIKeys", new { key = key.Id }));

            default:
                return(View(viewModel));
            }
        }
Exemplo n.º 5
0
        private void AdjustVMForAuthorization(AuthorizeApiKeysViewModel vm)
        {
            var permissions             = vm.Permissions?.Split(';') ?? Array.Empty <string>();
            var permissionsWithStoreIDs = new List <string>();

            /**
             * Go over each permission and associated store IDs and
             * join them so that permission for a specific store is parsed correctly
             */
            for (var i = 0; i < permissions.Length; i++)
            {
                var currPerm = permissions[i];
                var storeIds = vm.PermissionValues[i].SpecificStores.ToArray();
                if (storeIds.Length > 0)
                {
                    for (var x = 0; x < storeIds.Length; x++)
                    {
                        permissionsWithStoreIDs.Add($"{currPerm}:{storeIds[x]}");
                    }
                }
                else
                {
                    permissionsWithStoreIDs.Add(currPerm);
                }
            }

            var parsedPermissions = Permission.ToPermissions(permissionsWithStoreIDs.ToArray()).GroupBy(permission => permission.Policy);

            for (var index = vm.PermissionValues.Count - 1; index >= 0; index--)
            {
                var permissionValue = vm.PermissionValues[index];
                var wanted          = parsedPermissions?.SingleOrDefault(permission =>
                                                                         permission.Key.Equals(permissionValue.Permission,
                                                                                               StringComparison.InvariantCultureIgnoreCase));
                if (vm.Strict && !(wanted?.Any() ?? false))
                {
                    vm.PermissionValues.RemoveAt(index);
                    continue;
                }
                else if (wanted?.Any() ?? false)
                {
                    var commandParts         = vm.Command?.Split(':', StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty <string>();
                    var command              = commandParts.Length > 1 ? commandParts[1] : null;
                    var isPerformingAnAction = command == "change-store-mode" || command == "add-store";
                    // Don't want to accidentally change mode for the user if they are explicitly performing some action
                    if (isPerformingAnAction)
                    {
                        continue;
                    }

                    if (vm.SelectiveStores && Policies.IsStorePolicy(permissionValue.Permission) &&
                        wanted.Any(permission => !string.IsNullOrEmpty(permission.Scope)))
                    {
                        permissionValue.StoreMode      = AddApiKeyViewModel.ApiKeyStoreMode.Specific;
                        permissionValue.SpecificStores = wanted.Select(permission => permission.Scope).ToList();
                    }
                    else
                    {
                        permissionValue.StoreMode      = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
                        permissionValue.SpecificStores = new List <string>();
                        permissionValue.Value          = true;
                    }
                }
            }
        }
        public async Task <IActionResult> AuthorizeAPIKey([FromForm] AuthorizeApiKeysViewModel viewModel)
        {
            await SetViewModelValues(viewModel);

            var ar = HandleCommands(viewModel);

            if (ar != null)
            {
                return(ar);
            }


            if (viewModel.PermissionsFormatted.Contains(Permissions.ServerManagement))
            {
                if (!viewModel.IsServerAdmin && viewModel.ServerManagementPermission)
                {
                    viewModel.ServerManagementPermission = false;
                }

                if (!viewModel.ServerManagementPermission && viewModel.Strict)
                {
                    ModelState.AddModelError(nameof(viewModel.ServerManagementPermission),
                                             "This permission is required for this application.");
                }
            }

            if (viewModel.PermissionsFormatted.Contains(Permissions.StoreManagement))
            {
                if (!viewModel.SelectiveStores &&
                    viewModel.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific)
                {
                    viewModel.StoreMode = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
                    ModelState.AddModelError(nameof(viewModel.StoreManagementPermission),
                                             "This application does not allow selective store permissions.");
                }

                if (!viewModel.StoreManagementPermission && !viewModel.SpecificStores.Any() && viewModel.Strict)
                {
                    ModelState.AddModelError(nameof(viewModel.StoreManagementPermission),
                                             "This permission is required for this application.");
                }
            }

            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }

            switch (viewModel.Command.ToLowerInvariant())
            {
            case "no":
                return(RedirectToAction("APIKeys"));

            case "yes":
                var key = await CreateKey(viewModel);

                TempData.SetStatusMessageModel(new StatusMessageModel()
                {
                    Severity = StatusMessageModel.StatusSeverity.Success,
                    Html     = $"API key generated! <code>{key.Id}</code>"
                });
                return(RedirectToAction("APIKeys", new { key = key.Id }));

            default: return(View(viewModel));
            }
        }
        private async Task <APIKeyData> CheckForMatchingApiKey(IEnumerable <Permission> requestedPermissions, AuthorizeApiKeysViewModel vm)
        {
            if (string.IsNullOrEmpty(vm.ApplicationIdentifier) || vm.RedirectUrl == null)
            {
                return(null);
            }

            //check if there is an app identifier that matches and belongs to the current user
            var keys = await _apiKeyRepository.GetKeys(new APIKeyRepository.APIKeyQuery
            {
                UserId = new[] { _userManager.GetUserId(User) }
            });

            foreach (var key in keys)
            {
                var blob = key.GetBlob();
                if (blob.ApplicationIdentifier != vm.ApplicationIdentifier || blob.ApplicationAuthority != vm.RedirectUrl.AbsoluteUri)
                {
                    continue;
                }

                var requestedGrouped = requestedPermissions.GroupBy(permission => permission.Policy);
                var existingGrouped  = Permission.ToPermissions(blob.Permissions).GroupBy(permission => permission.Policy);

                //matched the identifier and authority, but we need to check if what the app is requesting in terms of permissions is enough
                var fail = false;
                foreach (var requested in requestedGrouped)
                {
                    var existing = existingGrouped.SingleOrDefault(grouping => requested.Key == grouping.Key);
                    if (vm.Strict && existing == null)
                    {
                        fail = true;
                        break;
                    }

                    if (Policies.IsStorePolicy(requested.Key))
                    {
                        if ((vm.SelectiveStores && !existing.Any(p => p.Scope == vm.StoreId)) ||
                            (!vm.SelectiveStores && existing.Any(p => !string.IsNullOrEmpty(p.Scope))))
                        {
                            fail = true;
                            break;
                        }
                    }
                }

                if (fail)
                {
                    continue;
                }

                //we have a key that is sufficient, redirect to a page to confirm that it's ok to provide this key to the app.
                return(key);
            }

            return(null);
        }
Exemplo n.º 8
0
        public async Task <IActionResult> AuthorizeAPIKey([FromForm] AuthorizeApiKeysViewModel viewModel)
        {
            await SetViewModelValues(viewModel);

            var ar = HandleCommands(viewModel);

            if (ar != null)
            {
                return(ar);
            }

            if (viewModel.Strict)
            {
                for (int i = 0; i < viewModel.PermissionValues.Count; i++)
                {
                    if (viewModel.PermissionValues[i].Forbidden)
                    {
                        ModelState.AddModelError($"{viewModel.PermissionValues}[{i}].Value",
                                                 $"The permission '{viewModel.PermissionValues[i].Title}' is required for this application.");
                    }
                }
            }

            var permissions = Permission.ToPermissions(viewModel.Permissions).ToHashSet();

            if (permissions.Contains(Permission.Create(Policies.CanModifyStoreSettings)))
            {
                if (!viewModel.SelectiveStores &&
                    viewModel.StoreMode == AddApiKeyViewModel.ApiKeyStoreMode.Specific)
                {
                    viewModel.StoreMode = AddApiKeyViewModel.ApiKeyStoreMode.AllStores;
                    ModelState.AddModelError(nameof(viewModel.StoreManagementPermission),
                                             "This application does not allow selective store permissions.");
                }

                if (!viewModel.StoreManagementPermission.Value && !viewModel.SpecificStores.Any() && viewModel.Strict)
                {
                    ModelState.AddModelError(nameof(viewModel.StoreManagementPermission),
                                             $"This permission '{viewModel.StoreManagementPermission.Title}' is required for this application.");
                }
            }

            if (!ModelState.IsValid)
            {
                return(View(viewModel));
            }

            switch (viewModel.Command.ToLowerInvariant())
            {
            case "no":
                return(RedirectToAction("APIKeys"));

            case "yes":
                var key = await CreateKey(viewModel);

                TempData.SetStatusMessageModel(new StatusMessageModel()
                {
                    Severity = StatusMessageModel.StatusSeverity.Success,
                    Html     = $"API key generated! <code>{key.Id}</code>"
                });
                return(RedirectToAction("APIKeys", new { key = key.Id }));

            default:
                return(View(viewModel));
            }
        }