mirror of
https://github.com/byo-software/steam-openid-connect-provider.git
synced 2025-01-08 09:36:21 +00:00
Initial code commit
This commit is contained in:
parent
0fb2b10212
commit
a07646e608
11 changed files with 339 additions and 0 deletions
9
.dockerignore
Normal file
9
.dockerignore
Normal file
|
@ -0,0 +1,9 @@
|
|||
.dockerignore
|
||||
.env
|
||||
.git
|
||||
.gitignore
|
||||
.vs
|
||||
.vscode
|
||||
*/bin
|
||||
*/obj
|
||||
**/.toolstarget
|
18
Dockerfile
Normal file
18
Dockerfile
Normal 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"]
|
25
SteamOpenIdConnectProxy.sln
Normal file
25
SteamOpenIdConnectProxy.sln
Normal 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
|
15
src/AppInMemoryDbContext.cs
Normal file
15
src/AppInMemoryDbContext.cs
Normal 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
89
src/ExternalLoginController.cs
Normal file
89
src/ExternalLoginController.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
45
src/IdentityServerConfig.cs
Normal file
45
src/IdentityServerConfig.cs
Normal 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
32
src/Program.cs
Normal 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
61
src/Startup.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
22
src/SteamOpenIdConnectProxy.csproj
Normal file
22
src/SteamOpenIdConnectProxy.csproj
Normal 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>
|
9
src/appsettings.Development.json
Normal file
9
src/appsettings.Development.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
}
|
||||
}
|
14
src/appsettings.json
Normal file
14
src/appsettings.json
Normal 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": "*"
|
||||
}
|
Loading…
Reference in a new issue