-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from dof-dss/JwtAuthentication
Added jwt authentication
- Loading branch information
Showing
8 changed files
with
356 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System; | ||
|
||
namespace de_institutions_api_core.Entities | ||
{ | ||
public class ConsumingApplication | ||
{ | ||
public int Id { get; set; } | ||
public string ApplicationName { get; set; } | ||
public string ApplicationDescription { get; set; } | ||
public string ApiKey { get; set; } | ||
public string SecretKey { get; set; } | ||
public DateTime DateEntered { get; set; } | ||
public bool IsDisabled { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
using de_institutions_api_core.Entities; | ||
using de_institutions_infrastructure.Data; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.IdentityModel.Tokens; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IdentityModel.Tokens.Jwt; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace de_institutions_api.Authentication | ||
{ | ||
public class JwtHelpers | ||
{ | ||
private readonly IServiceScopeFactory _serviceScopeFactory; | ||
|
||
private const double ISSUED_WITHIN_SECONDS = 30; | ||
|
||
public JwtHelpers(IServiceScopeFactory serviceScopeFactory) | ||
{ | ||
_serviceScopeFactory = serviceScopeFactory; | ||
} | ||
|
||
public IEnumerable<SecurityKey> ResolveSigningKey(string token, SecurityToken securityToken, string kid, TokenValidationParameters validationParameters) | ||
{ | ||
var signingKey = new List<SecurityKey>(); | ||
|
||
var jwtToken = securityToken as JwtSecurityToken; | ||
|
||
var kidFromJwt = ""; | ||
|
||
if (jwtToken.Payload.ContainsKey("kid")) | ||
kidFromJwt = jwtToken.Payload["kid"].ToString(); | ||
|
||
if (string.IsNullOrEmpty(kidFromJwt)) return signingKey; | ||
|
||
var secretKey = GetSigningKeyFromDatabase(kidFromJwt); | ||
|
||
if (string.IsNullOrEmpty(secretKey)) return signingKey; | ||
|
||
signingKey.Add(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey))); | ||
|
||
return signingKey; | ||
} | ||
|
||
public bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) | ||
{ | ||
var jwtToken = securityToken as JwtSecurityToken; | ||
|
||
return IssuedWithin(jwtToken); | ||
} | ||
|
||
private static bool IssuedWithin(JwtSecurityToken jwtToken) | ||
{ | ||
var iatValid = false; | ||
|
||
if (jwtToken.Payload.ContainsKey("iat")) | ||
{ | ||
var issuedString = jwtToken.Payload["iat"].ToString(); | ||
|
||
var dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(long.Parse(issuedString)); | ||
|
||
var issuedDate = dateTimeOffset.DateTime; | ||
|
||
var diff = DateTime.UtcNow.Subtract(issuedDate); | ||
|
||
if (diff.TotalSeconds < ISSUED_WITHIN_SECONDS) iatValid = true; | ||
} | ||
|
||
return iatValid; | ||
} | ||
|
||
private string GetSigningKeyFromDatabase(string kidFromJwt) | ||
{ | ||
ConsumingApplication consumingApplication = null; | ||
|
||
using (var scope = _serviceScopeFactory.CreateScope()) | ||
{ | ||
var dbContext = scope.ServiceProvider.GetService<InstituitonContext>(); | ||
|
||
consumingApplication = dbContext.ConsumingApplication.FirstOrDefault(x => x.ApiKey == kidFromJwt && !x.IsDisabled); | ||
} | ||
|
||
if (consumingApplication != null && consumingApplication.SecretKey != null) | ||
{ | ||
return consumingApplication.SecretKey; | ||
} | ||
else return ""; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
de-institutions-infrastructure/Migrations/20210914133911_AddConsumingAppTable.Designer.cs
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
36 changes: 36 additions & 0 deletions
36
de-institutions-infrastructure/Migrations/20210914133911_AddConsumingAppTable.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
using Microsoft.EntityFrameworkCore.Metadata; | ||
using Microsoft.EntityFrameworkCore.Migrations; | ||
using System; | ||
|
||
namespace de_institutions_infrastructure.Migrations | ||
{ | ||
public partial class AddConsumingAppTable : Migration | ||
{ | ||
protected override void Up(MigrationBuilder migrationBuilder) | ||
{ | ||
migrationBuilder.CreateTable( | ||
name: "ConsumingApplication", | ||
columns: table => new | ||
{ | ||
Id = table.Column<int>(nullable: false) | ||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), | ||
ApplicationName = table.Column<string>(nullable: true), | ||
ApplicationDescription = table.Column<string>(nullable: true), | ||
ApiKey = table.Column<string>(nullable: true), | ||
SecretKey = table.Column<string>(nullable: true), | ||
DateEntered = table.Column<DateTime>(nullable: false), | ||
IsDisabled = table.Column<bool>(nullable: false) | ||
}, | ||
constraints: table => | ||
{ | ||
table.PrimaryKey("PK_ConsumingApplication", x => x.Id); | ||
}); | ||
} | ||
|
||
protected override void Down(MigrationBuilder migrationBuilder) | ||
{ | ||
migrationBuilder.DropTable( | ||
name: "ConsumingApplication"); | ||
} | ||
} | ||
} |
Oops, something went wrong.