Skip to content

Commit

Permalink
Modernize clients in basics (#193)
Browse files Browse the repository at this point in the history
Co-authored-by: Roland Guijt <[email protected]>
  • Loading branch information
RolandGuijt and Roland Guijt authored Jun 28, 2024
1 parent bd492b2 commit ad16b63
Show file tree
Hide file tree
Showing 24 changed files with 992 additions and 1,217 deletions.
82 changes: 53 additions & 29 deletions IdentityServer/v7/Basics/Apis/ResourceBasedApi/Program.cs
Original file line number Diff line number Diff line change
@@ -1,35 +1,59 @@
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Client;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using ResourceBasedApi;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;

namespace ResourceBasedApi
{
public class Program
Console.Title = "Resource based API";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code)
.CreateLogger();

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSerilog();
builder.Services.AddControllers();

builder.Services.AddCors();
builder.Services.AddDistributedMemoryCache();

builder.Services.AddAuthentication("token")
// JWT tokens
.AddJwtBearer("token", options =>
{
options.Authority = Urls.IdentityServer;
options.Audience = "resource2";
options.TokenValidationParameters.ValidTypes = new[] { "at+jwt" };
// if token does not contain a dot, it is a reference token
options.ForwardDefaultSelector = Selector.ForwardReferenceToken("introspection");
})

// reference tokens
.AddOAuth2Introspection("introspection", options =>
{
public static void Main(string[] args)
{
Console.Title = "Simple API with Resources";

BuildWebHost(args).Run();
}

public static IWebHost BuildWebHost(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Code)
.CreateLogger();

return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}
}
options.Authority = Urls.IdentityServer;
options.ClientId = "resource1";
options.ClientSecret = "secret";
});

var app = builder.Build();

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers().RequireAuthorization();

app.Run();

75 changes: 37 additions & 38 deletions IdentityServer/v7/Basics/Apis/ResourceBasedApi/Selector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,55 @@
using System.Linq;
using Microsoft.AspNetCore.Http;

namespace ResourceBasedApi
namespace ResourceBasedApi;

/// <summary>
/// Provides helper functions for forwarding logic
/// </summary>
public static class Selector
{
/// <summary>
/// Provides helper functions for forwarding logic
/// Provides a forwarding func for JWT vs reference tokens (based on existence of dot in token)
/// </summary>
public static class Selector
/// <param name="introspectionScheme">Scheme name of the introspection handler</param>
/// <returns></returns>
public static Func<HttpContext, string> ForwardReferenceToken(string introspectionScheme = "introspection")
{
/// <summary>
/// Provides a forwarding func for JWT vs reference tokens (based on existence of dot in token)
/// </summary>
/// <param name="introspectionScheme">Scheme name of the introspection handler</param>
/// <returns></returns>
public static Func<HttpContext, string> ForwardReferenceToken(string introspectionScheme = "introspection")
string Select(HttpContext context)
{
string Select(HttpContext context)
var (scheme, credential) = GetSchemeAndCredential(context);
if (scheme.Equals("Bearer", StringComparison.OrdinalIgnoreCase) &&
!credential.Contains("."))
{
var (scheme, credential) = GetSchemeAndCredential(context);
if (scheme.Equals("Bearer", StringComparison.OrdinalIgnoreCase) &&
!credential.Contains("."))
{
return introspectionScheme;
}

return null;
return introspectionScheme;
}

return Select;
return null;
}

/// <summary>
/// Extracts scheme and credential from Authorization header (if present)
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static (string, string) GetSchemeAndCredential(HttpContext context)
{
var header = context.Request.Headers["Authorization"].FirstOrDefault();

if (string.IsNullOrEmpty(header))
{
return ("", "");
}
return Select;
}

/// <summary>
/// Extracts scheme and credential from Authorization header (if present)
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static (string, string) GetSchemeAndCredential(HttpContext context)
{
var header = context.Request.Headers["Authorization"].FirstOrDefault();

var parts = header.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2)
{
return ("", "");
}
if (string.IsNullOrEmpty(header))
{
return ("", "");
}

return (parts[0], parts[1]);
var parts = header.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2)
{
return ("", "");
}

return (parts[0], parts[1]);
}
}
54 changes: 0 additions & 54 deletions IdentityServer/v7/Basics/Apis/ResourceBasedApi/Startup.cs

This file was deleted.

88 changes: 40 additions & 48 deletions IdentityServer/v7/Basics/ClientCredentials/src/Program.cs
Original file line number Diff line number Diff line change
@@ -1,56 +1,48 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Client;
using IdentityModel.Client;

namespace Client
Console.Title = "Console Client Credentials Flow";

var response = await RequestTokenAsync();
response.Show();

Console.ReadLine();
await CallServiceAsync(response.AccessToken);

static async Task<TokenResponse> RequestTokenAsync()
{
class Program
var client = new HttpClient();

var disco = await client.GetDiscoveryDocumentAsync(Urls.IdentityServer);
if (disco.IsError) throw new Exception(disco.Error);

var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
public static async Task Main()
{
Console.Title = "Console Client Credentials Flow";

var response = await RequestTokenAsync();
response.Show();

Console.ReadLine();
await CallServiceAsync(response.AccessToken);
}

static async Task<TokenResponse> RequestTokenAsync()
{
var client = new HttpClient();

var disco = await client.GetDiscoveryDocumentAsync(Urls.IdentityServer);
if (disco.IsError) throw new Exception(disco.Error);

var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,

ClientId = "client.credentials.sample",
ClientSecret = "secret",

Scope = "scope1"
});

if (response.IsError) throw new Exception(response.Error);
return response;
}

static async Task CallServiceAsync(string token)
{
var client = new HttpClient
{
BaseAddress = new Uri(Urls.SampleApi)
};

client.SetBearerToken(token);
var response = await client.GetStringAsync("identity");

"\n\nService claims:".ConsoleGreen();
Console.WriteLine(response.PrettyPrintJson());
}
}
Address = disco.TokenEndpoint,

ClientId = "client.credentials.sample",
ClientSecret = "secret",

Scope = "scope1"
});

if (response.IsError) throw new Exception(response.Error);
return response;
}

static async Task CallServiceAsync(string token)
{
var client = new HttpClient
{
BaseAddress = new Uri(Urls.SampleApi)
};

client.SetBearerToken(token);
var response = await client.GetStringAsync("identity");

"\n\nService claims:".ConsoleGreen();
Console.WriteLine(response.PrettyPrintJson());
}
Loading

0 comments on commit ad16b63

Please sign in to comment.