a client store

This commit is contained in:
Paul Schneider
2025-07-15 17:35:14 +01:00
parent 1e766f4718
commit f43fd76baa
6 changed files with 80 additions and 57 deletions

View File

@ -31,38 +31,34 @@ public static class Config
/// <summary> /// <summary>
/// Lists Available user profile classes, /// Lists Available user profile classes,
/// populated at startup, using reflexion. /// populated at startup, using reflection.
/// </summary> /// </summary>
public static List<Type> ProfileTypes = new List<Type>(); public static List<Type> ProfileTypes = new List<Type>();
public static IEnumerable<IdentityResource> IdentityResources => public static IEnumerable<IdentityResource> IdentityResources =>
new IdentityResource[] [
{
new IdentityResources.OpenId(), new IdentityResources.OpenId(),
new IdentityResources.Profile(), new IdentityResources.Profile(),
new IdentityResources.Email() new IdentityResources.Email()
}; ];
public static IEnumerable<ApiScope> ApiScopes => public static IEnumerable<ApiScope> TestingApiScopes =>
new ApiScope[] [
{
new ApiScope("scope1",new string[] {"scope1"}), new ApiScope("scope1",new string[] {"scope1"}),
new ApiScope("scope2",new string[] {"scope2"}), new ApiScope("scope2",new string[] {"scope2"}),
}; ];
public static IEnumerable<Client> Clients => public static IEnumerable<Client> TestingClients =>
new Client[] [
{
// m2m client credentials flow client // m2m client credentials flow client
new Client new Client
{ {
ClientId = "m2m.client", ClientId = "m2m.client",
ClientName = "Client Credentials Client", ClientName = "Client Credentials Client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) }, ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = { "scope1" } AllowedScopes = { "scope1" }
}, },
@ -87,7 +83,7 @@ public static class Config
IdentityServerConstants.StandardScopes.OfflineAccess, IdentityServerConstants.StandardScopes.OfflineAccess,
"scope2" }, "scope2" },
}, },
}; ];
public static PayPalSettings? PayPalSettings { get; set; } public static PayPalSettings? PayPalSettings { get; set; }
} }

View File

@ -1,17 +1,22 @@
 
using Yavsc.Models.Haircut; using Microsoft.EntityFrameworkCore;
using Yavsc.Models.IT.Evolution; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Yavsc.Models.IT.Fixing; using Microsoft.EntityFrameworkCore.ChangeTracking;
using Yavsc.Abstract.Models.Messaging;
using Yavsc.Server.Models.EMailing; using Yavsc.Server.Models.EMailing;
using Yavsc.Server.Models.IT.SourceCode; using Yavsc.Server.Models.IT.SourceCode;
using Yavsc.Server.Models.IT; using Yavsc.Server.Models.IT;
using Yavsc.Models.Streaming; using Yavsc.Abstract.Identity;
using Yavsc.Server.Models.Calendar;
namespace Yavsc.Models namespace Yavsc.Models
{ {
using Haircut;
using IT.Evolution;
using IT.Fixing;
using Streaming;
using Relationship; using Relationship;
using Forms; using Forms;
using Yavsc;
using Auth; using Auth;
using Billing; using Billing;
using Musical; using Musical;
@ -28,18 +33,13 @@ namespace Yavsc.Models
using Bank; using Bank;
using Payment; using Payment;
using Blog; using Blog;
using Yavsc.Abstract.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Yavsc.Server.Models.Calendar;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Yavsc.Abstract.Models.Messaging;
using Microsoft.Extensions.Logging;
using System.Configuration;
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{ {
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
@ -273,7 +273,7 @@ namespace Yavsc.Models
public DbSet<Scope> Scopes { get; set; } public DbSet<Scope> Scopes { get; set; }
public DbSet<BlogSpotPublication> blogSpotPublications{ get; set; } public DbSet<BlogSpotPublication> blogSpotPublications { get; set; }
// public DbSet<IdentityUserLogin<String>> AspNetUserLogins { get; set; } public DbSet<Client> Client { get; set; }
} }
} }

View File

@ -1,10 +1,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Util.Store; using Google.Apis.Util.Store;
using IdentityServer8; using IdentityServer8;
using IdentityServer8.Services;
using IdentityServerHost.Quickstart.UI;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
@ -18,14 +15,9 @@ using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using Newtonsoft.Json; using Newtonsoft.Json;
using Yavsc.Abstract.Workflow;
using Yavsc.Billing;
using Yavsc.Helpers; using Yavsc.Helpers;
using Yavsc.Interface; using Yavsc.Interface;
using Yavsc.Models; using Yavsc.Models;
using Yavsc.Models.Billing;
using Yavsc.Models.Haircut;
using Yavsc.Models.Workflow;
using Yavsc.Services; using Yavsc.Services;
using Yavsc.Settings; using Yavsc.Settings;
using Yavsc.ViewModels.Auth; using Yavsc.ViewModels.Auth;
@ -34,8 +26,6 @@ using System.Security.Cryptography;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Protocols.Configuration; using Microsoft.IdentityModel.Protocols.Configuration;
using IdentityModel; using IdentityModel;
using System.Security.Claims;
using IdentityServer8.Security;
using Yavsc.Interfaces; using Yavsc.Interfaces;
namespace Yavsc.Extensions; namespace Yavsc.Extensions;
@ -238,8 +228,9 @@ public static class HostingExtensions
options.EmitStaticAudienceClaim = true; options.EmitStaticAudienceClaim = true;
}) })
.AddInMemoryIdentityResources(Config.IdentityResources) .AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryClients(Config.Clients) .AddInMemoryClients(Config.TestingClients)
.AddInMemoryApiScopes(Config.ApiScopes) .AddClientStore<ClientStore>()
.AddInMemoryApiScopes(Config.TestingApiScopes)
.AddAspNetIdentity<ApplicationUser>() .AddAspNetIdentity<ApplicationUser>()
; ;
if (builder.Environment.IsDevelopment()) if (builder.Environment.IsDevelopment())

View File

@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore;
using Yavsc.Models;
using IdentityServer8.Stores;
using IdentityServer8.Models;
namespace Yavsc.Services;
public class ClientStore : IClientStore
{
public ClientStore(ApplicationDbContext applicationDbContext)
{
ApplicationDbContext = applicationDbContext;
}
public ApplicationDbContext ApplicationDbContext { get; }
public async Task<Client> FindClientByIdAsync(string clientId)
{
var clientFromDb = await ApplicationDbContext.Client.FirstAsync(c => c.Id == clientId);
return new Client
{
ClientId = clientFromDb.Id,
ClientName = clientFromDb.DisplayName,
ClientSecrets = { new Secret(clientFromDb.Secret.Sha256()) },
AllowedGrantTypes =[ GrantType.ClientCredentials, GrantType.DeviceFlow],
AllowedScopes = ["openid", "profile", "scope1"]
};
}
}

View File

@ -24,22 +24,20 @@ namespace yavscTests
[MemberData(nameof(GetLoginIntentData), parameters: 1)] [MemberData(nameof(GetLoginIntentData), parameters: 1)]
public async Task TestUserMayLogin public async Task TestUserMayLogin
( (
string clientId, string userName,
string clientSecret, string password
string scope,
string authorizeUrl,
string redirectUrl,
string accessTokenUrl
) )
{ {
try try
{ {
String auth = _serverFixture.SiteSettings.Authority;
var oauthor = new OAuthenticator(clientId, clientSecret, scope, var oauthor = new OAuthenticator(clientId, clientSecret, scope,
new Uri(authorizeUrl), new Uri(redirectUrl), new Uri(accessTokenUrl)); new Uri(authorizeUrl), new Uri(redirectUrl), new Uri(accessTokenUrl));
var query = new Dictionary<string, string> var query = new Dictionary<string, string>
{ {
["Username"] = _serverFixture.TestingSetup.ValidCreds.UserName, ["Username"] = userName,
["Password"] = _serverFixture.TestingSetup.ValidCreds.Password, ["Password"] = password,
["GrantType"] = "Password" ["GrantType"] = "Password"
}; };
@ -56,7 +54,7 @@ namespace yavscTests
var webex = ex as WebException; var webex = ex as WebException;
if (webex != null && webex.Status == (WebExceptionStatus)400) if (webex != null && webex.Status == (WebExceptionStatus)400)
{ {
if (_serverFixture.TestingSetup.ValidCreds.UserName == "lame-user") if (_serverFixture?.TestingSetup?.ValidCreds.UserName == "lame-user")
{ {
Console.WriteLine("Bad pass joe!"); Console.WriteLine("Bad pass joe!");
return; return;
@ -66,9 +64,17 @@ namespace yavscTests
} }
} }
public static IEnumerable<object[]> GetLoginIntentData(int count) public static IEnumerable<object[]> GetLoginIntentData(int countFakes = 0)
{ {
return new object[][] {new object[]{ "", "", "", "", "", "" } }; if (countFakes == 0)
return new object[][] { new object[] { "testuser", "test" } };
var fakUsers = new List<String[]>();
for (int i = 0; i < countFakes; i++)
{
fakUsers.Add(new String[] { "fakeTester" + i, "pass" + i });
}
return fakUsers;
} }
} }

View File

@ -121,7 +121,7 @@ namespace isnd.tests
EmailConfirmed = true EmailConfirmed = true
}; };
var result = userManager.CreateAsync(TestingUser).Result; var result = userManager.CreateAsync(TestingUser,"test").Result;
Assert.True(result.Succeeded); Assert.True(result.Succeeded);