Initial code commit

This commit is contained in:
Enes Sadık Özbek 2019-05-02 00:41:28 +03:00
parent 0fb2b10212
commit a07646e608
11 changed files with 339 additions and 0 deletions

9
.dockerignore Normal file
View file

@ -0,0 +1,9 @@
.dockerignore
.env
.git
.gitignore
.vs
.vscode
*/bin
*/obj
**/.toolstarget

18
Dockerfile Normal file
View file

@ -0,0 +1,18 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["src/SteamOpenIdConnectProxy/SteamOpenIdConnectProxy.csproj", "SteamOpenIdConnectProxy/"]
RUN dotnet restore "SteamOpenIdConnectProxy/SteamOpenIdConnectProxy.csproj"
COPY src/ .
WORKDIR "/src/SteamOpenIdConnectProxy"
RUN dotnet build "SteamOpenIdConnectProxy.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "SteamOpenIdConnectProxy.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "SteamOpenIdConnectProxy.dll"]

View file

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.202
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SteamOpenIdConnectProxy", "src\SteamOpenIdConnectProxy.csproj", "{39261E1A-B9AB-45C1-991E-B88ED3E076A2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{39261E1A-B9AB-45C1-991E-B88ED3E076A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39261E1A-B9AB-45C1-991E-B88ED3E076A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39261E1A-B9AB-45C1-991E-B88ED3E076A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39261E1A-B9AB-45C1-991E-B88ED3E076A2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9BCD5B86-0661-4AF9-A17E-7710A46BF914}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,15 @@
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace SteamOpenIdConnectProxy
{
// This is completely in-memory, we do not need a persistent store.
public class AppInMemoryDbContext : IdentityDbContext<IdentityUser>
{
public AppInMemoryDbContext(DbContextOptions<AppInMemoryDbContext> options)
: base(options)
{
}
}
}

View file

@ -0,0 +1,89 @@
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace SteamOpenIdConnectProxy
{
[AllowAnonymous]
public class ExternalLoginController : Controller
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
private readonly ILogger<ExternalLoginController> _logger;
public ExternalLoginController(
SignInManager<IdentityUser> signInManager,
UserManager<IdentityUser> userManager,
ILogger<ExternalLoginController> logger)
{
_signInManager = signInManager;
_userManager = userManager;
_logger = logger;
}
[HttpGet]
[Route("/ExternalLogin")]
public async Task<IActionResult> Login(string returnUrl = null)
{
string provider = "Steam";
// Request a redirect to the external login provider.
var redirectUrl = "/ExternalLoginCallback?returnUrl=" + Uri.EscapeUriString(returnUrl);
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return new ChallengeResult(provider, properties);
}
[HttpGet]
[Route("/ExternalLoginCallback")]
public async Task<IActionResult> Callback(string returnUrl = null, string remoteError = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (remoteError != null)
{
return Content($"Error from external provider: {remoteError}");
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return Content($"Error loading external login information.");
}
// Sign in the user with this external login provider if the user already has a login.
var externalLoginResult = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
if (externalLoginResult.Succeeded)
{
_logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider);
return LocalRedirect(returnUrl);
}
var userName = info.Principal.FindFirstValue(ClaimTypes.Name);
var userId = info.Principal.FindFirstValue(ClaimTypes.NameIdentifier);
var user = new IdentityUser { UserName = userName, Id = userId };
var result = await _userManager.CreateAsync(user);
if (result.Succeeded)
{
result = await _userManager.AddLoginAsync(user, info);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
return BadRequest();
}
}
}

View file

@ -0,0 +1,45 @@
using System.Collections.Generic;
using IdentityServer4;
using IdentityServer4.Models;
namespace SteamOpenIdConnectProxy
{
public class IdentityServerConfig
{
public static IEnumerable<Client> GetClients(string clientId, string secret, string redirectUri, string logoutRedirectUri)
{
yield return new Client
{
ClientId = clientId,
ClientName = "Proxy Client",
AllowedGrantTypes = GrantTypes.Code,
ClientSecrets =
{
new Secret(secret.Sha256())
},
// where to redirect to after login
RedirectUris = { redirectUri },
// where to redirect to after logout
PostLogoutRedirectUris = { logoutRedirectUri },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
}
};
}
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
}
}
}

32
src/Program.cs Normal file
View file

@ -0,0 +1,32 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;
namespace SteamOpenIdConnectProxy
{
public class Program
{
public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.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.Literate)
.CreateLogger();
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseSerilog()
.UseStartup<Startup>();
}
}

61
src/Startup.cs Normal file
View file

@ -0,0 +1,61 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace SteamOpenIdConnectProxy
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddDbContext<AppInMemoryDbContext>(options =>
options.UseInMemoryDatabase("default")
);
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<AppInMemoryDbContext>()
.AddDefaultTokenProviders();
services.AddIdentityServer(options =>
{
options.UserInteraction.LoginUrl = "/ExternalLogin";
})
.AddAspNetIdentity<IdentityUser>()
.AddInMemoryClients(IdentityServerConfig.GetClients(Configuration["OpenID:ClientID"], Configuration["OpenID:ClientSecret"], Configuration["OpenID:RedirectUri"], Configuration["OpenID:PostLogoutRedirectUri"]))
.AddInMemoryPersistedGrants()
.AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources());
services.AddAuthentication()
.AddSteam(options =>
{
options.ApplicationKey = Configuration["Authentication:Steam:ApplicationKey"];
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
app.UseMvc();
}
}
}

View file

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
<UserSecretsId>9f8cb9ce-f696-422f-901a-563af9413684</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AspNet.Security.OpenId.Steam" Version="2.0.0" />
<PackageReference Include="AspNet.Security.OpenIdConnect.Server" Version="2.0.0" />
<PackageReference Include="IdentityServer4" Version="2.4.0" />
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.4.0" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" />
<PackageReference Include="Serilog" Version="2.8.0" />
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}

14
src/appsettings.json Normal file
View file

@ -0,0 +1,14 @@
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"OpenID": {
"ClientID": "proxy",
"ClientSecret": "secret",
"RedirectUri": "http://localhost:8080/auth/realms/master/broker/steam/endpoint",
"PostLogoutRedirectUri": ""
},
"AllowedHosts": "*"
}