-
Notifications
You must be signed in to change notification settings - Fork 275
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 #174 from DuendeSoftware/joe/scopes-resources
ScopesAndResources - Update to .NET 8
- Loading branch information
Showing
22 changed files
with
623 additions
and
558 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,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" | ||
}, | ||
} | ||
] | ||
} |
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,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" | ||
} | ||
] | ||
} |
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
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
100
IdentityServer/v7/ScopesAndResources/Client/TokenResponseExtensions.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,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(); | ||
} | ||
} |
Oops, something went wrong.