Skip to content

Commit

Permalink
Merge pull request #174 from DuendeSoftware/joe/scopes-resources
Browse files Browse the repository at this point in the history
ScopesAndResources - Update to .NET 8
  • Loading branch information
brockallen authored Jan 25, 2024
2 parents baf3c69 + 2f4eebf commit 278af46
Show file tree
Hide file tree
Showing 22 changed files with 623 additions and 558 deletions.
40 changes: 40 additions & 0 deletions IdentityServer/v7/ScopesAndResources/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"version": "0.2.0",
"compounds": [
{
"name": "Run All",
"configurations": ["IdentityServerHost", "Client"],
"presentation": {
"group": "10-compunds",
}
}
],
"configurations": [
{
"name": "IdentityServerHost",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build-identityserverhost",
"program": "${workspaceFolder}/IdentityServerHost/bin/Debug/net8.0/IdentityServerHost.dll",
"args": [],
"cwd": "${workspaceFolder}/IdentityServerHost",
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"console": "externalTerminal",
},
{
"name": "Client",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build-client",
"program": "${workspaceFolder}/Client/bin/Debug/net8.0/Client.dll",
"args": [],
"cwd": "${workspaceFolder}/Client",
"console": "externalTerminal",
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
}
]
}
41 changes: 41 additions & 0 deletions IdentityServer/v7/ScopesAndResources/.vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "process",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}/PAT.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "build-identityserverhost",
"type": "process",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}/IdentityServerHost",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "build-client",
"type": "process",
"command": "dotnet",
"args": [
"build",
"${workspaceFolder}/Client",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="IdentityModel" Version="5.2.0" />
<PackageReference Include="IdentityModel" Version="6.2.0" />
</ItemGroup>
</Project>
177 changes: 177 additions & 0 deletions IdentityServer/v7/ScopesAndResources/Client/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IdentityModel.Client;

namespace Client;

class Program
{
private static DiscoveryCache Cache;

static async Task Main(string[] args)
{
Console.Title = "Console Resources and Scopes Client";
Cache = new DiscoveryCache("https://localhost:5001");

var leave = false;

while (leave == false)
{
Console.Clear();

"Resource setup:\n".ConsoleGreen();

"resource1: resource1.scope1 resource1.scope2 shared.scope".ConsoleGreen();
"resource2: resource2.scope1 resource2.scope2 shared.scope\n".ConsoleGreen();
"resource3 (isolated): resource3.scope1 resource3.scope2 shared.scope\n".ConsoleGreen();
"scopes without resource association: scope3 scope4 transaction\n\n".ConsoleGreen();


// scopes without associated resource
"a) scope3 scope4".ConsoleYellow();

// one scope, single resource
"b) resource1.scope1".ConsoleYellow();

// two scopes, single resources
"c) resource1.scope1 resource1.scope2".ConsoleYellow();

// two scopes, one has a resource, one doesn't
"d) resource1.scope1 scope3".ConsoleYellow();

// two scopes, two resource
"e) resource1.scope1 resource2.scope1".ConsoleYellow();

// shared scope between two resources
"f) shared.scope".ConsoleYellow();

// shared scope between two resources and scope that belongs to resource
"g) resource1.scope1 shared.scope".ConsoleYellow();

// parameterized scope
"h) transaction:123".ConsoleYellow();

// no scope
"i) no scope".ConsoleYellow();

// no scope
"j) no scope (resource: resource1)".ConsoleYellow();

// no scope
"k) no scope (resource: resource3)".ConsoleYellow();

// isolated scope without resource parameter
"l) resource3.scope1".ConsoleYellow();

// isolated scope without resource parameter
"m) resource3.scope1 (resource: resource3)".ConsoleYellow();

// isolated scope without resource parameter
"n) resource3.scope1 (resource: resource2)".ConsoleYellow();

"\nx) quit".ConsoleYellow();

var input = Console.ReadKey();

switch (input.Key)
{
case ConsoleKey.A:
await RequestToken("scope3 scope4");
break;

case ConsoleKey.B:
await RequestToken("resource1.scope1");
break;

case ConsoleKey.C:
await RequestToken("resource1.scope1 resource1.scope2");
break;

case ConsoleKey.D:
await RequestToken("resource1.scope1 scope3");
break;

case ConsoleKey.E:
await RequestToken("resource1.scope1 resource2.scope1");
break;

case ConsoleKey.F:
await RequestToken("shared.scope");
break;

case ConsoleKey.G:
await RequestToken("resource1.scope1 shared.scope");
break;

case ConsoleKey.H:
await RequestToken("transaction:123");
break;

case ConsoleKey.I:
await RequestToken("");
break;

case ConsoleKey.J:
await RequestToken("", "urn:resource1");
break;

case ConsoleKey.K:
await RequestToken("", "urn:resource3");
break;

case ConsoleKey.L:
await RequestToken("resource3.scope1");
break;

case ConsoleKey.M:
await RequestToken("resource3.scope1", "urn:resource3");
break;

case ConsoleKey.N:
await RequestToken("resource3.scope1", "urn:resource2");
break;

case ConsoleKey.X:
leave = true;
break;
}
}
}

static async Task RequestToken(string scope, string resource = null)
{
var client = new HttpClient();
var disco = await Cache.GetAsync();

var request = new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "resources.and.scopes",
ClientSecret = "secret",

Scope = scope
};

if (!string.IsNullOrEmpty(resource))
{
request.Resource.Add(resource);
}

var response = await client.RequestClientCredentialsTokenAsync(request);

if (response.IsError)
{
Console.WriteLine();
Console.WriteLine(response.Error);
Console.ReadLine();
return;
}

Console.WriteLine();
Console.WriteLine();

response.Show();
Console.ReadLine();
}
}
100 changes: 100 additions & 0 deletions IdentityServer/v7/ScopesAndResources/Client/TokenResponseExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using IdentityModel;
using IdentityModel.Client;
using System;
using System.Diagnostics;
using System.Text;
using System.Text.Json;

namespace Client;

public static class TokenResponseExtensions
{
public static void Show(this TokenResponse response)
{
if (!response.IsError)
{
"Token response:".ConsoleGreen();
Console.WriteLine(response.Json);

if (response.AccessToken.Contains("."))
{
"\nAccess Token (decoded):".ConsoleGreen();

var parts = response.AccessToken.Split('.');
var header = parts[0];
var claims = parts[1];

Console.WriteLine(PrettyPrintJson(Encoding.UTF8.GetString(Base64Url.Decode(header))));
Console.WriteLine(PrettyPrintJson(Encoding.UTF8.GetString(Base64Url.Decode(claims))));
}
}
else
{
if (response.ErrorType == ResponseErrorType.Http)
{
"HTTP error: ".ConsoleGreen();
Console.WriteLine(response.Error);
"HTTP status code: ".ConsoleGreen();
Console.WriteLine(response.HttpStatusCode);
}
else
{
"Protocol error response:".ConsoleGreen();
Console.WriteLine(response.Raw);
}
}
}

public static string PrettyPrintJson(this string raw)
{
var doc = JsonDocument.Parse(raw).RootElement;
return JsonSerializer.Serialize(doc, new JsonSerializerOptions { WriteIndented = true });
}
}


public static class ConsoleExtensions
{
/// <summary>
/// Writes green text to the console.
/// </summary>
/// <param name="text">The text.</param>
[DebuggerStepThrough]
public static void ConsoleGreen(this string text)
{
text.ColoredWriteLine(ConsoleColor.Green);
}

/// <summary>
/// Writes red text to the console.
/// </summary>
/// <param name="text">The text.</param>
[DebuggerStepThrough]
public static void ConsoleRed(this string text)
{
text.ColoredWriteLine(ConsoleColor.Red);
}

/// <summary>
/// Writes yellow text to the console.
/// </summary>
/// <param name="text">The text.</param>
[DebuggerStepThrough]
public static void ConsoleYellow(this string text)
{
text.ColoredWriteLine(ConsoleColor.Yellow);
}

/// <summary>
/// Writes out text with the specified ConsoleColor.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="color">The color.</param>
[DebuggerStepThrough]
public static void ColoredWriteLine(this string text, ConsoleColor color)
{
Console.ForegroundColor = color;
Console.WriteLine(text);
Console.ResetColor();
}
}
Loading

0 comments on commit 278af46

Please sign in to comment.