Skip to content

Commit

Permalink
Merge pull request #9 from lreb/okta
Browse files Browse the repository at this point in the history
Okta and JWT self generated
  • Loading branch information
lreb authored Sep 19, 2020
2 parents d83d4f8 + 24549f3 commit 21397a1
Show file tree
Hide file tree
Showing 19 changed files with 474 additions and 3 deletions.
2 changes: 2 additions & 0 deletions FacwareBase.API/Controllers/AlbumController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using FacwareBase.API.Helpers.Domain.POCO;
using FacwareBase.API.Helpers.OData;
using Microsoft.AspNet.OData;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
Expand All @@ -12,6 +13,7 @@ namespace FacwareBase.API.Controllers
/// <summary>
/// Demo Controller with OData feature
/// </summary>
[Authorize]
public class AlbumController : ODataController
{
private readonly ILogger<AlbumController> _logger;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using FacwareBase.API.Helpers.Domain.POCO;
using FacwareBase.API.Helpers.Jwt;
using Microsoft.AspNetCore.Mvc;

namespace FacwareBase.API.Controllers.Authentication
{
/// <summary>
/// Provides authentication feature JWT
/// </summary>
[Route("api/[controller]")]
public class AuthenticationController: ControllerBase
{
private readonly IJwtUtility _jwtUtility;
public AuthenticationController(IJwtUtility jwtUtility)
{
_jwtUtility = jwtUtility;
}

/// <summary>
/// Create session
/// </summary>
/// <param name="user">User <see cref="User"/></param>
/// <returns>JWT data</returns>
[HttpPost]
public async Task<IActionResult> Create([FromBody]User user)
{
IList<string> roles = new List<string>(){"Administrator","DemoRole"};

var token = await _jwtUtility.GenerateJwt(user, roles);
return Ok(new
{
User = new {
Token = token,
Name = user.Name,
Email = user.Email
}
});
}
}
}
42 changes: 42 additions & 0 deletions FacwareBase.API/Extensions/Authentication/JwtExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using FacwareBase.API.Helpers.Jwt;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

namespace FacwareBase.API.Extensions.Authentication
{
/// <summary>
/// Utility to JWT
/// </summary>
public static class JwtExtension
{
/// <summary>
/// app setting for okta
/// </summary>
public static readonly string JwtOptionsSection = "Okta";
/// <summary>
/// enables okata service
/// </summary>
/// <param name="services">application service <see cref="IServiceCollection"/></param>
/// <param name="configuration">application configuratio <see cref="IConfiguration"/></param>
public static void ConfigureJwt(this IServiceCollection services, IConfiguration configuration)
{
var jwt = configuration.GetSection(JwtOptions.JwtOptionsSection).Get<JwtOptions>();

services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwt.Secret)),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
}
}
42 changes: 42 additions & 0 deletions FacwareBase.API/Extensions/Authentication/OktaExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Okta.AspNetCore;
using FacwareBase.API.Helpers.Okta;
using System;

namespace FacwareBase.Api.Extensions
{
/// <summary>
/// enables okata service
/// </summary>
public static class OktaExtension
{
/// <summary>
/// app setting for okta
/// </summary>
public static readonly string OktaConfiguartion = "Okta";
/// <summary>
/// enables okata service
/// </summary>
/// <param name="services">application service <see cref="IServiceCollection"/></param>
/// <param name="configuration">application configuratio <see cref="IConfiguration"/></param>
public static void ConfigureOkta(this IServiceCollection services, IConfiguration configuration)
{
var okta = configuration.GetSection(OktaConfiguartion).Get<OktaHelper>();

services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultChallengeScheme = OktaDefaults.ApiAuthenticationScheme;
options.DefaultSignInScheme = OktaDefaults.ApiAuthenticationScheme;
})
.AddCookie()
.AddJwtBearer(options =>
{
options.Authority = okta.Authority;
options.Audience = okta.Audience;
options.RequireHttpsMetadata = Convert.ToBoolean(okta.RequireHttpsMetadata);
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using FacwareBase.API.Helpers.Jwt;
using Microsoft.Extensions.DependencyInjection;

namespace FacwareBase.API.Extensions.DependencyInyection
{
/// <summary>
/// register all dependencies
/// </summary>
public static class DependencyInyectionExtension
{
/// <summary>
/// Configure all dependecy inyection
/// </summary>
/// <param name="services">Application services<see cref="IServiceCollection"/></param>
public static void DependencyInyectionConfiguration(this IServiceCollection services)
{
services.AddScoped<IJwtUtility,JwtUtility>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public Task<HealthCheckResult> CheckHealthAsync(
Dictionary<string, object> data = new Dictionary<string, object>();
data["environment"] = _config["HealthChecks:Environment"];
data["corsAllowedOrigin"] = _config.GetSection("Cors:AllowedOrigin").Get<string[]>();
data["authenticationMode"] = _config["Authentication:AuthenticationMode"];
// data["connection"] = _config["ConnectionStrings:ApplicationConfigurationConnectionString"];
return Task.FromResult(
HealthCheckResult.Healthy("Test health check data", data));
Expand Down
3 changes: 3 additions & 0 deletions FacwareBase.API/FacwareBase.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.1.1" />
<PackageReference Include="AWSSDK.Core" Version="3.5.1.10" />
<PackageReference Include="EntityFramework6.Npgsql" Version="6.4.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.8" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.8" />
<PackageReference Include="Microsoft.AspNetCore.OData" Version="7.4.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.1.8" />
Expand All @@ -20,12 +21,14 @@
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
<PackageReference Include="Okta.AspNetCore" Version="3.3.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
<PackageReference Include="Serilog.Sinks.AwsCloudWatch" Version="4.0.161" />
<PackageReference Include="Serilog.Sinks.ColoredConsole" Version="3.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="5.5.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.7.1" />
</ItemGroup>

</Project>
32 changes: 32 additions & 0 deletions FacwareBase.API/Helpers/Authentication/AuthenticationOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace FacwareBase.API.Helpers.Authentication
{
/// <summary>
/// Authentication configurations
/// </summary>
public class AuthenticationOptions
{
/// <summary>
/// Section in app settings
/// </summary>
public const string AuthenticationOptionsSection = "Authentication";
/// <summary>
/// Mode value in basis to AuthenticationModes <see cref="AuthenticationModes"/>
/// </summary>
/// <value></value>
public string AuthenticationMode { get; set; }
}
/// <summary>
/// Authentication modes
/// </summary>
public static class AuthenticationModes
{
/// <summary>
/// Okta mode
/// </summary>
public const string Okta = "Okta";
/// <summary>
/// Bearer JWT
/// </summary>
public const string Jwt = "Jwt";
}
}
13 changes: 13 additions & 0 deletions FacwareBase.API/Helpers/Domain/POCO/User.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace FacwareBase.API.Helpers.Domain.POCO
{
/// <summary>
/// demo user model
/// </summary>
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
}
20 changes: 20 additions & 0 deletions FacwareBase.API/Helpers/Jwt/IJwtUtility.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using FacwareBase.API.Helpers.Domain.POCO;

namespace FacwareBase.API.Helpers.Jwt
{
/// <summary>
/// JWT tools
/// </summary>
public interface IJwtUtility
{
/// <summary>
/// Generates JWT token
/// </summary>
/// <param name="user">System user entity<see cref="User"/></param>
/// <param name="roles">role asseigned to user, string list<see cref="string"/></param>
/// <returns></returns>
Task<string> GenerateJwt(User user, IList<string> roles);
}
}
29 changes: 29 additions & 0 deletions FacwareBase.API/Helpers/Jwt/JwtOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
namespace FacwareBase.API.Helpers.Jwt
{
/// <summary>
/// Defines JWT configure strongly typed settings objects
/// </summary>
public class JwtOptions
{
/// <summary>
/// Section in app settings json file
/// </summary>
public const string JwtOptionsSection = "Jwt";
/// <summary>
/// Domain that generates jwt
/// </summary>
public string Issuer { get; set; }
/// <summary>
/// Secret private key to encode and decode JWT
/// </summary>
public string Secret { get; set; }
/// <summary>
/// Expitation in days
/// </summary>
public int ExpirationInDays { get; set; }
/// <summary>
/// Expiration in hours
/// </summary>
public int ExpirationInHours { get; set; }
}
}
69 changes: 69 additions & 0 deletions FacwareBase.API/Helpers/Jwt/JwtUtility.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using FacwareBase.API.Helpers.Domain.POCO;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;

namespace FacwareBase.API.Helpers.Jwt
{
public class JwtUtility : IJwtUtility
{
private readonly JwtOptions _jwtSettingsOptions;

/// <summary>
/// Constructor
/// </summary>
/// <param name="jwtSettingsOptions">App settings from appsettings.json<see cref="JwtOptions"/></param>
public JwtUtility
(
IOptions<JwtOptions> jwtSettingsOptions
)
{
_jwtSettingsOptions = jwtSettingsOptions.Value;
}

/// <summary>
/// generates jwt token with user data
/// </summary>
/// <param name="user">User information<see cref="User"/></param>
/// <param name="roles">Role information<see cref="string"/></param>
/// <returns></returns>
public async Task<string> GenerateJwt(User user, IList<string> roles)
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Name),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())
};

var roleClaims = roles.Select(r => new Claim(ClaimTypes.Role, r));

claims.AddRange(roleClaims);

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettingsOptions.Secret));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
// set expiration in hours
// var expires = DateTime.Now.AddDays(Convert.ToDouble(jwtSettings.ExpirationInDays));
// set expiration in hours
var expires = DateTime.Now.AddHours(Convert.ToDouble(_jwtSettingsOptions.ExpirationInHours));

var token = new JwtSecurityToken(
issuer: _jwtSettingsOptions.Issuer,
audience: _jwtSettingsOptions.Issuer,
claims,
expires : expires,
signingCredentials : creds
);

return new JwtSecurityTokenHandler().WriteToken(token);
}
}
}
20 changes: 20 additions & 0 deletions FacwareBase.API/Helpers/Okta/Okta.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace FacwareBase.API.Helpers.Okta
{
/// <summary>
/// Okta helper
/// </summary>
public class OktaHelper
{
/// <summary>
/// origin autority
/// </summary>
/// <code>https://{replace-with-okta-domain}.okta.com/oauth2/default</code>
public string Authority { get; set; }
/// <summary>
/// allowed audience
/// </summary>
/// <code>api://default</code>
public string Audience { get; set; }
public string RequireHttpsMetadata { get; set; }
}
}
Loading

0 comments on commit 21397a1

Please sign in to comment.