Skip to content

Commit

Permalink
WeatherForecast as an SSO service
Browse files Browse the repository at this point in the history
  • Loading branch information
JZO001 committed Oct 30, 2022
1 parent f3aac28 commit c9e5e44
Show file tree
Hide file tree
Showing 21 changed files with 356 additions and 44 deletions.
8 changes: 6 additions & 2 deletions Forge.Yoda.Apps.ASPNETCore.Client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Forge.Yoda.Shared.UI;
using Forge.Wasm.BrowserStorages.Services.Abstraction;

namespace Forge.Yoda.Apps.ASPNETCore.Client
{
Expand Down Expand Up @@ -46,8 +47,11 @@ public static async Task Main(string[] args)
builder.Services.AddScoped<UserContext>();

// business services goes here...
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped(typeof(IWeatherForecastService), typeof(WeatherForecastService));
//builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri($"{builder.HostEnvironment.BaseAddress}:7067") });
//builder.Services.AddScoped(typeof(IWeatherForecastService), typeof(WeatherForecastService));
builder.Services.AddWeatherForecastService(config => {
config.BaseAddress = "https://localhost:7067/";
});

await builder.Build().RunAsync();
}
Expand Down
7 changes: 5 additions & 2 deletions Forge.Yoda.Apps.MAUI/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public static MauiApp CreateMauiApp()

#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
string baseAddress = DeviceInfo.Platform == DevicePlatform.Android ? "https://10.0.2.2:7166" : "https://localhost:7166";
string baseAddress = DeviceInfo.Platform == DevicePlatform.Android ? "https://10.0.2.2:7067" : "https://localhost:7067";
builder.Services.AddScoped(sp => new HttpClient(GetLocalhostHandler()) { BaseAddress = new Uri(baseAddress) });
#else
// TODO: change it to the final address
Expand Down Expand Up @@ -80,7 +80,10 @@ public static MauiApp CreateMauiApp()

builder.Services.AddScoped<UserContext>();

builder.Services.AddScoped(typeof(IWeatherForecastService), typeof(WeatherForecastService));
//builder.Services.AddScoped(typeof(IWeatherForecastService), typeof(WeatherForecastService));
builder.Services.AddWeatherForecastService(config => {
config.BaseAddress = "https://localhost:7067/";
});

return builder.Build();
}
Expand Down
8 changes: 6 additions & 2 deletions Forge.Yoda.Apps.WPF/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ public MainWindow()
services.AddScoped<UserContext>();

// business services goes here...
services.AddTransient(sp => new HttpClient(GetInsecureHandler()) { BaseAddress = new Uri("https://localhost:7166/") });
services.AddScoped(typeof(IWeatherForecastService), typeof(WeatherForecastService));
//services.AddTransient(sp => new HttpClient(GetInsecureHandler()) { BaseAddress = new Uri("https://localhost:7067/") });
//services.AddScoped(typeof(IWeatherForecastService), typeof(WeatherForecastService));
services.AddWeatherForecastService(config => {
config.BaseAddress = "https://localhost:7067/";
});


ServiceProvider serviceProvider = services.BuildServiceProvider();

Expand Down
7 changes: 5 additions & 2 deletions Forge.Yoda.Apps.WinForms/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ private void MainForm_Shown(object sender, EventArgs e)
services.AddScoped<UserContext>();

// business services goes here...
services.AddTransient(sp => new HttpClient(GetInsecureHandler()) { BaseAddress = new Uri("https://localhost:7166/") });
services.AddScoped(typeof(IWeatherForecastService), typeof(WeatherForecastService));
//services.AddTransient(sp => new HttpClient(GetInsecureHandler()) { BaseAddress = new Uri("https://localhost:7067/") });
//services.AddScoped(typeof(IWeatherForecastService), typeof(WeatherForecastService));
services.AddWeatherForecastService(config => {
config.BaseAddress = "https://localhost:7067/";
});

ServiceProvider serviceProvider = services.BuildServiceProvider();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public ActionResult Logout([FromBody] LogoutRequestViewModel request)
return Ok(new BooleanResponse() { Result = result });
}

[AllowAnonymous]
[HttpPost("validate-token")]
public async Task<ActionResult> ValidateToken([FromBody] TokenRequest request)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,17 @@
<PackageReference Include="Forge.Security.Jwt.Service.Storage.SqlServer" Version="1.0.0" />
<PackageReference Include="Forge.Security.Jwt.Shared" Version="1.6.0" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.10">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.10">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.10" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.5" />
<PackageReference Include="log4net" Version="2.0.15" />
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="6.1.0" />
</ItemGroup>

<ItemGroup>
<!--Reference Include="Forge.Security.Jwt.Service">
<HintPath>..\Forge.Yoda.Externals\Forge.Security.Jwt.Service.dll</HintPath>
</Reference>
<Reference Include="Forge.Security.Jwt.Shared">
<HintPath>..\Forge.Yoda.Externals\Forge.Security.Jwt.Shared.dll</HintPath>
</Reference>
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.24.0" />
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.10" /-->

<Folder Include="Migrations\" />
</ItemGroup>

</Project>
4 changes: 2 additions & 2 deletions Forge.Yoda.Services.Authentication/Services/UserService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ public async Task<LoginResult> Login(string username, string password, IEnumerab
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Role, user.Role),
new Claim(ClaimTypes.NameIdentifier, user.Id),
new Claim(ClaimTypes.Surname, user.Surname),
new Claim(ClaimTypes.GivenName, user.Givenname),
new Claim(ClaimTypes.Surname, user.Surname!),
new Claim(ClaimTypes.GivenName, user.Givenname!),
new Claim(ClaimTypes.Email, user.Email),
};

Expand Down
5 changes: 4 additions & 1 deletion Forge.Yoda.Services.Authentication/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.IdentityModel.Tokens;
using Swashbuckle.AspNetCore.Filters;
using System.Text;
using Forge.Yoda.Services.Authentication.Codes;

namespace Forge.Yoda.Services.Authentication
{
Expand Down Expand Up @@ -62,6 +63,7 @@ public void ConfigureServices(IServiceCollection services)
.AddEntityFrameworkStores<DatabaseContext>()
.AddDefaultTokenProviders();

// add JWT bearer token authentication
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
Expand Down Expand Up @@ -102,7 +104,8 @@ public void ConfigureServices(IServiceCollection services)
});
});

services.AddControllers().AddNewtonsoftJson();//.AddXmlSerializerFormatters();
services.AddControllers().AddNewtonsoftJson();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
services.AddEndpointsApiExplorer();
services.AddSwaggerGen(options =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
using Forge.Yoda.Shared.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Forge.Yoda.Apps.ASPNETCore.Server.Controllers
namespace Forge.Yoda.Services.WeatherForecastApi.Controllers
{
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

private readonly ILogger<WeatherForecastController> _logger;

Expand All @@ -19,7 +21,7 @@ public WeatherForecastController(ILogger<WeatherForecastController> logger)
_logger = logger;
}

[HttpGet]
[HttpGet(/*Name = "GetWeatherForecast"*/)]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
Expand Down
22 changes: 22 additions & 0 deletions Forge.Yoda.Services.WeatherForecastApi/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["Forge.Yoda.Services.WeatherForecastApi/Forge.Yoda.Services.WeatherForecastApi.csproj", "Forge.Yoda.Services.WeatherForecastApi/"]
RUN dotnet restore "Forge.Yoda.Services.WeatherForecastApi/Forge.Yoda.Services.WeatherForecastApi.csproj"
COPY . .
WORKDIR "/src/Forge.Yoda.Services.WeatherForecastApi"
RUN dotnet build "Forge.Yoda.Services.WeatherForecastApi.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "Forge.Yoda.Services.WeatherForecastApi.csproj" -c Release -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Forge.Yoda.Services.WeatherForecastApi.dll"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>e48e8476-964c-4df5-9dda-abcef6f128df</UserSecretsId>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Forge.Security.Jwt.Service" Version="1.5.1" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.17.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.10" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.10" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.5" />
<PackageReference Include="log4net" Version="2.0.15" />
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="6.1.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Forge.Yoda.Shared.Models\Forge.Yoda.Shared.Models.csproj" />
</ItemGroup>

</Project>
102 changes: 102 additions & 0 deletions Forge.Yoda.Services.WeatherForecastApi/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using Forge.Security.Jwt.Service;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Swashbuckle.AspNetCore.Filters;
using System.Text;

namespace Forge.Yoda.Services.WeatherForecastApi
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
JwtTokenConfiguration jwtTokenConfig = builder.Configuration.GetSection("JwtTokenConfig").Get<JwtTokenConfiguration>();
builder.Services.AddSingleton(jwtTokenConfig);

// add JWT bearer token authentication
builder.Services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = true;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = jwtTokenConfig.ValidateIssuer,
ValidIssuer = jwtTokenConfig.Issuer,
ValidateIssuerSigningKey = jwtTokenConfig.ValidateIssuerSigningKey,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtTokenConfig.Secret)),
ValidAudience = jwtTokenConfig.Audience,
ValidateAudience = jwtTokenConfig.ValidateAudience,
ValidateLifetime = jwtTokenConfig.ValidateLifetime,
ClockSkew = TimeSpan.FromMinutes(jwtTokenConfig.ClockSkewInMinutes)
};
});

builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.AllowAnyHeader()
.AllowAnyOrigin()
.AllowAnyMethod();
});
});

builder.Services.AddControllers().AddNewtonsoftJson();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.AddSecurityDefinition("Access Token", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
{
BearerFormat = JwtBearerDefaults.AuthenticationScheme,
Description = "Standard Authorization header using the Bearer scheme. Example: \"Bearer {access token}\"",
Name = "Authorization",
Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
In = Microsoft.OpenApi.Models.ParameterLocation.Header
});

options.OperationFilter<SecurityRequirementsOperationFilter>();
});

builder.Services.AddLogging(options => options.SetMinimumLevel(LogLevel.Trace));

var app = builder.Build();

ILoggerFactory loggerFactory = (ILoggerFactory)app.Services.GetService(typeof(ILoggerFactory));
loggerFactory.AddLog4Net();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseRouting();

app.UseCors();

app.UseAuthentication();

app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});

app.Run();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"profiles": {
"Forge.Yoda.Services.WeatherForecastApi": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"dotnetRunMessages": true,
"applicationUrl": "https://localhost:7067;http://localhost:5067"
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
"publishAllPorts": true,
"useSSL": true
}
},
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:15491",
"sslPort": 44322
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
Loading

0 comments on commit c9e5e44

Please sign in to comment.