Skip to content

Commit 1aefa86

Browse files
authored
Merge pull request #24 from umbraco/feature/zapier-api-key-auth
Validate access using also an API key.
2 parents 548f00a + 42014d3 commit 1aefa86

File tree

10 files changed

+59
-38
lines changed

10 files changed

+59
-38
lines changed

src/Umbraco.Cms.Integrations.Automation.Zapier/Configuration/ZapierSettings.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ public ZapierSettings()
1111

1212
public ZapierSettings(NameValueCollection appSettings)
1313
{
14-
UserGroup = appSettings[Constants.UmbracoCmsIntegrationsAutomationZapierUserGroup];
14+
UserGroupAlias = appSettings[Constants.UmbracoCmsIntegrationsAutomationZapierUserGroupAlias];
15+
16+
ApiKey = appSettings[Constants.UmbracoCmsIntegrationsAutomationZapierApiKey];
1517
}
1618

17-
public string UserGroup { get; set; }
19+
public string UserGroupAlias { get; set; }
20+
21+
public string ApiKey { get; set; }
1822
}
1923
}

src/Umbraco.Cms.Integrations.Automation.Zapier/Constants.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@ public class Constants
99

1010
public const string TargetStateName = "zapiersubscriptionhook-db";
1111

12-
public const string UmbracoCmsIntegrationsAutomationZapierUserGroup = "Umbraco.Cms.Integrations.Automation.Zapier.UserGroup";
12+
public const string UmbracoCmsIntegrationsAutomationZapierUserGroupAlias = "Umbraco.Cms.Integrations.Automation.Zapier.UserGroupAlias";
13+
14+
public const string UmbracoCmsIntegrationsAutomationZapierApiKey = "Umbraco.Cms.Integrations.Automation.Zapier.ApiKey";
1315

1416
public static class ZapierAppConfiguration
1517
{
1618
public const string UsernameHeaderKey = "X-USERNAME";
1719

1820
public const string PasswordHeaderKey = "X-PASSWORD";
21+
22+
public const string ApiKeyHeaderKey = "X-APIKEY";
1923
}
2024

2125
public static class Configuration
Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
using System.Threading.Tasks;
22

3-
using Umbraco.Cms.Integrations.Automation.Zapier.Configuration;
43
using Umbraco.Cms.Integrations.Automation.Zapier.Models;
54
using Umbraco.Cms.Integrations.Automation.Zapier.Services;
65

76
#if NETCOREAPP
87
using Microsoft.AspNetCore.Mvc;
9-
using Microsoft.Extensions.Options;
8+
109
using Umbraco.Cms.Web.Common.Controllers;
11-
using Umbraco.Cms.Core.Security;
1210
#else
1311
using System.Web.Http;
14-
using System.Configuration;
15-
using Umbraco.Cms.Integrations.Automation.Zapier.Models.Dtos;
12+
1613
using Umbraco.Web.WebApi;
1714
#endif
1815

@@ -23,31 +20,14 @@ namespace Umbraco.Cms.Integrations.Automation.Zapier.Controllers
2320
/// </summary>
2421
public class AuthController : UmbracoApiController
2522
{
26-
private readonly ZapierSettings Options;
27-
2823
private readonly IUserValidationService _userValidationService;
2924

30-
#if NETCOREAPP
31-
private readonly IBackOfficeUserManager _backOfficeUserManager;
32-
33-
public AuthController(IBackOfficeUserManager backOfficeUserManager, IUserValidationService userValidationService, IOptions<ZapierSettings> options)
34-
{
35-
_backOfficeUserManager = backOfficeUserManager;
36-
37-
_userValidationService = userValidationService;
38-
39-
Options = options.Value;
40-
}
41-
#else
4225
public AuthController(IUserValidationService userValidationService)
4326
{
44-
Options = new ZapierSettings(ConfigurationManager.AppSettings);
45-
4627
_userValidationService = userValidationService;
4728
}
48-
#endif
4929

5030
[HttpPost]
51-
public async Task<bool> ValidateUser([FromBody] UserModel userModel) => await _userValidationService.Validate(userModel.Username, userModel.Password, Options.UserGroup);
31+
public async Task<bool> ValidateUser([FromBody] UserModel userModel) => await _userValidationService.Validate(userModel.Username, userModel.Password, userModel.ApiKey);
5232
}
5333
}

src/Umbraco.Cms.Integrations.Automation.Zapier/Controllers/ContentController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public ContentController(IContentTypeService contentTypeService, IUserValidation
3535

3636
public IEnumerable<ContentTypeDto> GetContentTypes()
3737
{
38-
if (!IsUserValid()) return null;
38+
if (!IsAccessValid()) return null;
3939

4040
var contentTypes = _contentTypeService.GetAll();
4141

src/Umbraco.Cms.Integrations.Automation.Zapier/Controllers/PollingController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public PollingController(IContentService contentService, IContentTypeService con
4444
[Obsolete("Used only for Umbraco Zapier app v1.0.0. For updated versions use GetContentByType")]
4545
public IEnumerable<PublishedContentDto> GetSampleContent()
4646
{
47-
if (!IsUserValid()) return null;
47+
if (!IsAccessValid()) return null;
4848

4949
var rootNodes = _contentService.GetRootContent()
5050
.Where(p => p.Published)
@@ -60,7 +60,7 @@ public IEnumerable<PublishedContentDto> GetSampleContent()
6060

6161
public List<Dictionary<string, string>> GetContentByType(string alias)
6262
{
63-
if (!IsUserValid()) return null;
63+
if (!IsAccessValid()) return null;
6464

6565
var contentType = _contentTypeService.Get(alias);
6666
if (contentType == null) return new List<Dictionary<string, string>>();

src/Umbraco.Cms.Integrations.Automation.Zapier/Controllers/SubscriptionController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public SubscriptionController(
3838
[HttpPost]
3939
public bool UpdatePreferences([FromBody] SubscriptionDto dto)
4040
{
41-
if (!IsUserValid() || dto == null) return false;
41+
if (!IsAccessValid() || dto == null) return false;
4242

4343
var result = dto.SubscribeHook
4444
? _zapierSubscriptionHookService.Add(dto.EntityId, dto.Type, dto.HookUrl)

src/Umbraco.Cms.Integrations.Automation.Zapier/Controllers/ZapierAuthorizedApiController.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@ public ZapierAuthorizedApiController(IUserValidationService userValidationServic
3636
_userValidationService = userValidationService;
3737
}
3838

39-
public bool IsUserValid()
39+
public bool IsAccessValid()
4040
{
4141
string username = string.Empty;
4242
string password = string.Empty;
43+
string apiKey = string.Empty;
4344

4445
#if NETCOREAPP
4546
if (Request.Headers.TryGetValue(Constants.ZapierAppConfiguration.UsernameHeaderKey,
@@ -48,18 +49,27 @@ public bool IsUserValid()
4849
if (Request.Headers.TryGetValue(Constants.ZapierAppConfiguration.PasswordHeaderKey,
4950
out var passwordValues))
5051
password = passwordValues.First();
52+
if (Request.Headers.TryGetValue(Constants.ZapierAppConfiguration.ApiKeyHeaderKey,
53+
out var apiKeyValues))
54+
apiKey = apiKeyValues.First();
5155
#else
5256
if (Request.Headers.TryGetValues(Constants.ZapierAppConfiguration.UsernameHeaderKey,
5357
out var usernameValues))
5458
username = usernameValues.First();
5559
if (Request.Headers.TryGetValues(Constants.ZapierAppConfiguration.PasswordHeaderKey,
5660
out var passwordValues))
5761
password = passwordValues.First();
62+
if (Request.Headers.TryGetValues(Constants.ZapierAppConfiguration.ApiKeyHeaderKey,
63+
out var apiKeyValues))
64+
apiKey = apiKeyValues.First();
5865
#endif
5966

60-
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return false;
67+
if (string.IsNullOrEmpty(apiKey) && (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))) return false;
6168

62-
var isAuthorized = _userValidationService.Validate(username, password, Options.UserGroup).GetAwaiter()
69+
if (!string.IsNullOrEmpty(apiKey))
70+
return apiKey == Options.ApiKey;
71+
72+
var isAuthorized = _userValidationService.Validate(username, password, Options.UserGroupAlias).GetAwaiter()
6373
.GetResult();
6474
if (!isAuthorized) return false;
6575

src/Umbraco.Cms.Integrations.Automation.Zapier/Models/UserModel.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ public class UserModel
66
public string Username { get; set; }
77

88
public string Password { get; set; }
9+
10+
public string ApiKey { get; set; }
911
}
1012
}

src/Umbraco.Cms.Integrations.Automation.Zapier/Services/IUserValidationService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ namespace Umbraco.Cms.Integrations.Automation.Zapier.Services
44
{
55
public interface IUserValidationService
66
{
7-
Task<bool> Validate(string username, string password, string userGroup);
7+
Task<bool> Validate(string username, string password, string apiKey);
88
}
99
}

src/Umbraco.Cms.Integrations.Automation.Zapier/Services/UserValidationService.cs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
using System.Linq;
22
using System.Threading.Tasks;
33

4+
using Umbraco.Cms.Integrations.Automation.Zapier.Configuration;
5+
46
#if NETCOREAPP
7+
using Microsoft.Extensions.Options;
8+
59
using Umbraco.Cms.Core.Security;
610
using Umbraco.Cms.Core.Services;
711
#else
12+
using System.Configuration;
13+
814
using Umbraco.Core.Services;
915
#endif
1016

@@ -14,23 +20,38 @@ public class UserValidationService : IUserValidationService
1420
{
1521
private readonly IUserService _userService;
1622

23+
private readonly ZapierSettings _zapierSettings;
1724

1825
#if NETCOREAPP
1926
private readonly IBackOfficeUserManager _backOfficeUserManager;
2027

21-
public UserValidationService(IBackOfficeUserManager backOfficeUserManager, IUserService userService)
28+
public UserValidationService(IOptions<ZapierSettings> options, IBackOfficeUserManager backOfficeUserManager)
2229
{
2330
_backOfficeUserManager = backOfficeUserManager;
31+
32+
_zapierSettings = options.Value;
2433
}
2534
#else
2635
public UserValidationService(IUserService userService)
2736
{
2837
_userService = userService;
38+
39+
_zapierSettings = new ZapierSettings(ConfigurationManager.AppSettings);
2940
}
3041
#endif
3142

32-
public async Task<bool> Validate(string username, string password, string userGroup)
43+
/// <summary>
44+
/// Allow access by validating API Key. If API key is missing, validate user credentials.
45+
/// </summary>
46+
/// <param name="username"></param>
47+
/// <param name="password"></param>
48+
/// <param name="apiKey"></param>
49+
/// <returns></returns>
50+
public async Task<bool> Validate(string username, string password, string apiKey)
3351
{
52+
if (!string.IsNullOrEmpty(apiKey))
53+
return apiKey == _zapierSettings.ApiKey;
54+
3455
#if NETCOREAPP
3556
var isUserValid =
3657
await _backOfficeUserManager.ValidateCredentialsAsync(username, password);
@@ -40,11 +61,11 @@ public async Task<bool> Validate(string username, string password, string userGr
4061

4162
if (!isUserValid) return false;
4263

43-
if (!string.IsNullOrEmpty(userGroup))
64+
if (!string.IsNullOrEmpty(_zapierSettings.UserGroupAlias))
4465
{
4566
var user = _userService.GetByUsername(username);
4667

47-
return user != null && user.Groups.Any(p => p.Name == userGroup);
68+
return user != null && user.Groups.Any(p => p.Alias == _zapierSettings.UserGroupAlias);
4869
}
4970

5071
return true;

0 commit comments

Comments
 (0)