Skip to content

Commit

Permalink
Add example (#130)
Browse files Browse the repository at this point in the history
* Add example

* Funker for Cert sjekk også

---------

Co-authored-by: Jarle Børsheim <jarle.borsheim@sonat.no>
  • Loading branch information
exoen and jarleborsheim authored May 31, 2023
1 parent c61fe4c commit 1a5931a
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 27 deletions.
6 changes: 5 additions & 1 deletion ExampleApplication/ExampleApplication.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\KS.Fiks.Maskinporten.Client\KS.Fiks.Maskinporten.Client.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.30.1" />
</ItemGroup>

</Project>
94 changes: 69 additions & 25 deletions ExampleApplication/Program.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Ks.Fiks.Maskinporten.Client;
using Microsoft.IdentityModel.Tokens;

namespace ExampleApplication
{
Expand All @@ -16,48 +21,87 @@ namespace ExampleApplication
*/
public class Program
{
public static void Main(string[] args)
public static async Task Main(string[] args)
{
await CertExample();
await RsaExample();
}

private static async Task RsaExample()
{
// The issuer as defined in Maskinporten
var issuer = Environment.GetEnvironmentVariable("MASKINPORTEN_ISSUER");

// Content of PEM file containing public/private key with ----BEGIN.. and ----END removed, e.g., "MIIE...A=="
var pem = Environment.GetEnvironmentVariable("pem")!;
var rsa = RSA.Create();

//Will import both public and private part in same RSA, could be done in two different variables
rsa.ImportPkcs8PrivateKey(Convert.FromBase64String(pem), out _);

const string keyIdentifier = "23b3f45a-be84-43c4-a654-2182ff14dc40";
var configuration = MaskinportenClientConfigurationFactory.CreateVer2Configuration(
issuer,
privateKey: rsa,
publicKey: rsa,
keyIdentifier: keyIdentifier
);

var maskinportenClient = new MaskinportenClient(configuration);
var token = await maskinportenClient.GetAccessToken("ks:fiks");

await ValidateToken(token);
}

private static async Task CertExample()
{
// Relative or absolute path to the *.p12-file containing the test certificate
var p12Filename = Environment.GetEnvironmentVariable("P12FILENAME");

// Password required to use the certificate
var p12Password = Environment.GetEnvironmentVariable("P12PWD");

// The issuer as defined in Maskinporten
var issuer = Environment.GetEnvironmentVariable("MASKINPORTEN_ISSUER");

var cert = new X509Certificate2(p12Filename, p12Password);
var configuration = new MaskinportenClientConfiguration(
audience: @"https://ver2.maskinporten.no/", // ID-porten audience path
tokenEndpoint: @"https://ver2.maskinporten.no/token", // ID-porten token path
issuer: issuer, // Issuer name
numberOfSecondsLeftBeforeExpire: 10, // The token will be refreshed 10 seconds before it expires
certificate: cert);
@"https://ver2.maskinporten.no/", // ID-porten audience path
@"https://ver2.maskinporten.no/token", // ID-porten token path
issuer, // Issuer name
10, // The token will be refreshed 10 seconds before it expires
cert);
var maskinportenClient = new MaskinportenClient(configuration);

var tokenTask = maskinportenClient.GetAccessToken("ks:fiks").ContinueWith(t =>
{
var token = t.Result;
Console.Out.WriteLine($"Token (expiring: {token.IsExpiring()}): {token.Token}");
var token = await maskinportenClient.GetAccessToken("ks:fiks");
await ValidateToken(token);
}

return DecodeToken(token, cert);
});
// Do something with the token. In this case we only wait for it to be decoded and written to the console
tokenTask.GetAwaiter().GetResult();
private static async Task ValidateToken(MaskinportenToken token)
{
using var client = new HttpClient();
var json = await client.GetStringAsync("https://ver2.maskinporten.no/jwk");
var jwks = new JsonWebKeySet(json);
var jwk = jwks.Keys.First();

var validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "https://ver2.maskinporten.no/",
IssuerSigningKey = jwk
};

}
var handler = new JwtSecurityTokenHandler();
var claimsPrincipal = handler.ValidateToken(token.Token, validationParameters, out var validatedToken);

private static string DecodeToken(MaskinportenToken token, X509Certificate2 pubprivCertificate)
{
var serializer = new JsonNetSerializer();
var provider = new UtcDateTimeProvider();
var claims = claimsPrincipal.Claims;
foreach (var claim in claims) Console.WriteLine($"{claim.Type}: {claim.Value}");

var jwtDecoder = new JwtDecoder(serializer, new JwtValidator(serializer, provider), new JwtBase64UrlEncoder(), new RS256Algorithm(pubprivCertificate));
var decodedToken = jwtDecoder.Decode(token.Token);
Console.Out.WriteLine($"Decoded token {decodedToken}");
return decodedToken;
Console.WriteLine($"Token (expiring: {token.IsExpiring()}): {token.Token}");
Console.WriteLine($"Token valid until: {validatedToken.ValidTo}");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<RepositoryType>git</RepositoryType>
<PackageTags>FIKS</PackageTags>
<VersionPrefix>1.1.6</VersionPrefix>
<TargetFrameworks>net6.0;netcoreapp3.1;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public MaskinportenClientConfiguration(
throw new ArgumentException("Either certificate or private and public key must be set!");
}

if (certificate != null && (privateKey != null || publicKey != null))
{
throw new ArgumentException("Only certificate or public/private key must be set. Not both");
}

Audience = audience;
TokenEndpoint = tokenEndpoint;
Issuer = issuer;
Expand Down

0 comments on commit 1a5931a

Please sign in to comment.