mirror of
https://github.com/byo-software/steam-openid-connect-provider.git
synced 2025-01-09 18:06:22 +00:00
Refactor code
This commit is contained in:
parent
0e74cd4321
commit
ce7dfb3a9e
9 changed files with 173 additions and 124 deletions
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Identity;
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace SteamOpenIdConnectProvider
|
||||
namespace SteamOpenIdConnectProvider.Controllers
|
||||
{
|
||||
[AllowAnonymous]
|
||||
[Route("[action]")]
|
||||
|
@ -28,20 +28,20 @@ namespace SteamOpenIdConnectProvider
|
|||
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> ExternalLogin(string returnUrl = null)
|
||||
public Task<IActionResult> ExternalLogin(string returnUrl = null)
|
||||
{
|
||||
string provider = "Steam";
|
||||
const string provider = "Steam";
|
||||
|
||||
// Request a redirect to the external login provider.
|
||||
var redirectUrl = Url.Action("ExternalLoginCallback", new { returnUrl });
|
||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
|
||||
return new ChallengeResult(provider, properties);
|
||||
return Task.FromResult<IActionResult>(new ChallengeResult(provider, properties));
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
|
||||
{
|
||||
returnUrl = returnUrl ?? Url.Content("~/");
|
||||
returnUrl ??= Url.Content("~/");
|
||||
|
||||
if (remoteError != null)
|
||||
{
|
||||
throw new Exception($"Error from external provider: {remoteError}");
|
||||
|
@ -53,7 +53,6 @@ namespace SteamOpenIdConnectProvider
|
|||
throw new Exception($"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)
|
||||
{
|
||||
|
@ -61,13 +60,13 @@ namespace SteamOpenIdConnectProvider
|
|||
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 };
|
||||
|
||||
_userManager.UserValidators.Clear();
|
||||
|
||||
var result = await _userManager.CreateAsync(user);
|
||||
if (result.Succeeded)
|
||||
{
|
|
@ -2,7 +2,7 @@
|
|||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace SteamOpenIdConnectProvider
|
||||
namespace SteamOpenIdConnectProvider.Database
|
||||
{
|
||||
// This is completely in-memory, we do not need a persistent store.
|
||||
public class AppInMemoryDbContext : IdentityDbContext<IdentityUser>
|
11
src/Profile/Models/GetPlayerSummariesResponse.cs
Normal file
11
src/Profile/Models/GetPlayerSummariesResponse.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SteamOpenIdConnectProvider.Profile.Models
|
||||
{
|
||||
public sealed class GetPlayerSummariesResponse
|
||||
{
|
||||
[JsonProperty("players")]
|
||||
public ICollection<Player> Players { get; set; }
|
||||
}
|
||||
}
|
58
src/Profile/Models/Player.cs
Normal file
58
src/Profile/Models/Player.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace SteamOpenIdConnectProvider.Profile.Models
|
||||
{
|
||||
public sealed class Player
|
||||
{
|
||||
[JsonProperty("steamid")]
|
||||
public ulong SteamId { get; set; }
|
||||
|
||||
[JsonProperty("communityvisibilitystate")]
|
||||
public int CommunityVisibilityState { get; set; }
|
||||
|
||||
[JsonProperty("profilestate")]
|
||||
public int ProfileState { get; set; }
|
||||
|
||||
[JsonProperty("personaname")]
|
||||
public string PersonaName { get; set; }
|
||||
|
||||
[JsonProperty("commentpermission")]
|
||||
public int CommentPermission { get; set; }
|
||||
|
||||
[JsonProperty("profileurl")]
|
||||
public string ProfileUrl { get; set; }
|
||||
|
||||
[JsonProperty("avatar")]
|
||||
public string Avatar { get; set; }
|
||||
|
||||
[JsonProperty("avatarmedium")]
|
||||
public string AvatarMedium { get; set; }
|
||||
|
||||
[JsonProperty("avatarfull")]
|
||||
public string AvatarFull { get; set; }
|
||||
|
||||
[JsonProperty("avatarhash")]
|
||||
public string AvatarHash { get; set; }
|
||||
|
||||
[JsonProperty("lastlogoff")]
|
||||
public int LastLogoff { get; set; }
|
||||
|
||||
[JsonProperty("personastate")]
|
||||
public int PersonaState { get; set; }
|
||||
|
||||
[JsonProperty("realname")]
|
||||
public string RealName { get; set; }
|
||||
|
||||
[JsonProperty("primaryclanid")]
|
||||
public ulong PrimaryClanId { get; set; }
|
||||
|
||||
[JsonProperty("timecreated")]
|
||||
public int TimeCreated { get; set; }
|
||||
|
||||
[JsonProperty("personastateflags")]
|
||||
public int PersonaStateFlags { get; set; }
|
||||
|
||||
[JsonProperty("loccountrycode")]
|
||||
public string LocCountryCode { get; set; }
|
||||
}
|
||||
}
|
10
src/Profile/Models/SteamResponse.cs
Normal file
10
src/Profile/Models/SteamResponse.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace SteamOpenIdConnectProvider.Profile.Models
|
||||
{
|
||||
public sealed class SteamResponse<T>
|
||||
{
|
||||
[JsonProperty("response")]
|
||||
public T Response { get; set; }
|
||||
}
|
||||
}
|
80
src/Profile/SteamProfileService.cs
Normal file
80
src/Profile/SteamProfileService.cs
Normal file
|
@ -0,0 +1,80 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using IdentityServer4.Extensions;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Services;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Newtonsoft.Json;
|
||||
using SteamOpenIdConnectProvider.Profile.Models;
|
||||
|
||||
namespace SteamOpenIdConnectProvider.Profile
|
||||
{
|
||||
public class SteamProfileService : IProfileService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IUserClaimsPrincipalFactory<IdentityUser> _claimsFactory;
|
||||
private readonly UserManager<IdentityUser> _userManager;
|
||||
|
||||
private async Task<GetPlayerSummariesResponse> GetPlayerSummariesAsync(IEnumerable<string> steamIds)
|
||||
{
|
||||
const string baseurl = "https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002";
|
||||
|
||||
var applicationKey = _configuration["Authentication:Steam:ApplicationKey"];
|
||||
var url = $"{baseurl}/?key={applicationKey}&steamids={string.Join(',', steamIds)}";
|
||||
|
||||
var res = await _httpClient.GetStringAsync(url);
|
||||
var response = JsonConvert.DeserializeObject<SteamResponse<GetPlayerSummariesResponse>>(res);
|
||||
return response.Response;
|
||||
}
|
||||
|
||||
public SteamProfileService(
|
||||
UserManager<IdentityUser> userManager,
|
||||
IUserClaimsPrincipalFactory<IdentityUser> claimsFactory,
|
||||
IConfiguration configuration,
|
||||
HttpClient httpClient)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_claimsFactory = claimsFactory;
|
||||
_configuration = configuration;
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
|
||||
{
|
||||
var sub = context.Subject.GetSubjectId();
|
||||
var user = await _userManager.FindByIdAsync(sub);
|
||||
var principal = await _claimsFactory.CreateAsync(user);
|
||||
|
||||
var claims = principal.Claims.ToList();
|
||||
claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
|
||||
|
||||
const string steamUrl = "https://steamcommunity.com/openid/id/";
|
||||
var steamId = sub.Substring(steamUrl.Length);
|
||||
|
||||
var userSummary = await GetPlayerSummariesAsync(new[] { steamId });
|
||||
var player = userSummary.Players.FirstOrDefault();
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
claims.Add(new Claim("picture", player.AvatarFull));
|
||||
claims.Add(new Claim("nickname", player.PersonaName));
|
||||
claims.Add(new Claim("given_name", player.RealName));
|
||||
claims.Add(new Claim("website", player.ProfileUrl));
|
||||
}
|
||||
|
||||
context.IssuedClaims = claims;
|
||||
}
|
||||
|
||||
public async Task IsActiveAsync(IsActiveContext context)
|
||||
{
|
||||
var sub = context.Subject.GetSubjectId();
|
||||
var user = await _userManager.FindByIdAsync(sub);
|
||||
context.IsActive = user != null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Extensions;
|
||||
using IdentityServer4.Services;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace IdentityServer.Services
|
||||
{
|
||||
public class ProfileService : IProfileService
|
||||
{
|
||||
private IConfiguration _configuration;
|
||||
private readonly IUserClaimsPrincipalFactory<IdentityUser> _claimsFactory;
|
||||
private readonly UserManager<IdentityUser> _userManager;
|
||||
|
||||
private async Task<IPlayerSummary> FetchUserSummary(string steamid64)
|
||||
{
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
|
||||
var baseurl = "https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002";
|
||||
var applicationKey = _configuration["Authentication:Steam:ApplicationKey"];
|
||||
var url = $"{baseurl}/?key={applicationKey}&steamids={steamid64}";
|
||||
|
||||
var res = await httpClient.GetStringAsync(url);
|
||||
var json = JsonConvert.DeserializeObject<IPlayerSummary>(res);
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
public class Player {
|
||||
public string steamid { get; set; }
|
||||
public int communityvisibilitystate { get; set; }
|
||||
public int profilestate { get; set; }
|
||||
public string personaname { get; set; }
|
||||
public int commentpermission { get; set; }
|
||||
public string profileurl { get; set; }
|
||||
public string avatar { get; set; }
|
||||
public string avatarmedium { get; set; }
|
||||
public string avatarfull { get; set; }
|
||||
public string avatarhash { get; set; }
|
||||
public int lastlogoff { get; set; }
|
||||
public int personastate { get; set; }
|
||||
public string realname { get; set; }
|
||||
public string primaryclanid { get; set; }
|
||||
public int timecreated { get; set; }
|
||||
public int personastateflags { get; set; }
|
||||
public string loccountrycode { get; set; }
|
||||
}
|
||||
|
||||
public class Response {
|
||||
public List<Player> players { get; set; }
|
||||
}
|
||||
|
||||
public class IPlayerSummary {
|
||||
public Response response { get; set; }
|
||||
}
|
||||
|
||||
public ProfileService(
|
||||
UserManager<IdentityUser> userManager,
|
||||
IUserClaimsPrincipalFactory<IdentityUser> claimsFactory,
|
||||
IConfiguration configuration
|
||||
)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_claimsFactory = claimsFactory;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
|
||||
{
|
||||
var sub = context.Subject.GetSubjectId();
|
||||
var user = await _userManager.FindByIdAsync(sub);
|
||||
var principal = await _claimsFactory.CreateAsync(user);
|
||||
|
||||
var claims = principal.Claims.ToList();
|
||||
claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
|
||||
|
||||
var steamurl = "https://steamcommunity.com/openid/id/";
|
||||
var steamid64 = sub.Substring(steamurl.Length);
|
||||
|
||||
var userSummary = await FetchUserSummary(steamid64);
|
||||
var player = userSummary.response.players[0];
|
||||
|
||||
if (player != null)
|
||||
{
|
||||
claims.Add(new Claim("picture", player.avatarfull));
|
||||
claims.Add(new Claim("nickname", player.personaname));
|
||||
claims.Add(new Claim("given_name", player.realname));
|
||||
claims.Add(new Claim("website", player.profileurl));
|
||||
}
|
||||
|
||||
context.IssuedClaims = claims;
|
||||
}
|
||||
|
||||
public async Task IsActiveAsync(IsActiveContext context)
|
||||
{
|
||||
var sub = context.Subject.GetSubjectId();
|
||||
var user = await _userManager.FindByIdAsync(sub);
|
||||
context.IsActive = user != null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,7 +19,6 @@ namespace SteamOpenIdConnectProvider
|
|||
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate)
|
||||
.CreateLogger();
|
||||
|
||||
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
@ -9,7 +10,8 @@ using Microsoft.Extensions.Configuration;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using IdentityServer4.Services;
|
||||
using IdentityServer.Services;
|
||||
using SteamOpenIdConnectProvider.Database;
|
||||
using SteamOpenIdConnectProvider.Profile;
|
||||
|
||||
namespace SteamOpenIdConnectProvider
|
||||
{
|
||||
|
@ -29,8 +31,7 @@ namespace SteamOpenIdConnectProvider
|
|||
.AddNewtonsoftJson()
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
|
||||
|
||||
services.AddSingleton<IConfiguration>(Configuration);
|
||||
|
||||
services.AddSingleton(Configuration);
|
||||
services.AddDbContext<AppInMemoryDbContext>(options =>
|
||||
options.UseInMemoryDatabase("default"));
|
||||
|
||||
|
@ -56,7 +57,7 @@ namespace SteamOpenIdConnectProvider
|
|||
.AddDeveloperSigningCredential(true)
|
||||
.AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources());
|
||||
|
||||
services.AddScoped<IProfileService, ProfileService>();
|
||||
services.AddHttpClient<IProfileService, SteamProfileService>();
|
||||
|
||||
services.AddAuthentication()
|
||||
.AddCookie(options =>
|
||||
|
|
Loading…
Reference in a new issue