first commit
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
using System.Xml;
|
||||
using Xunit;
|
||||
using OnlineBankingAuth.Parsers;
|
||||
|
||||
namespace OnlineBankingAuth.Tests
|
||||
{
|
||||
public class AuthenticationParserTest
|
||||
{
|
||||
[Fact]
|
||||
public void AuthenticationParse()
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load("ExampleXML" + System.IO.Path.DirectorySeparatorChar + "DecryptedAssertion.xml");
|
||||
|
||||
XmlElement readAssertion = doc.DocumentElement;
|
||||
|
||||
var parser = new SAMLParser();
|
||||
var parsedAssertion = parser.ParseAssertion(readAssertion);
|
||||
|
||||
Assert.Equal("DI0019", parsedAssertion.FI_ID);
|
||||
Assert.Equal("123456", parsedAssertion.MemberID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Xunit;
|
||||
using Landmark.OLA.Application.Common.Security;
|
||||
|
||||
namespace OnlineBankingAuth.Tests
|
||||
{
|
||||
public class CookieCrytorTest
|
||||
{
|
||||
[Fact]
|
||||
public void EncryptAndDecrypt()
|
||||
{
|
||||
var sampleUnencryptedString = "This string will be encrypted and decrypted in this test";
|
||||
var secret = "A secret to serve as a key in our symmetric encryption";
|
||||
|
||||
var encrypted = CookieCryptor.EncryptJwt(sampleUnencryptedString, secret);
|
||||
Assert.NotEqual(sampleUnencryptedString, encrypted);
|
||||
|
||||
var decrypted = CookieCryptor.DecryptJwt(encrypted, secret);
|
||||
Assert.Equal(sampleUnencryptedString, decrypted);
|
||||
}
|
||||
}
|
||||
}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="ySyIzPto.pP5OtW0IIq9o3X_5V0" IssueInstant="2019-01-14T15:38:56.593Z" Version="2.0">
|
||||
<saml:Issuer>pfd.qal1.digitalinsight.com</saml:Issuer>
|
||||
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
||||
<ds:SignedInfo>
|
||||
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
|
||||
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></ds:SignatureMethod>
|
||||
<ds:Reference URI="#ySyIzPto.pP5OtW0IIq9o3X_5V0">
|
||||
<ds:Transforms>
|
||||
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
|
||||
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
|
||||
</ds:Transforms>
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod>
|
||||
<ds:DigestValue>IH1Nf8hwUP2FPf9ozez8Fsx9HEE5uBggOXuOISfvdgk=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
</ds:SignedInfo>
|
||||
<ds:SignatureValue>
|
||||
pCpwRldAMg3IUHyusRLznzFoEeHbGlYKyZl9vyi6hwL/z+afqN9kRUTgtQwnwnwk7mUZmhdInP4P
|
||||
MGUvKm2LFFu6BQ7iWHOqE93ZJ9gwbJbj+VnKsKxeepNcH/vDamTx/iTJ4lR3pKzISJTOvllND72s
|
||||
6LTvCpfTs6aAVv7qJDrJTkMUNOPVzy1YELy+T68GoZ25rJ1byNOSJkN9cdHgfqgI43p86eVYuKiK
|
||||
lTDXWpyxyfuV24AgDbUP8xy8f57DtlRvyThZ92iS5L5zA9DpY+w44DhPyOCm9TxMKOJO1KaDKbbb
|
||||
dCL+IKHuPaBoqY62FaV1HjGx6ZyEdu5rgcGhSQ==
|
||||
</ds:SignatureValue>
|
||||
<ds:KeyInfo>
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>
|
||||
MIIGejCCBWKgAwIBAgIQBuighc3hzI6Q8zikuBZQvzANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
|
||||
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5EaWdpQ2VydCBTSEEyIFNlY3Vy
|
||||
ZSBTZXJ2ZXIgQ0EwHhcNMTgwODE3MDAwMDAwWhcNMTkxMDE2MTIwMDAwWjCBszELMAkGA1UEBhMC
|
||||
VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExGTAXBgNVBAcTEFdlc3RsYWtlIFZpbGxhZ2UxJDAiBgNV
|
||||
BAoTG0RpZ2l0YWwgSW5zaWdodCBDb3Jwb3JhdGlvbjEjMCEGA1UECxMaUG93ZXJlZCBCeSBEaWdp
|
||||
dGFsIEluc2lnaHQxKTAnBgNVBAMTIHBmZC1zaWduLnFhbDEuZGlnaXRhbGluc2lnaHQuY29tMIIB
|
||||
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtff3NhEQw2GeTGoI97G28t7/plzLCBe9kBay
|
||||
q9knqD2OC0yOrfT65MGmHjq8PrGZGR7xIgeP282li+M71ITPjs+tny+njCBv53GdRW+5DqREteJS
|
||||
syUS5ydXZPcuHBCFS6g/lEvojsbOeeQoCMiMfS2qfC81HdVqpsiQiQMC5ksbGKAdFPHd1K/tx0OX
|
||||
IYsQRmUWU4GN6sSO8+uYfE/dyC4fYGd/0LSVkwYGZubTVK5e84plaNOYbC5rSHOiyAJTMvXaU8PP
|
||||
2oobp3vYDRxIsvj/vPZtzSJqSYahXSXK+qP3yOcNfx9BlWQagkkEg6sKRJfHFCR0JngnSojdwTOR
|
||||
TQIDAQABo4IC7TCCAukwHwYDVR0jBBgwFoAUD4BhHIIxYdUvKOeNRji0LOHG2eIwHQYDVR0OBBYE
|
||||
FM0cZ8MrIy+kauc6Fu+Y+jnSzLKhMCsGA1UdEQQkMCKCIHBmZC1zaWduLnFhbDEuZGlnaXRhbGlu
|
||||
c2lnaHQuY29tMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
|
||||
awYDVR0fBGQwYjAvoC2gK4YpaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nNi5j
|
||||
cmwwL6AtoCuGKWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zc2NhLXNoYTItZzYuY3JsMEwGA1Ud
|
||||
IARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNv
|
||||
bS9DUFMwCAYGZ4EMAQICMHwGCCsGAQUFBwEBBHAwbjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au
|
||||
ZGlnaWNlcnQuY29tMEYGCCsGAQUFBzAChjpodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln
|
||||
aUNlcnRTSEEyU2VjdXJlU2VydmVyQ0EuY3J0MAkGA1UdEwQCMAAwggEFBgorBgEEAdZ5AgQCBIH2
|
||||
BIHzAPEAdwC72d+8H4pxtZOUI5eqkntHOFeVCqtS6BqQlmQ2jh7RhQAAAWVFMDGaAAAEAwBIMEYC
|
||||
IQDkZdJn7l+5cuCvTc1IBhWbPGRnBlzlF0idM5vW+6hJ5QIhAILyNNA0R/CknRpy1C/gwBq0bTwx
|
||||
a8943O1cl0LqhMFeAHYAh3W/51l8+IxDmV+9827/Vo1HVjb/SrVgwbTq/16ggw8AAAFlRTAxfwAA
|
||||
BAMARzBFAiEAt0eDmAR+709rXPYcui9OMmMF25uzitbdRNaepZD2cfICIFLmOF+ZH6rFB/bke6Ql
|
||||
zX4Abq8lEfT845V/CAWnenXoMA0GCSqGSIb3DQEBCwUAA4IBAQB+wiMTrhyBaFalIeUlTAQaskMe
|
||||
CXCJ5N7ORozblg2Dz97Vs/CIOod2ucwKFhr/n7Fh+K5ch3huEh8pupqqI3TIMvS2fWHkKmZV1tWt
|
||||
b2X6B6aRW8bmkJea+Hc03hO7QruGw3kESSzfYO8OrgFd5Aww1+oTATmzsPnl19EZfbK2ustmeDS/
|
||||
0E1eENN5uAZDus4NqQZkWDlVcABtXcKXORzayiH4zU3Ghh59tYSZ6uzHnyDG7vA4QJENxdYHL8ed
|
||||
1qdODv6a7rJhPXSOwH7gNpINRTNe0SJQPgtgzQiBIgpR079+05vJjwqF2nXyVvZqI1YKPNQLjdKc
|
||||
coyQJC0B0qmB
|
||||
</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
<ds:KeyValue>
|
||||
<ds:RSAKeyValue>
|
||||
<ds:Modulus>
|
||||
tff3NhEQw2GeTGoI97G28t7/plzLCBe9kBayq9knqD2OC0yOrfT65MGmHjq8PrGZGR7xIgeP282l
|
||||
i+M71ITPjs+tny+njCBv53GdRW+5DqREteJSsyUS5ydXZPcuHBCFS6g/lEvojsbOeeQoCMiMfS2q
|
||||
fC81HdVqpsiQiQMC5ksbGKAdFPHd1K/tx0OXIYsQRmUWU4GN6sSO8+uYfE/dyC4fYGd/0LSVkwYG
|
||||
ZubTVK5e84plaNOYbC5rSHOiyAJTMvXaU8PP2oobp3vYDRxIsvj/vPZtzSJqSYahXSXK+qP3yOcN
|
||||
fx9BlWQagkkEg6sKRJfHFCR0JngnSojdwTORTQ==
|
||||
</ds:Modulus>
|
||||
<ds:Exponent>AQAB</ds:Exponent>
|
||||
</ds:RSAKeyValue>
|
||||
</ds:KeyValue>
|
||||
</ds:KeyInfo>
|
||||
</ds:Signature>
|
||||
<saml:Subject>
|
||||
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">tpvcerts1</saml:NameID>
|
||||
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
|
||||
<saml:SubjectConfirmationData NotOnOrAfter="2019-02-11T15:38:56.593Z" Recipient="https://loan-app-api-dvl.azurewebsites.net/api/SAMLAssertionConsumer"></saml:SubjectConfirmationData>
|
||||
</saml:SubjectConfirmation>
|
||||
</saml:Subject>
|
||||
<saml:Conditions NotBefore="2018-12-17T15:38:56.593Z" NotOnOrAfter="2019-02-11T15:38:56.593Z">
|
||||
<saml:AudienceRestriction>
|
||||
<saml:Audience>landmarkcu.digitalinsight.test</saml:Audience>
|
||||
</saml:AudienceRestriction>
|
||||
</saml:Conditions>
|
||||
<saml:AuthnStatement AuthnInstant="2019-01-14T15:38:56.592Z" SessionIndex="ySyIzPto.pP5OtW0IIq9o3X_5V0">
|
||||
<saml:AuthnContext>
|
||||
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
|
||||
</saml:AuthnContext>
|
||||
</saml:AuthnStatement>
|
||||
<saml:AttributeStatement>
|
||||
<saml:Attribute Name="MemberID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
|
||||
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">123456</saml:AttributeValue>
|
||||
</saml:Attribute>
|
||||
<saml:Attribute Name="FI_ID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
|
||||
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">DI0019</saml:AttributeValue>
|
||||
</saml:Attribute>
|
||||
<saml:Attribute Name="KEEP_ALIVE_URL" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
|
||||
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">https://www.iqa019.com/tob/live/usp-core/app/launch?code=ping</saml:AttributeValue>
|
||||
</saml:Attribute>
|
||||
</saml:AttributeStatement>
|
||||
</saml:Assertion>
|
||||
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.10.1" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
|
||||
<PackageReference Include="XmlUnit.Core" Version="2.11.1" />
|
||||
<PackageReference Include="xunit" Version="2.3.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
|
||||
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Landmark.OLA.Application\Landmark.OLA.Application.csproj" />
|
||||
<ProjectReference Include="..\OnlineBankingAuth\OnlineBankingAuth.csproj" />
|
||||
<ProjectReference Include="..\Landmark.OLA.Models\Landmark.OLA.Models.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="ExampleXML\DecryptedAssertion.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,113 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using OnlineBankingAuth.Configuration;
|
||||
using OnlineBankingAuth.Tokens;
|
||||
using Landmark.OLA.Application.Common.Security;
|
||||
using Landmark.OLA.Models.OnlineBanking;
|
||||
|
||||
namespace OnlineBankingAuth.Tests
|
||||
{
|
||||
public class TokenServiceTest
|
||||
{
|
||||
public static SecuritySettings _settings = new SecuritySettings
|
||||
{
|
||||
TokenSecret = "Some fake secret for crypt"
|
||||
};
|
||||
|
||||
//public static IOptions<SecuritySettings> _options = IOptions<SecuritySettings>(_settings);
|
||||
public static IOptions<SecuritySettings> _options = Options.Create<SecuritySettings>(_settings);
|
||||
|
||||
TokenService _tokenService = new TokenService(_options);
|
||||
|
||||
[Fact]
|
||||
public void ShouldGenerateTokenAndRetrieveTokenFromCookie()
|
||||
{
|
||||
var assertion = new DISAMLAssertion
|
||||
{
|
||||
MemberID = "123456",
|
||||
FI_ID = "7890"
|
||||
};
|
||||
var obToken = new OnlineBankingToken(assertion, null, false);
|
||||
var token = _tokenService.CreateOnlineBankingJWT(obToken);
|
||||
|
||||
var cookies = new Dictionary<string, string>
|
||||
{
|
||||
{ Constants.TokenPayload, token },
|
||||
{ Constants.TokenAuthorization, "Role=" + Constants.TokenAuthorizationString }
|
||||
};
|
||||
|
||||
var cookieMock = new Mock<IRequestCookieCollection>();
|
||||
cookieMock.Setup(c => c[It.IsAny<string>()])
|
||||
.Returns((string key) => cookies.TryGetValue(key, out var v) ? v : null);
|
||||
cookieMock.Setup(c => c.ContainsKey(It.IsAny<string>()))
|
||||
.Returns((string key) => cookies.ContainsKey(key));
|
||||
cookieMock.Setup(c => c.TryGetValue(It.IsAny<string>(), out It.Ref<string>.IsAny))
|
||||
.Returns((string key, out string value) =>
|
||||
{
|
||||
var ok = cookies.TryGetValue(key, out var v);
|
||||
value = v;
|
||||
return ok;
|
||||
});
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
context.Request.Cookies = cookieMock.Object;
|
||||
|
||||
var retrievedAssertion = _tokenService.GetAuthenticatedDataFromCookie(context);
|
||||
|
||||
Assert.Equal(assertion.FI_ID, retrievedAssertion.FI_ID);
|
||||
Assert.Equal(assertion.MemberID, retrievedAssertion.MemberID);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldRenewCookie()
|
||||
{
|
||||
var assertion = new DISAMLAssertion
|
||||
{
|
||||
MemberID = "123456",
|
||||
FI_ID = "7890"
|
||||
};
|
||||
|
||||
var obToken = new OnlineBankingToken(assertion, null, false);
|
||||
var token = _tokenService.CreateOnlineBankingJWT(obToken);
|
||||
|
||||
var cookies = new Dictionary<string, string>
|
||||
{
|
||||
{ Constants.TokenPayload, token },
|
||||
{ Constants.TokenAuthorization, "Role=" + Constants.TokenAuthorizationString }
|
||||
};
|
||||
|
||||
var cookieMock = new Mock<IRequestCookieCollection>();
|
||||
cookieMock.Setup(c => c[It.IsAny<string>()])
|
||||
.Returns((string key) => cookies.TryGetValue(key, out var v) ? v : null);
|
||||
cookieMock.Setup(c => c.ContainsKey(It.IsAny<string>()))
|
||||
.Returns((string key) => cookies.ContainsKey(key));
|
||||
cookieMock.Setup(c => c.TryGetValue(It.IsAny<string>(), out It.Ref<string>.IsAny))
|
||||
.Returns((string key, out string value) =>
|
||||
{
|
||||
var ok = cookies.TryGetValue(key, out var v);
|
||||
value = v;
|
||||
return ok;
|
||||
});
|
||||
|
||||
var context = new DefaultHttpContext();
|
||||
context.Request.Cookies = cookieMock.Object;
|
||||
|
||||
var renewedSession = _tokenService.RenewOnlineBankingJWT(context);
|
||||
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
|
||||
var firstEncryptedToken = CookieCryptor.DecryptJwt(token[Constants.TokenPrefix.Length..], _settings.TokenSecret);
|
||||
var firstToken = tokenHandler.ReadJwtToken(firstEncryptedToken);
|
||||
|
||||
var secondEncryptedToken = CookieCryptor.DecryptJwt(renewedSession[Constants.TokenPrefix.Length..], _settings.TokenSecret);
|
||||
var secondToken = tokenHandler.ReadJwtToken(secondEncryptedToken);
|
||||
|
||||
Assert.Equal(firstToken.Payload[Constants.MemberID], secondToken.Payload[Constants.MemberID]);
|
||||
Assert.Equal(firstToken.Payload[Constants.FI_ID], secondToken.Payload[Constants.FI_ID]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- additional settings used during the dotnet test execution step in the azure dev ops pipeline -->
|
||||
|
||||
<RunSettings>
|
||||
|
||||
<DataCollectionRunSettings>
|
||||
<DataCollectors>
|
||||
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<Configuration>
|
||||
<CodeCoverage>
|
||||
|
||||
|
||||
<CompanyNames>
|
||||
<Exclude>
|
||||
<CompanyName>.*microsoft.*</CompanyName>
|
||||
</Exclude>
|
||||
</CompanyNames>
|
||||
|
||||
</CodeCoverage>
|
||||
</Configuration>
|
||||
</DataCollector>
|
||||
|
||||
</DataCollectors>
|
||||
</DataCollectionRunSettings>
|
||||
|
||||
</RunSettings>
|
||||
Reference in New Issue
Block a user