Merge pull request #110 from sharpn/develop

Adding JWT authentication for use with auth0
This commit is contained in:
Tom Pallister
2017-06-30 09:32:55 +01:00
committed by GitHub
18 changed files with 934 additions and 630 deletions

View File

@ -6,6 +6,8 @@ using Ocelot.Responses;
namespace Ocelot.Authentication.Handler.Creator
{
using Ocelot.Configuration;
using AuthenticationOptions = Configuration.AuthenticationOptions;
/// <summary>
@ -17,15 +19,31 @@ namespace Ocelot.Authentication.Handler.Creator
{
var builder = app.New();
builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
if (authOptions.Provider.ToLower() == "jwt")
{
Authority = authOptions.ProviderRootUrl,
ApiName = authOptions.ApiName,
RequireHttpsMetadata = authOptions.RequireHttps,
AllowedScopes = authOptions.AllowedScopes,
SupportedTokens = SupportedTokens.Both,
ApiSecret = authOptions.ApiSecret
});
var authenticationConfig = authOptions.Config as JwtConfig;
builder.UseJwtBearerAuthentication(
new JwtBearerOptions()
{
Authority = authenticationConfig.Authority,
Audience = authenticationConfig.Audience
});
}
else
{
var authenticationConfig = authOptions.Config as IdentityServerConfig;
builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = authenticationConfig.ProviderRootUrl,
ApiName = authenticationConfig.ApiName,
RequireHttpsMetadata = authenticationConfig.RequireHttps,
AllowedScopes = authOptions.AllowedScopes,
SupportedTokens = SupportedTokens.Both,
ApiSecret = authenticationConfig.ApiSecret
});
}
var authenticationNext = builder.Build();

View File

@ -2,6 +2,7 @@
{
public enum SupportedAuthenticationProviders
{
IdentityServer
IdentityServer,
Jwt
}
}

View File

@ -2,24 +2,52 @@
namespace Ocelot.Configuration
{
using Newtonsoft.Json;
public class AuthenticationOptions
{
public AuthenticationOptions(string provider, string providerRootUrl, string apiName, bool requireHttps, List<string> allowedScopes, string apiSecret)
public AuthenticationOptions(string provider, List<string> allowedScopes, IAuthenticationConfig config)
{
Provider = provider;
ProviderRootUrl = providerRootUrl;
ApiName = apiName;
RequireHttps = requireHttps;
AllowedScopes = allowedScopes;
ApiSecret = apiSecret;
AllowedScopes = allowedScopes;
Config = config;
}
public string Provider { get; private set; }
public List<string> AllowedScopes { get; private set; }
public IAuthenticationConfig Config { get; private set; }
}
public class IdentityServerConfig : IAuthenticationConfig
{
public IdentityServerConfig(string providerRootUrl, string apiName, bool requireHttps, string apiSecret)
{
ProviderRootUrl = providerRootUrl;
ApiName = apiName;
RequireHttps = requireHttps;
ApiSecret = apiSecret;
}
public string ProviderRootUrl { get; private set; }
public string ApiName { get; private set; }
public string ApiSecret { get; private set; }
public bool RequireHttps { get; private set; }
public List<string> AllowedScopes { get; private set; }
}
public class JwtConfig : IAuthenticationConfig
{
public JwtConfig(string authority, string audience)
{
Audience = audience;
Authority = authority;
}
public string Audience { get; }
public string Authority { get; }
}
public interface IAuthenticationConfig {}
}

View File

@ -6,51 +6,93 @@ namespace Ocelot.Configuration.Builder
{
private string _provider;
private string _providerRootUrl;
private string _apiName;
private string _apiSecret;
private bool _requireHttps;
private List<string> _allowedScopes;
private IAuthenticationConfig _identityServerConfig;
public AuthenticationOptionsBuilder WithProvider(string provider)
{
_provider = provider;
return this;
}
public AuthenticationOptionsBuilder WithProviderRootUrl(string providerRootUrl)
{
_providerRootUrl = providerRootUrl;
return this;
}
public AuthenticationOptionsBuilder WithApiName(string apiName)
{
_apiName = apiName;
return this;
}
public AuthenticationOptionsBuilder WithApiSecret(string apiSecret)
{
_apiSecret = apiSecret;
return this;
}
public AuthenticationOptionsBuilder WithRequireHttps(bool requireHttps)
{
_requireHttps = requireHttps;
return this;
}
public AuthenticationOptionsBuilder WithAllowedScopes(List<string> allowedScopes)
{
_allowedScopes = allowedScopes;
return this;
}
public AuthenticationOptionsBuilder WithConfig(IAuthenticationConfig config)
{
_identityServerConfig = config;
return this;
}
public AuthenticationOptions Build()
{
return new AuthenticationOptions(_provider, _providerRootUrl, _apiName, _requireHttps, _allowedScopes, _apiSecret);
return new AuthenticationOptions(_provider, _allowedScopes, _identityServerConfig);
}
}
public class IdentityServerConfigBuilder
{
private string _providerRootUrl;
private string _apiName;
private string _apiSecret;
private bool _requireHttps;
public IdentityServerConfigBuilder WithProviderRootUrl(string providerRootUrl)
{
_providerRootUrl = providerRootUrl;
return this;
}
public IdentityServerConfigBuilder WithApiName(string apiName)
{
_apiName = apiName;
return this;
}
public IdentityServerConfigBuilder WithApiSecret(string apiSecret)
{
_apiSecret = apiSecret;
return this;
}
public IdentityServerConfigBuilder WithRequireHttps(bool requireHttps)
{
_requireHttps = requireHttps;
return this;
}
public IdentityServerConfig Build()
{
return new IdentityServerConfig(_providerRootUrl, _apiName, _requireHttps, _apiSecret);
}
}
public class JwtConfigBuilder
{
public string _authority;
public string _audience;
public JwtConfigBuilder WithAuthority(string authority)
{
_authority = authority;
return this;
}
public JwtConfigBuilder WithAudience(string audience)
{
_audience = audience;
return this;
}
public JwtConfig Build()
{
return new JwtConfig(_authority, _audience);
}
}
}

View File

@ -7,14 +7,13 @@ namespace Ocelot.Configuration.Creator
{
public AuthenticationOptions Create(FileReRoute fileReRoute)
{
var authenticationConfig = new ConfigCreator().Create(fileReRoute.AuthenticationOptions);
return new AuthenticationOptionsBuilder()
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
.WithProviderRootUrl(fileReRoute.AuthenticationOptions?.ProviderRootUrl)
.WithApiName(fileReRoute.AuthenticationOptions?.ApiName)
.WithRequireHttps(fileReRoute.AuthenticationOptions.RequireHttps)
.WithAllowedScopes(fileReRoute.AuthenticationOptions?.AllowedScopes)
.WithApiSecret(fileReRoute.AuthenticationOptions?.ApiSecret)
.Build();
}
.WithProvider(fileReRoute.AuthenticationOptions?.Provider)
.WithAllowedScopes(fileReRoute.AuthenticationOptions?.AllowedScopes)
.WithConfig(authenticationConfig)
.Build();
}
}
}

View File

@ -0,0 +1,35 @@
namespace Ocelot.Configuration.Creator
{
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.File;
public class ConfigCreator
{
public IAuthenticationConfig Create(FileAuthenticationOptions authenticationOptions)
{
if (authenticationOptions.Provider == "Jwt")
{
return CreateJwt(authenticationOptions);
}
return CreateIdentityServer(authenticationOptions);
}
private JwtConfig CreateJwt(FileAuthenticationOptions authenticationOptions)
{
return new JwtConfigBuilder()
.WithAudience(authenticationOptions.JwtConfig?.Audience)
.WithAuthority(authenticationOptions.JwtConfig?.Authority)
.Build();
}
private IdentityServerConfig CreateIdentityServer(FileAuthenticationOptions authenticationOptions)
{
return new IdentityServerConfigBuilder()
.WithApiName(authenticationOptions.IdentityServerConfig?.ApiName)
.WithApiSecret(authenticationOptions.IdentityServerConfig?.ApiSecret)
.WithProviderRootUrl(authenticationOptions.IdentityServerConfig?.ProviderRootUrl)
.WithRequireHttps(authenticationOptions.IdentityServerConfig.RequireHttps).Build();
}
}
}

View File

@ -6,14 +6,29 @@ namespace Ocelot.Configuration.File
{
public FileAuthenticationOptions()
{
AllowedScopes = new List<string>();
AllowedScopes = new List<string>();
IdentityServerConfig = new FileIdentityServerConfig();
JwtConfig = new FileJwtConfig();
}
public string Provider { get; set; }
public List<string> AllowedScopes { get; set; }
public FileIdentityServerConfig IdentityServerConfig { get; set; }
public FileJwtConfig JwtConfig { get; set; }
}
public class FileIdentityServerConfig
{
public string ProviderRootUrl { get; set; }
public string ApiName { get; set; }
public bool RequireHttps { get; set; }
public List<string> AllowedScopes { get; set; }
public string ApiSecret { get; set; }
}
public class FileJwtConfig
{
public string Authority { get; set; }
public string Audience { get; set; }
}
}

View File

@ -9,6 +9,8 @@ using Ocelot.ServiceDiscovery;
namespace Ocelot.Configuration.Repository
{
using Ocelot.AcceptanceTests;
public class ConsulOcelotConfigurationRepository : IOcelotConfigurationRepository
{
private readonly ConsulClient _consul;
@ -48,7 +50,9 @@ namespace Ocelot.Configuration.Repository
var json = Encoding.UTF8.GetString(bytes);
var consulConfig = JsonConvert.DeserializeObject<OcelotConfiguration>(json);
var settings = new JsonSerializerSettings();
settings.Converters.Add(new AuthenticationConfigConverter());
var consulConfig = JsonConvert.DeserializeObject<OcelotConfiguration>(json, settings);
return new OkResponse<IOcelotConfiguration>(consulConfig);
}

View File

@ -0,0 +1,59 @@
using System;
using Newtonsoft.Json;
using Ocelot.Configuration;
namespace Ocelot.AcceptanceTests
{
using Newtonsoft.Json.Linq;
public class AuthenticationConfigConverter : JsonConverter
{
public override bool CanWrite => false;
public override bool CanRead => true;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new InvalidOperationException("Use default serialization.");
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jsonObject = JObject.Load(reader);
var setting = default(IAuthenticationConfig);
if (jsonObject["Provider"] != null)
{
switch (jsonObject["Provider"].Value<string>())
{
case "Jwt":
setting = new JwtConfig(
jsonObject["Authority"].Value<string>(),
jsonObject["Audience"].Value<string>());
break;
default:
setting = new IdentityServerConfig(
jsonObject["ProviderRootUrl"].Value<string>(),
jsonObject["ApiName"].Value<string>(),
jsonObject["RequireHttps"].Value<bool>(),
jsonObject["ApiSecret"].Value<string>());
break;
}
}
else
{
setting = new IdentityServerConfig(string.Empty, string.Empty, false, string.Empty);
}
serializer.Populate(jsonObject.CreateReader(), setting);
return setting;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(IAuthenticationConfig);
}
}
}