diff --git a/Security/src/AuthApi/Program.cs b/Security/src/AuthApi/Program.cs index ccc3c9c7a..3617b0f72 100644 --- a/Security/src/AuthApi/Program.cs +++ b/Security/src/AuthApi/Program.cs @@ -1,4 +1,3 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; using Steeltoe.Common.Certificates; using Steeltoe.Configuration.CloudFoundry; using Steeltoe.Configuration.CloudFoundry.ServiceBindings; @@ -27,7 +26,7 @@ builder.Configuration.AddAppInstanceIdentityCertificate(new Guid(orgId), new Guid(spaceId)); // Steeltoe: Register Microsoft's JWT Bearer and Certificate libraries for authentication, configure JWT to work with UAA/Cloud Foundry. -builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer().ConfigureJwtBearerForCloudFoundry().AddCertificate(); +builder.Services.AddAuthentication().AddJwtBearer().ConfigureJwtBearerForCloudFoundry().AddCertificate(); // Steeltoe: Register Microsoft authorization services. builder.Services.AddAuthorizationBuilder() diff --git a/Security/src/AuthApi/Steeltoe.Samples.AuthApi.csproj b/Security/src/AuthApi/Steeltoe.Samples.AuthApi.csproj index 5cab4fdf5..c6ff1da5c 100644 --- a/Security/src/AuthApi/Steeltoe.Samples.AuthApi.csproj +++ b/Security/src/AuthApi/Steeltoe.Samples.AuthApi.csproj @@ -2,8 +2,8 @@ net8.0 - enable enable + enable diff --git a/Security/src/AuthApi/manifest-windows.yml b/Security/src/AuthApi/manifest-windows.yml index bbade4271..cf75d8b83 100644 --- a/Security/src/AuthApi/manifest-windows.yml +++ b/Security/src/AuthApi/manifest-windows.yml @@ -1,10 +1,10 @@ ---- +--- applications: - name: auth-server-sample buildpacks: - binary_buildpack command: cmd /c .\Steeltoe.Samples.AuthApi --urls=http://0.0.0.0:%PORT% - memory: 128M + memory: 256M stack: windows env: DOTNET_CLI_TELEMETRY_OPTOUT: "true" diff --git a/Security/src/AuthApi/manifest.yml b/Security/src/AuthApi/manifest.yml index 0dc0fb0e3..bcd118937 100644 --- a/Security/src/AuthApi/manifest.yml +++ b/Security/src/AuthApi/manifest.yml @@ -1,9 +1,9 @@ ---- +--- applications: - name: auth-server-sample buildpacks: - dotnet_core_buildpack - memory: 128M + memory: 256M stack: cflinuxfs4 env: DOTNET_CLI_TELEMETRY_OPTOUT: "true" diff --git a/Security/src/AuthConsole/.cfignore b/Security/src/AuthConsole/.cfignore new file mode 100644 index 000000000..a7bd40ed2 --- /dev/null +++ b/Security/src/AuthConsole/.cfignore @@ -0,0 +1,34 @@ +# DotNet +bin/ +obj/ +publish/ + +# user-specific state +*.user + +# VS Code +.vscode/ +*.code-workspace + +# Visual Studio +.vs/ + +# JetBrains +.idea/ +*.iws +*.iml +*.ipr + +# Test framework files +scaffold/ +*.feature + +# Common files that don't need to be pushed +config/ +*.http +manifest*.yml +*.md +launchSettings.json + +# files specific this sample +GeneratedCertificates diff --git a/Security/src/AuthConsole/ApiClients/CertificateAuthorizationApiClient.cs b/Security/src/AuthConsole/ApiClients/CertificateAuthorizationApiClient.cs new file mode 100644 index 000000000..a550fcee4 --- /dev/null +++ b/Security/src/AuthConsole/ApiClients/CertificateAuthorizationApiClient.cs @@ -0,0 +1,17 @@ +using Steeltoe.Samples.AuthConsole.Models; + +namespace Steeltoe.Samples.AuthConsole.ApiClients; + +public sealed class CertificateAuthorizationApiClient(HttpClient httpClient) + : StringApiClient(httpClient) +{ + public async Task GetSameOrgAsync(CancellationToken cancellationToken) + { + return await GetAsync("api/certificate/SameOrg", cancellationToken); + } + + public async Task GetSameSpaceAsync(CancellationToken cancellationToken) + { + return await GetAsync("api/certificate/SameSpace", cancellationToken); + } +} diff --git a/Security/src/AuthConsole/ApiClients/StringApiClient.cs b/Security/src/AuthConsole/ApiClients/StringApiClient.cs new file mode 100644 index 000000000..f12fc5055 --- /dev/null +++ b/Security/src/AuthConsole/ApiClients/StringApiClient.cs @@ -0,0 +1,38 @@ +using Steeltoe.Samples.AuthConsole.Models; + +namespace Steeltoe.Samples.AuthConsole.ApiClients; + +public abstract class StringApiClient(HttpClient httpClient) +{ + protected HttpClient HttpClient => httpClient; + + protected async Task GetAsync(string requestUri, CancellationToken cancellationToken) + { + string fullRequestUri = httpClient.BaseAddress + requestUri; + + try + { + using HttpResponseMessage response = await httpClient.GetAsync(requestUri, cancellationToken); + string responseBody = await response.Content.ReadAsStringAsync(cancellationToken); + + if (response.IsSuccessStatusCode) + { + return new AuthApiResponseModel + { + RequestUri = fullRequestUri, + Message = responseBody + }; + } + + throw new HttpRequestException($"Request failed with status {(int)response.StatusCode}:{Environment.NewLine}{responseBody}"); + } + catch (Exception exception) + { + return new AuthApiResponseModel + { + RequestUri = fullRequestUri, + Error = exception + }; + } + } +} diff --git a/Security/src/AuthConsole/CloudFoundryConventions.cs b/Security/src/AuthConsole/CloudFoundryConventions.cs new file mode 100644 index 000000000..db67fc4d9 --- /dev/null +++ b/Security/src/AuthConsole/CloudFoundryConventions.cs @@ -0,0 +1,10 @@ +namespace Steeltoe.Samples.AuthConsole; + +internal sealed class CloudFoundryConventions +{ + public const string ConfigurationPrefix = "CloudFoundryConventions"; + + public string ApiUriSegment { get; set; } = ""; + + public string AppsUriSegment { get; set; } = ""; +} diff --git a/Security/src/AuthConsole/Directory.Build.props b/Security/src/AuthConsole/Directory.Build.props new file mode 100644 index 000000000..09be6a6d5 --- /dev/null +++ b/Security/src/AuthConsole/Directory.Build.props @@ -0,0 +1,8 @@ + + + 4.0.*-* + + + 8.0.* + + diff --git a/Security/src/AuthConsole/HttpClientBuilderExtensions.cs b/Security/src/AuthConsole/HttpClientBuilderExtensions.cs new file mode 100644 index 000000000..36145d5a5 --- /dev/null +++ b/Security/src/AuthConsole/HttpClientBuilderExtensions.cs @@ -0,0 +1,45 @@ +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Http.Logging; + +namespace Steeltoe.Samples.AuthConsole; + +/// +/// Provides simplified logging of outgoing HTTP requests. +/// +/// +/// Based on https://josef.codes/customize-the-httpclient-logging-dotnet-core/. +/// +public static class HttpClientBuilderExtensions +{ + public static IHttpClientBuilder ConfigureLogging(this IHttpClientBuilder builder) + { + builder.Services.TryAddScoped(); + return builder.RemoveAllLoggers().AddLogger(true); + } + + private sealed class HttpLogger(ILogger logger) : IHttpClientLogger + { + private readonly ILogger _logger = logger; + + public object? LogRequestStart(HttpRequestMessage request) + { + _logger.LogInformation("Sending '{Request.Method}' to '{Request.Host}{Request.Path}'", request.Method, + request.RequestUri?.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped), request.RequestUri?.PathAndQuery); + + return null; + } + + public void LogRequestStop(object? context, HttpRequestMessage request, HttpResponseMessage response, TimeSpan elapsed) + { + _logger.LogInformation("Received '{Response.StatusCodeInt} {Response.StatusCodeString}' after {Response.ElapsedMilliseconds}ms", + (int)response.StatusCode, response.StatusCode, elapsed.TotalMilliseconds.ToString("F1")); + } + + public void LogRequestFailed(object? context, HttpRequestMessage request, HttpResponseMessage? response, Exception exception, TimeSpan elapsed) + { + _logger.LogError(exception, "Request towards '{Request.Host}{Request.Path}' failed after {Response.ElapsedMilliseconds}ms", + request.RequestUri?.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped), request.RequestUri!.PathAndQuery, + elapsed.TotalMilliseconds.ToString("F1")); + } + } +} diff --git a/Security/src/AuthConsole/Models/AuthApiResponseModel.cs b/Security/src/AuthConsole/Models/AuthApiResponseModel.cs new file mode 100644 index 000000000..a9683f60a --- /dev/null +++ b/Security/src/AuthConsole/Models/AuthApiResponseModel.cs @@ -0,0 +1,8 @@ +namespace Steeltoe.Samples.AuthConsole.Models; + +public sealed class AuthApiResponseModel +{ + public string? RequestUri { get; set; } + public string? Message { get; set; } + public Exception? Error { get; set; } +} diff --git a/Security/src/AuthConsole/Program.cs b/Security/src/AuthConsole/Program.cs new file mode 100644 index 000000000..209fbc88f --- /dev/null +++ b/Security/src/AuthConsole/Program.cs @@ -0,0 +1,46 @@ +using Microsoft.Extensions.Options; +using Steeltoe.Common; +using Steeltoe.Common.Certificates; +using Steeltoe.Configuration.CloudFoundry; +using Steeltoe.Samples.AuthConsole; +using Steeltoe.Samples.AuthConsole.ApiClients; +using Steeltoe.Security.Authorization.Certificate; + +const string orgId = "a8fef16f-94c0-49e3-aa0b-ced7c3da6229"; +const string spaceId = "122b942a-d7b9-4839-b26e-836654b9785f"; + +HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); +builder.Services.AddHostedService(); + +// Steeltoe: Register IOptions that enable calculating the backend app's Uri based on the location of the Cloud Foundry API. +builder.Services.AddOptions().BindConfiguration(CloudFoundryConventions.ConfigurationPrefix); + +// Steeltoe: Add Cloud Foundry application info and instance identity certificate to configuration. +builder.AddCloudFoundryConfiguration(); +builder.Configuration.AddAppInstanceIdentityCertificate(new Guid(orgId), new Guid(spaceId)); + +// Steeltoe: register a typed HttpClient that includes the application instance identity certificate. +builder.Services.AddHttpClient(SetBaseAddress).AddAppInstanceIdentityCertificate().ConfigureLogging(); + +IHost host = builder.Build(); +host.Run(); + +return; + +// This code is used to limit complexity in the sample. A real application should use Service Discovery. +// To learn more about service discovery, review the documentation at: https://docs.steeltoe.io/api/v4/discovery/ +static void SetBaseAddress(IServiceProvider serviceProvider, HttpClient client) +{ + var instanceInfo = serviceProvider.GetRequiredService(); + + if (instanceInfo is CloudFoundryApplicationOptions { Api: not null } options) + { + CloudFoundryConventions conventions = serviceProvider.GetRequiredService>().Value; + string baseAddress = options.Api.Replace(conventions.ApiUriSegment, $"auth-server-sample.{conventions.AppsUriSegment}"); + client.BaseAddress = new Uri($"{baseAddress}"); + } + else + { + client.BaseAddress = new Uri("https://localhost:7184"); + } +} diff --git a/Security/src/AuthConsole/README.md b/Security/src/AuthConsole/README.md new file mode 100644 index 000000000..89f2cf287 --- /dev/null +++ b/Security/src/AuthConsole/README.md @@ -0,0 +1,42 @@ +# Steeltoe Application Security Worker/Console Client-side Authentication and Authorization + +This application shows how to use the Steeltoe [security library](https://docs.steeltoe.io/api/v4/security/) for authentication and authorization with client certificates provided by Cloud Foundry or Steeltoe (when running locally). + +## General pre-requisites + +1. Installed .NET 8 SDK +1. Optional: [Tanzu Platform for Cloud Foundry](https://techdocs.broadcom.com/us/en/vmware-tanzu/platform/tanzu-platform-for-cloud-foundry/10-0/tpcf/concepts-overview.html) + (optionally with [Windows support](https://techdocs.broadcom.com/us/en/vmware-tanzu/platform/tanzu-platform-for-cloud-foundry/10-0/tpcf/toc-tasw-install-index.html)) + and [Cloud Foundry CLI](https://github.com/cloudfoundry/cli) + +## Running locally + +1. `dotnet run` both AuthApi and AuthConsole + +## Running on Tanzu Platform for Cloud Foundry + +1. Refer to the [AuthWeb README](../AuthWeb/README.md) for instructions on deploying AuthApi + * If you are only interested in certificate authentication, skip everything related to Single Sign-On (SSO) and comment out or delete the `sampleSSOService` service reference from manifest(-windows).yml before `cf push` + +1. Push AuthConsole to Cloud Foundry + 1. `cf target -o your-org -s your-space` + 1. `cd samples/Security/src/AuthConsole` + 1. `cf push` + * When deploying to Windows, binaries must be built locally before push. Use the following commands instead: + + ```shell + dotnet publish -r win-x64 --self-contained + cf push -f manifest-windows.yml -p bin/Release/net8.0/win-x64/publish + ``` + +> [!NOTE] +> The provided manifests will create apps named `auth-client-console-sample` and `auth-server-sample` +> and attempt to bind AuthApi to the SSO service `sampleSSOService`. + +## What to expect + +At this point, the app is up and running. Since there is no user interface for this worker, you can access the logs with this command: `cf logs auth-client-console-sample` + +--- + +See the Official [Steeltoe Security Documentation](https://docs.steeltoe.io/api/v4/security/) for more detailed information. diff --git a/Security/src/AuthConsole/Steeltoe.Samples.AuthConsole.csproj b/Security/src/AuthConsole/Steeltoe.Samples.AuthConsole.csproj new file mode 100644 index 000000000..2f61743a5 --- /dev/null +++ b/Security/src/AuthConsole/Steeltoe.Samples.AuthConsole.csproj @@ -0,0 +1,16 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + diff --git a/Security/src/AuthConsole/Worker.cs b/Security/src/AuthConsole/Worker.cs new file mode 100644 index 000000000..cf57a9d26 --- /dev/null +++ b/Security/src/AuthConsole/Worker.cs @@ -0,0 +1,24 @@ +using Steeltoe.Samples.AuthConsole.ApiClients; +using Steeltoe.Samples.AuthConsole.Models; + +namespace Steeltoe.Samples.AuthConsole; + +public sealed class Worker(CertificateAuthorizationApiClient certificateAuthorizationApiClient, ILogger logger) : BackgroundService +{ + protected override async Task ExecuteAsync(CancellationToken cancellationToken) + { + while (!cancellationToken.IsCancellationRequested) + { + AuthApiResponseModel model = await certificateAuthorizationApiClient.GetSameOrgAsync(cancellationToken); + logger.LogInformation("Request Uri: {requestUri}", model.RequestUri); + logger.LogInformation("GetSameOrg response: {ApiResponse}", model.Message != null ? model.Message : model.Error); + + model = await certificateAuthorizationApiClient.GetSameSpaceAsync(cancellationToken); + logger.LogInformation("Request Uri: {requestUri}", model.RequestUri); + logger.LogInformation("GetSameSpace response: {ApiResponse}", model.Message != null ? model.Message : model.Error); + + Console.WriteLine("Sleeping for 10 seconds (press Ctrl+C to close)."); + await Task.Delay(10_000, cancellationToken); + } + } +} diff --git a/Security/src/AuthConsole/appsettings.Development.json b/Security/src/AuthConsole/appsettings.Development.json new file mode 100644 index 000000000..84c24627a --- /dev/null +++ b/Security/src/AuthConsole/appsettings.Development.json @@ -0,0 +1,10 @@ +{ + // Steeltoe: Add schema to get auto-completion. + "$schema": "https://steeltoe.io/schema/v4/schema.json", + "Logging": { + "LogLevel": { + "Default": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/Security/src/AuthConsole/appsettings.json b/Security/src/AuthConsole/appsettings.json new file mode 100644 index 000000000..7b008e4c8 --- /dev/null +++ b/Security/src/AuthConsole/appsettings.json @@ -0,0 +1,15 @@ +{ + // Steeltoe: Add schema to get auto-completion. + "$schema": "https://steeltoe.io/schema/v4/schema.json", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + // Steeltoe: Identify the subdomains used in different areas of Cloud Foundry. + "CloudFoundryConventions": { + "ApiUriSegment": "api.sys", + "AppsUriSegment": "apps" + } +} diff --git a/Security/src/AuthConsole/manifest-windows.yml b/Security/src/AuthConsole/manifest-windows.yml new file mode 100644 index 000000000..ba7c7d0fa --- /dev/null +++ b/Security/src/AuthConsole/manifest-windows.yml @@ -0,0 +1,13 @@ +--- +applications: +- name: auth-client-console-sample + buildpacks: + - binary_buildpack + command: cmd /c .\Steeltoe.Samples.AuthConsole + health-check-type: process + memory: 128M + no-route: true + stack: windows + env: + DOTNET_CLI_TELEMETRY_OPTOUT: "true" + DOTNET_NOLOGO: "true" diff --git a/Security/src/AuthConsole/manifest.yml b/Security/src/AuthConsole/manifest.yml new file mode 100644 index 000000000..8a2eee6fa --- /dev/null +++ b/Security/src/AuthConsole/manifest.yml @@ -0,0 +1,12 @@ +--- +applications: +- name: auth-client-console-sample + buildpacks: + - dotnet_core_buildpack + health-check-type: process + memory: 128M + no-route: true + stack: cflinuxfs4 + env: + DOTNET_CLI_TELEMETRY_OPTOUT: "true" + DOTNET_NOLOGO: "true" diff --git a/Security/src/AuthConsole/nuget.config b/Security/src/AuthConsole/nuget.config new file mode 100644 index 000000000..7a8af6c7c --- /dev/null +++ b/Security/src/AuthConsole/nuget.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Security/src/AuthWeb/.cfignore b/Security/src/AuthWeb/.cfignore index 490d80281..a7bd40ed2 100644 --- a/Security/src/AuthWeb/.cfignore +++ b/Security/src/AuthWeb/.cfignore @@ -1,42 +1,34 @@ # DotNet - bin/ obj/ publish/ # user-specific state - *.user # VS Code - .vscode/ *.code-workspace # Visual Studio - .vs/ # JetBrains - .idea/ *.iws *.iml *.ipr # Test framework files - scaffold/ *.feature # Common files that don't need to be pushed - config/ *.http manifest*.yml *.md launchSettings.json - # files specific this sample GeneratedCertificates diff --git a/Security/src/AuthWeb/ApiClients/CertificateAuthorizationApiClient.cs b/Security/src/AuthWeb/ApiClients/CertificateAuthorizationApiClient.cs index 9bdaa5a1f..9649a0595 100644 --- a/Security/src/AuthWeb/ApiClients/CertificateAuthorizationApiClient.cs +++ b/Security/src/AuthWeb/ApiClients/CertificateAuthorizationApiClient.cs @@ -1,6 +1,3 @@ -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; using Steeltoe.Samples.AuthWeb.Models; namespace Steeltoe.Samples.AuthWeb.ApiClients; @@ -10,11 +7,11 @@ public sealed class CertificateAuthorizationApiClient(HttpClient httpClient) { public async Task GetSameOrgAsync(CancellationToken cancellationToken) { - return await GetAsync("/api/certificate/SameOrg", cancellationToken); + return await GetAsync("api/certificate/SameOrg", cancellationToken); } public async Task GetSameSpaceAsync(CancellationToken cancellationToken) { - return await GetAsync("/api/certificate/SameSpace", cancellationToken); + return await GetAsync("api/certificate/SameSpace", cancellationToken); } } diff --git a/Security/src/AuthWeb/ApiClients/JwtAuthorizationApiClient.cs b/Security/src/AuthWeb/ApiClients/JwtAuthorizationApiClient.cs index 7efe1f6ea..6431c3c06 100644 --- a/Security/src/AuthWeb/ApiClients/JwtAuthorizationApiClient.cs +++ b/Security/src/AuthWeb/ApiClients/JwtAuthorizationApiClient.cs @@ -1,8 +1,4 @@ -using System; -using System.Net.Http; using System.Net.Http.Headers; -using System.Threading; -using System.Threading.Tasks; using Steeltoe.Samples.AuthWeb.Models; namespace Steeltoe.Samples.AuthWeb.ApiClients; @@ -22,6 +18,6 @@ public async Task GetAuthorizationAsync(string? accessToke } HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); - return await GetAsync("/api/JwtAuthorization", cancellationToken); + return await GetAsync("api/JwtAuthorization", cancellationToken); } } diff --git a/Security/src/AuthWeb/ApiClients/StringApiClient.cs b/Security/src/AuthWeb/ApiClients/StringApiClient.cs index 9dbb9ef02..5f190848a 100644 --- a/Security/src/AuthWeb/ApiClients/StringApiClient.cs +++ b/Security/src/AuthWeb/ApiClients/StringApiClient.cs @@ -1,7 +1,3 @@ -using System; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; using Steeltoe.Samples.AuthWeb.Models; namespace Steeltoe.Samples.AuthWeb.ApiClients; @@ -12,6 +8,8 @@ public abstract class StringApiClient(HttpClient httpClient) protected async Task GetAsync(string requestUri, CancellationToken cancellationToken) { + string fullRequestUri = httpClient.BaseAddress + requestUri; + try { using HttpResponseMessage response = await httpClient.GetAsync(requestUri, cancellationToken); @@ -21,6 +19,7 @@ protected async Task GetAsync(string requestUri, Cancellat { return new AuthApiResponseModel { + RequestUri = fullRequestUri, Message = responseBody }; } @@ -31,6 +30,7 @@ protected async Task GetAsync(string requestUri, Cancellat { return new AuthApiResponseModel { + RequestUri = fullRequestUri, Error = exception }; } diff --git a/Security/src/AuthWeb/Controllers/HomeController.cs b/Security/src/AuthWeb/Controllers/HomeController.cs index 6ec1546b2..657c73d19 100644 --- a/Security/src/AuthWeb/Controllers/HomeController.cs +++ b/Security/src/AuthWeb/Controllers/HomeController.cs @@ -1,6 +1,4 @@ using System.Diagnostics; -using System.Threading; -using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; diff --git a/Security/src/AuthWeb/HttpClientBuilderExtensions.cs b/Security/src/AuthWeb/HttpClientBuilderExtensions.cs index e9233c381..c3a4f617e 100644 --- a/Security/src/AuthWeb/HttpClientBuilderExtensions.cs +++ b/Security/src/AuthWeb/HttpClientBuilderExtensions.cs @@ -1,9 +1,5 @@ -using System; -using System.Net.Http; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Http.Logging; -using Microsoft.Extensions.Logging; namespace Steeltoe.Samples.AuthWeb; diff --git a/Security/src/AuthWeb/Models/AuthApiResponseModel.cs b/Security/src/AuthWeb/Models/AuthApiResponseModel.cs index 012d51f29..359a75260 100644 --- a/Security/src/AuthWeb/Models/AuthApiResponseModel.cs +++ b/Security/src/AuthWeb/Models/AuthApiResponseModel.cs @@ -1,9 +1,8 @@ -using System; - namespace Steeltoe.Samples.AuthWeb.Models; public sealed class AuthApiResponseModel { + public string? RequestUri { get; set; } public string? Message { get; set; } public Exception? Error { get; set; } } diff --git a/Security/src/AuthWeb/Program.cs b/Security/src/AuthWeb/Program.cs index a1e1a2dac..a068f341a 100644 --- a/Security/src/AuthWeb/Program.cs +++ b/Security/src/AuthWeb/Program.cs @@ -1,13 +1,5 @@ -using System; -using System.Linq; -using System.Net.Http; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; using Steeltoe.Common; using Steeltoe.Common.Certificates; using Steeltoe.Configuration.CloudFoundry; @@ -57,12 +49,6 @@ WebApplication app = builder.Build(); -// Steeltoe: Direct ASP.NET Core to use forwarded header information in order to generate links correctly when behind a reverse-proxy (eg: when in Cloud Foundry). -app.UseForwardedHeaders(new ForwardedHeadersOptions -{ - ForwardedHeaders = ForwardedHeaders.XForwardedHost | ForwardedHeaders.XForwardedProto -}); - // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { @@ -93,7 +79,7 @@ static void SetBaseAddress(IServiceProvider serviceProvider, HttpClient client) if (instanceInfo is CloudFoundryApplicationOptions { Uris.Count: > 0 } options) { string address = options.Uris.First(); - string baseAddress = address.Replace("auth-client-sample", "auth-server-sample"); + string baseAddress = address.Replace("auth-client-web-sample", "auth-server-sample"); client.BaseAddress = new Uri($"https://{baseAddress}"); } else diff --git a/Security/src/AuthWeb/README.md b/Security/src/AuthWeb/README.md index 67b7b2291..4a9443d7a 100644 --- a/Security/src/AuthWeb/README.md +++ b/Security/src/AuthWeb/README.md @@ -52,7 +52,7 @@ This application shows how to use the Steeltoe [security libraries](https://docs ``` > [!NOTE] -> The provided manifests will create apps named `auth-client-sample` and `auth-server-sample` +> The provided manifests will create apps named `auth-client-web-sample` and `auth-server-sample` > and attempt to bind both to the SSO service `sampleSSOService`. ### RedirectUri and Scope access @@ -80,10 +80,10 @@ dashboard url: https://p-identity.sys.cf-app.com/developer/identity-zones/15aa ## What to expect -At this point the app is up and running. You can access it at or . +At this point the app is up and running. You can access it at or . > [!NOTE] -> To see the logs on Cloud Foundry as the app runs, execute this command: `cf logs auth-client-sample` +> To see the logs on Cloud Foundry as the app runs, execute this command: `cf logs auth-client-web-sample` From the website's menu, click on the `Log in` menu item and you should be redirected to the UAA server's login page. Enter `testuser` and `password`, and you should be authenticated and redirected back to the auth client home page. diff --git a/Security/src/AuthWeb/Steeltoe.Samples.AuthWeb.csproj b/Security/src/AuthWeb/Steeltoe.Samples.AuthWeb.csproj index d6c3d65ab..792657f4f 100644 --- a/Security/src/AuthWeb/Steeltoe.Samples.AuthWeb.csproj +++ b/Security/src/AuthWeb/Steeltoe.Samples.AuthWeb.csproj @@ -2,6 +2,7 @@ net8.0 + enable enable diff --git a/Security/src/AuthWeb/Views/Home/InvokeService.cshtml b/Security/src/AuthWeb/Views/Home/InvokeService.cshtml index 928eaa153..da2ed4e04 100644 --- a/Security/src/AuthWeb/Views/Home/InvokeService.cshtml +++ b/Security/src/AuthWeb/Views/Home/InvokeService.cshtml @@ -1,4 +1,4 @@ -@model Steeltoe.Samples.AuthWeb.Models.AuthApiResponseModel +@model Steeltoe.Samples.AuthWeb.Models.AuthApiResponseModel @{ ViewData["Title"] = "Invoke a backend service"; } @@ -19,3 +19,5 @@ else @Model.Message } + +

Request URI: @Model.RequestUri

diff --git a/Security/src/AuthWeb/manifest-windows.yml b/Security/src/AuthWeb/manifest-windows.yml index 62a6cc596..9a0bcb111 100644 --- a/Security/src/AuthWeb/manifest-windows.yml +++ b/Security/src/AuthWeb/manifest-windows.yml @@ -1,10 +1,10 @@ ---- +--- applications: -- name: auth-client-sample +- name: auth-client-web-sample buildpacks: - binary_buildpack command: cmd /c .\Steeltoe.Samples.AuthWeb --urls=http://0.0.0.0:%PORT% - memory: 128M + memory: 256M stack: windows env: DOTNET_CLI_TELEMETRY_OPTOUT: "true" diff --git a/Security/src/AuthWeb/manifest.yml b/Security/src/AuthWeb/manifest.yml index a7083c4f4..3f6244217 100644 --- a/Security/src/AuthWeb/manifest.yml +++ b/Security/src/AuthWeb/manifest.yml @@ -1,9 +1,9 @@ ---- +--- applications: -- name: auth-client-sample +- name: auth-client-web-sample buildpacks: - dotnet_core_buildpack - memory: 128M + memory: 256M stack: cflinuxfs4 env: DOTNET_CLI_TELEMETRY_OPTOUT: "true" diff --git a/Security/src/RedisDataProtection/Steeltoe.Samples.RedisDataProtection.csproj b/Security/src/RedisDataProtection/Steeltoe.Samples.RedisDataProtection.csproj index 0b86e319d..67057d31d 100644 --- a/Security/src/RedisDataProtection/Steeltoe.Samples.RedisDataProtection.csproj +++ b/Security/src/RedisDataProtection/Steeltoe.Samples.RedisDataProtection.csproj @@ -2,8 +2,8 @@ net8.0 - enable enable + enable diff --git a/Security/src/Steeltoe.Samples.Security.sln b/Security/src/Steeltoe.Samples.Security.sln index 91d653869..3a1eb59fb 100644 --- a/Security/src/Steeltoe.Samples.Security.sln +++ b/Security/src/Steeltoe.Samples.Security.sln @@ -8,10 +8,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ..\README.md = ..\README.md EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.Samples.AuthWeb", "AuthWeb\Steeltoe.Samples.AuthWeb.csproj", "{CBBCE83B-8AF2-40BB-A7E0-11AA4CA61FD2}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.Samples.AuthApi", "AuthApi\Steeltoe.Samples.AuthApi.csproj", "{D3CBBDCC-2BF2-4917-9A56-AEED28FBC6E1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Steeltoe.Samples.AuthConsole", "AuthConsole\Steeltoe.Samples.AuthConsole.csproj", "{F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.Samples.AuthWeb", "AuthWeb\Steeltoe.Samples.AuthWeb.csproj", "{CBBCE83B-8AF2-40BB-A7E0-11AA4CA61FD2}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.Samples.RedisDataProtection", "RedisDataProtection\Steeltoe.Samples.RedisDataProtection.csproj", "{A0EDA633-4FF3-40A5-BA7D-2516F6AD2C8C}" EndProject Global @@ -60,6 +62,18 @@ Global {A0EDA633-4FF3-40A5-BA7D-2516F6AD2C8C}.Release|x64.Build.0 = Release|Any CPU {A0EDA633-4FF3-40A5-BA7D-2516F6AD2C8C}.Release|x86.ActiveCfg = Release|Any CPU {A0EDA633-4FF3-40A5-BA7D-2516F6AD2C8C}.Release|x86.Build.0 = Release|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Debug|x64.ActiveCfg = Debug|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Debug|x64.Build.0 = Debug|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Debug|x86.ActiveCfg = Debug|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Debug|x86.Build.0 = Debug|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Release|Any CPU.Build.0 = Release|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Release|x64.ActiveCfg = Release|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Release|x64.Build.0 = Release|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Release|x86.ActiveCfg = Release|Any CPU + {F9143A4B-4D52-4C65-BFD3-CE967BE4AA01}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE