Skip to content

Commit

Permalink
Merge pull request #110 from sharpn/develop
Browse files Browse the repository at this point in the history
Adding JWT authentication for use with auth0
  • Loading branch information
TomPallister authored Jun 30, 2017
2 parents 0139452 + 1168eb3 commit 50ee9e2
Show file tree
Hide file tree
Showing 18 changed files with 916 additions and 612 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

namespace Ocelot.Authentication.Handler.Creator
{
using Ocelot.Configuration;

using AuthenticationOptions = Configuration.AuthenticationOptions;

/// <summary>
Expand All @@ -17,15 +19,31 @@ public Response<RequestDelegate> Create(IApplicationBuilder app, AuthenticationO
{
var builder = app.New();

builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
if (authOptions.Provider.ToLower() == "jwt")
{
var authenticationConfig = authOptions.Config as JwtConfig;

builder.UseJwtBearerAuthentication(
new JwtBearerOptions()
{
Authority = authenticationConfig.Authority,
Audience = authenticationConfig.Audience
});
}
else
{
Authority = authOptions.ProviderRootUrl,
ApiName = authOptions.ApiName,
RequireHttpsMetadata = authOptions.RequireHttps,
AllowedScopes = authOptions.AllowedScopes,
SupportedTokens = SupportedTokens.Both,
ApiSecret = authOptions.ApiSecret
});
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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
public enum SupportedAuthenticationProviders
{
IdentityServer
IdentityServer,
Jwt
}
}
38 changes: 33 additions & 5 deletions src/Ocelot/Configuration/AuthenticationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
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;
ApiName = apiName;
RequireHttps = requireHttps;
AllowedScopes = allowedScopes;
ApiSecret = apiSecret;
}

public string Provider { get; private set; }
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 {}
}
66 changes: 54 additions & 12 deletions src/Ocelot/Configuration/Builder/AuthenticationOptionsBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,93 @@ public class AuthenticationOptionsBuilder
{

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)
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, _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 AuthenticationOptionsBuilder WithApiName(string apiName)
public IdentityServerConfigBuilder WithApiName(string apiName)
{
_apiName = apiName;
return this;
}

public AuthenticationOptionsBuilder WithApiSecret(string apiSecret)
public IdentityServerConfigBuilder WithApiSecret(string apiSecret)
{
_apiSecret = apiSecret;
return this;
}

public AuthenticationOptionsBuilder WithRequireHttps(bool requireHttps)
public IdentityServerConfigBuilder WithRequireHttps(bool requireHttps)
{
_requireHttps = requireHttps;
return this;
}

public AuthenticationOptionsBuilder WithAllowedScopes(List<string> allowedScopes)
public IdentityServerConfig Build()
{
_allowedScopes = allowedScopes;
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 AuthenticationOptions Build()
public JwtConfigBuilder WithAudience(string audience)
{
_audience = audience;
return this;
}

public JwtConfig Build()
{
return new AuthenticationOptions(_provider, _providerRootUrl, _apiName, _requireHttps, _allowedScopes, _apiSecret);
return new JwtConfig(_authority, _audience);
}
}
}
15 changes: 7 additions & 8 deletions src/Ocelot/Configuration/Creator/AuthenticationOptionsCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ public class AuthenticationOptionsCreator : IAuthenticationOptionsCreator
{
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();
}
}
}
35 changes: 35 additions & 0 deletions src/Ocelot/Configuration/Creator/ConfigCreator.cs
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
19 changes: 17 additions & 2 deletions src/Ocelot/Configuration/File/FileAuthenticationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,29 @@ public class FileAuthenticationOptions
{
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; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace Ocelot.Configuration.Repository
{
using Ocelot.AcceptanceTests;

public class ConsulOcelotConfigurationRepository : IOcelotConfigurationRepository
{
private readonly ConsulClient _consul;
Expand Down Expand Up @@ -48,7 +50,9 @@ public async Task<Response<IOcelotConfiguration>> Get()

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);
}
Expand Down
59 changes: 59 additions & 0 deletions src/Ocelot/JsonConverters/AuthenticationConfigConverter.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}


}
Loading

0 comments on commit 50ee9e2

Please sign in to comment.