diff --git a/global.json b/global.json
index 952b7d76..f2fb072c 100644
--- a/global.json
+++ b/global.json
@@ -1,12 +1,11 @@
{
"projects": [
"src",
- "scripts",
- "tests"
+ "test"
],
"sdk": {
"runtime": "dotnet",
- "architecture": "x64"
+ "version": "8.0.405"
},
"packages": "packages"
}
diff --git a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Create.cshtml b/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Create.cshtml
deleted file mode 100644
index d212ba9f..00000000
--- a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Create.cshtml
+++ /dev/null
@@ -1,145 +0,0 @@
-@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
-@using Microsoft.Extensions.CodeGeneration.EntityFramework
-@@model @Model.ViewDataTypeName
-
-@{
- if (Model.IsPartialView)
- {
- }
- else if (Model.IsLayoutPageSelected)
- {
-@:@@{
- @:ViewData["Title"] = @@Model.ViewName;
- if (!string.IsNullOrEmpty(Model.LayoutPageFile))
- {
- @:Layout = "@Model.LayoutPageFile";
- }
-@:}
-@:
-@:
@@Model.ViewName
-@:
- }
- else
- {
-@:@@{
- @:Layout = "null";
-@:}
-@:
-@:
-@:
-@:
-@:
- @:
- @:@Model.ViewName
-@:
-@:
-@:
- // PushIndent(" ");
- }
-@:
-
-
-
-@{
- if (Model.ReferenceScriptLibraries && (Model.IsLayoutPageSelected || Model.IsPartialView))
- {
-@:@@section Scripts {
- @:
- @:
- @:
-@:}
- }
- // The following code closes the tag used in the case of a view using a layout page and the body and html tags in the case of a regular view page
- if (!Model.IsPartialView && !Model.IsLayoutPageSelected)
- {
- if (Model.ReferenceScriptLibraries)
- {
-@:@@section Scripts {
- @:
- @:
- @:
-@:}
- //ClearIndent();
- }
-@:
-@:
- }
-}
-@functions
-{
- // Do we need to use this in conjunction with the PrimaryKey check?
- bool IsPropertyGuid(PropertyMetadata property)
- {
- return string.Equals("System.Guid", property.TypeName, StringComparison.OrdinalIgnoreCase);
- }
-}
diff --git a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Delete.cshtml b/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Delete.cshtml
deleted file mode 100644
index 1c2dab35..00000000
--- a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Delete.cshtml
+++ /dev/null
@@ -1,81 +0,0 @@
-@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
-@using Microsoft.Extensions.CodeGeneration.EntityFramework
-@@model @Model.ViewDataTypeName
-
-@{
- if (Model.IsPartialView)
- {
- }
- else if (Model.IsLayoutPageSelected)
- {
-@:@@{
- @:ViewData["Title"] = @@Model.ViewName;
- if (!string.IsNullOrEmpty(Model.LayoutPageFile))
- {
- @:Layout = "@Model.LayoutPageFile";
- }
-@:}
-@:
-@:@@Model.ViewName
-@:
- }
- else
- {
-@:@@{
- @:Layout = "null";
-@:}
-@:
-@:
-@:
-@:
-@:
- @:
- @:@@@Model.ViewName
-@:
-@:
-@:
- // PushIndent(" ");
- }
-}
-@AreYourSureYouWantToDeleteThis
-
-
@@@Model.ViewDataTypeShortName
-
-
-@{
- foreach (var property in Model.ModelMetadata.Properties)
- {
- if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
- {
- -
- @@Html.DisplayNameFor(model => model.@GetValueExpression(property))
-
- -
- @@Html.DisplayFor(model => model.@GetValueExpression(property))
-
- }
- }
- @:
- @:
- @:
-@:
- if (!Model.IsPartialView && !Model.IsLayoutPageSelected)
- {
- //ClearIndent();
-@:
-@:
- }
-}
-@functions
-{
- string GetValueExpression(PropertyMetadata property)
- {
- //Todo: Get the association for the property and use that.
- return property.PropertyName;
- }
-}
diff --git a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Details.cshtml b/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Details.cshtml
deleted file mode 100644
index 87e0bc5c..00000000
--- a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Details.cshtml
+++ /dev/null
@@ -1,95 +0,0 @@
-@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
-@using Microsoft.Extensions.CodeGeneration.EntityFramework
-@@model @Model.ViewDataTypeName
-
-@{
- if (Model.IsPartialView)
- {
- }
- else if (Model.IsLayoutPageSelected)
- {
-@:@@{
- @:ViewData["Title"] = @@Model.ViewName;
- if (!string.IsNullOrEmpty(Model.LayoutPageFile))
- {
- @:Layout = "@Model.LayoutPageFile";
- }
-@:}
-@:
-@:@@Model.ViewName
-@:
- }
- else
- {
-@:@@{
- @:Layout = "null";
-@:}
-@:
-@:
-@:
-@:
-@:
- @:
- @:@Model.ViewName
-@:
-@:
-@:
- // PushIndent(" ");
- }
-}
-
-
@Model.ViewDataTypeShortName
-
-
-@{
- foreach (var property in Model.ModelMetadata.Properties)
- {
- if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
- {
- -
- @@Html.DisplayNameFor(model => model.@GetValueExpression(property))
-
- -
- @@Html.DisplayFor(model => model.@GetValueExpression(property))
-
- }
- }
-}
-
-
-@{
- string pkName = GetPrimaryKeyName();
- if (pkName != null)
- {
- @:@Edit |
- @:Back to List
- }
- else
- {
- @:@@Html.ActionLink(@Edit, "Edit", new { /* id = Model.PrimaryKey */ }) |
- @:Back to List
- }
-}
-@{
- if (!Model.IsPartialView && !Model.IsLayoutPageSelected)
- {
- //ClearIndent();
-@:
-@:
- }
-}
-@functions
-{
- string GetPrimaryKeyName()
- {
- return (Model.ModelMetadata.PrimaryKeys != null && Model.ModelMetadata.PrimaryKeys.Length == 1)
- ? Model.ModelMetadata.PrimaryKeys[0].PropertyName
- : null;
- }
-
- string GetValueExpression(PropertyMetadata property)
- {
- //Todo: Get the association for the property and use that.
- return property.PropertyName;
- }
-}
diff --git a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Edit.cshtml b/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Edit.cshtml
deleted file mode 100644
index 6437586f..00000000
--- a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/Edit.cshtml
+++ /dev/null
@@ -1,149 +0,0 @@
-@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
-@using Microsoft.Extensions.CodeGeneration.EntityFramework
-@@model @Model.ViewDataTypeName
-
-@{
- if (Model.IsPartialView)
- {
- }
- else if (Model.IsLayoutPageSelected)
- {
-@:@@{
- @:ViewData["Title"] = @@Model.ViewName;
- if (!string.IsNullOrEmpty(Model.LayoutPageFile))
- {
- @:Layout = "@Model.LayoutPageFile";
- }
-@:}
-@:
-@:@@Model.ViewName
-@:
- }
- else
- {
-@:@@{
- @:Layout = "null";
-@:}
-@:
-@:
-@:
-@:
-@:
- @:
- @:@@Model.ViewName
-@:
-@:
-@:
- // PushIndent(" ");
- }
-@:
-
-
-
-@{
- if (Model.ReferenceScriptLibraries && (Model.IsLayoutPageSelected || Model.IsPartialView))
- {
-@:@@section Scripts {
- @:
- @:
- @:
-@:}
- }
- // The following code closes the tag used in the case of a view using a layout page and the body and html tags in the case of a regular view page
- if (!Model.IsPartialView && !Model.IsLayoutPageSelected)
- {
- if (Model.ReferenceScriptLibraries)
- {
-@:@@section Scripts {
- @:
- @:
- @:
-@:}
- //ClearIndent();
- }
-@:
-@:
- }
-}
-@functions
-{
- string GetAssociationName(PropertyMetadata property)
- {
- //Todo: Implement properly.
- return property.PropertyName;
- }
-}
diff --git a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/List.cshtml b/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/List.cshtml
deleted file mode 100644
index a2e66ae2..00000000
--- a/scripts/configure/tools/mvc-code-generators/new-templates/ViewGenerator/List.cshtml
+++ /dev/null
@@ -1,115 +0,0 @@
-@inherits Microsoft.Extensions.CodeGeneration.Templating.RazorTemplateBase
-@using Microsoft.Extensions.CodeGeneration.EntityFramework
-@@model @GetEnumerableTypeExpression(Model.ViewDataTypeName)
-
-@{
- if (Model.IsPartialView)
- {
- }
- else if (Model.IsLayoutPageSelected)
- {
-@:@@{
- @:ViewData["Title"] = @@Model.ViewName;
- if (!string.IsNullOrEmpty(Model.LayoutPageFile))
- {
- @:Layout = "@Model.LayoutPageFile";
- }
-@:}
-@:
-@:@@Model.ViewName
-@:
- }
- else
- {
-@:@@{
- @:Layout = "null";
-@:}
-@:
-@:
-@:
-@:
-@:
- @:
- @:@@Model.ViewName
-@:
-@:
- // PushIndent(" ");
- }
-@:
- @:Create New
-@:
-@:
- @:
- IEnumerable properties = Model.ModelMetadata.Properties;
- foreach (var property in properties)
- {
- if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
- {
- |
- @@Html.DisplayNameFor(model => model.@GetValueExpression(property))
- |
- }
- }
- @: |
- @:
- @:
-@:@@foreach (var item in Model) {
- @:
- foreach (PropertyMetadata property in properties)
- {
- if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
- {
- |
- @@Html.DisplayFor(modelItem => item.@GetValueExpression(property))
- |
- }
- }
-
- string pkName = GetPrimaryKeyName();
- if (pkName != null)
- {
- @:
- @:@Edit |
- @:@Details |
- @:@Delete
- @: |
- }
- else
- {
-
- @@Html.ActionLink("Edit", "Edit",new { /* id=item.PrimaryKey */ }) |
- @@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
- @@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
- |
- }
- @:
-@:}
-
-@:
- if(!Model.IsPartialView && !Model.IsLayoutPageSelected)
- {
- //ClearIndent();
-@:
-@:
- }
-}
-@functions
-{
- string GetPrimaryKeyName()
- {
- return (Model.ModelMetadata.PrimaryKeys != null && Model.ModelMetadata.PrimaryKeys.Length == 1)
- ? Model.ModelMetadata.PrimaryKeys[0].PropertyName
- : null;
- }
-
- string GetValueExpression(PropertyMetadata property)
- {
- //Todo: Get the association for the property and use that.
- return property.PropertyName;
- }
-
- string GetEnumerableTypeExpression(string typeName)
- {
- return "IEnumerable<" + typeName + ">";
- }
-}
diff --git a/scripts/make/Makefile b/scripts/make/Makefile
deleted file mode 100644
index 76584c73..00000000
--- a/scripts/make/Makefile
+++ /dev/null
@@ -1,78 +0,0 @@
-include versioning.mk
-
-
-REPO_ROOT=../../../src
-
-SUBDIRS=Yavsc Yavsc.Server Yavsc.Abstract OAuth.AspNet.AuthServer OAuth.AspNet.Token cli test
-
-all: $(SUBDIRS)
-
-Yavsc.Abstract:
- $(MAKE) -C $(REPO_ROOT)/Yavsc.Abstract VERSION=$(VERSION)
-
-OAuth.AspNet.Token:
- $(MAKE) -C $(REPO_ROOT)/OAuth.AspNet.Token VERSION=$(VERSION)
-
-OAuth.AspNet.AuthServer: OAuth.AspNet.Token
- $(MAKE) -C $(REPO_ROOT)/OAuth.AspNet.AuthServer VERSION=$(VERSION)
-
-Yavsc.Server: Yavsc.Abstract
- $(MAKE) -C $(REPO_ROOT)/Yavsc.Server VERSION=$(VERSION)
-
-Yavsc: Yavsc.Server OAuth.AspNet.AuthServer OAuth.AspNet.Token
- make -C $(REPO_ROOT)/Yavsc VERSION=$(VERSION)
-
-Yavsc-deploy-pkg: Yavsc
- make -C $(REPO_ROOT)/Yavsc deploy-pkg
-
-Yavsc.Server-deploy-pkg: Yavsc.Server
- make -C $(REPO_ROOT)/Yavsc.Server deploy-pkg
-
-Yavsc.Abstract-deploy-pkg: Yavsc.Abstract
- make -C $(REPO_ROOT)/Yavsc.Abstract deploy-pkg
-
-cli-deploy-pkg: cli check
- make -C $(REPO_ROOT)/cli deploy-pkg
-
-cli: Yavsc-deploy-pkg Yavsc.Server-deploy-pkg Yavsc.Abstract-deploy-pkg
- make -C $(REPO_ROOT)/cli
-
-undoLocalYavscNugetDeploy:
- rm -rf ../../../packages/Yavsc.Abstract
- rm -rf ../../../packages/Yavsc.Server
- rm -rf ../../../packages/Yavsc
- rm -rf ~/.dnx/packages/Yavsc.Abstract
- rm -rf ~/.dnx/packages/Yavsc.Server
- rm -rf ~/.dnx/packages/Yavsc
-
-check: cli
- make -C $(REPO_ROOT)/cli check
- make -C $(REPO_ROOT)/test
-
-test:
- make -C $(REPO_ROOT)/test
-
-pushInPre:
- make -C $(REPO_ROOT)/Yavsc pushInPre
-
-pushInProd:
- make -C $(REPO_ROOT)/Yavsc pushInProd
-
-deploy-pkgs: Yavsc-deploy-pkg Yavsc.Server-deploy-pkg Yavsc.Abstract-deploy-pkg cli-deploy-pkg
-
-memo:
- vim ~/TODO.md
-
-rc-num:
- @echo echo 1-alpha1 < $< ^ $^ @ $@
-
-clean:
- for subdir in $(SUBDIRS) ; do \
- make -C $(REPO_ROOT)/$${subdir} clean ; \
- done
-
-watch:
- make -C $(REPO_ROOT)/Yavsc watch
-
-.PHONY: all $(SUBDIRS)
-
diff --git a/scripts/make/dnx.mk b/scripts/make/dnx.mk
deleted file mode 100644
index 9a5a8a58..00000000
--- a/scripts/make/dnx.mk
+++ /dev/null
@@ -1,71 +0,0 @@
-# Common defs
-#
-
-ifndef PRJNAME
-PRJNAME := $(shell basename `pwd -P`)
-endif
-FRAMEWORK=dnx451
-ASPNET_ENV=Development
-ASPNET_LOG_LEVEL=Debug
-HOSTING=localhost
-HOSTADMIN=root
-FRAMEWORKALIAS=dnx451
-# nuget package destination, at generation time
-BINTARGET=$(PRJNAME).dll
-BINTARGETPATH=bin/$(CONFIGURATION)/$(FRAMEWORKALIAS)/$(BINTARGET)
-PKGFILENAME=$(PRJNAME).$(VERSION).nupkg
-dnu=dnu
-
-# OBS SUBDIRS=Yavsc.Server Yavsc.Abstract Yavsc cli
-#
-
-# Git commit hash, in order to not publish some uncrontrolled code in production environment
-#
-
-git_status := $(shell git status -s --porcelain |wc -l)
-
-all: $(BINTARGETPATH)
-
-fixSystemXML:
- @# fixing package id reference case, to System.Xml, from package NJsonSchema.CodeGeneration.CSharp
- @sed 's/System.XML/System.Xml/' project.lock.json > project.lock.json.new && mv project.lock.json.new project.lock.json
-
-restore:
- touch project.json
- $(dnu) restore --ignore-failed-sources
-
-project.lock.json: project.json
- $(dnu) restore --ignore-failed-sources
-
-watch: project.lock.json
- MONO_OPTIONS=--debug MONO_MANAGED_WATCHER=enabled ASPNET_ENV=$(ASPNET_ENV) ASPNET_LOG_LEVEL=$(ASPNET_LOG_LEVEL) dnx-watch web --configuration=$(CONFIGURATION)
-
-clean:
- rm -rf bin obj
- rm project.lock.json
-
-cleanoutput:
- rm -rf bin/$(CONFIGURATION)
- rm -rf bin/output
-
-$(BINTARGETPATH): project.lock.json rc-num.txt-check
- $(dnu) build --configuration=$(CONFIGURATION)
-
-# Default target, from one level sub dirs
-
-bin/output:
- $(dnu) publish
-
-bin/output/wwwroot/version: bin/output
- @echo $(version) > bin/output/wwwroot/version
-
-pack: $(BINTARGETPATH) ../../version.txt
- dnu pack --configuration $(CONFIGURATION)
-
-push: pack
- @echo push to source: $(ISNSOURCE)
- isn push -s $(ISNSOURCE) -k $(NUGETSOURCEAPIKEY) src/$(PRJNAME)/bin/$(CONFIGURATION)/$(PRJNAME).*.nupkg
-
-.PHONY: rc-num.txt-check
-
-# .DEFAULT_GOAL := $(BINTARGETPATH)
diff --git a/scripts/make/msbuild.mk b/scripts/make/msbuild.mk
deleted file mode 100644
index d6d260f8..00000000
--- a/scripts/make/msbuild.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-MSBUILD=msbuild
-MONO=mono
-CONFIGURATION=Debug
-BINTYPE=exe
-PRJNAME := $(shell basename `pwd -P`)
-
-rc_num := $(shell cat ../../rc-num.txt)
-VERSION=1.0.5-rc$(rc_num)
-
-BINTARGET=$(PRJNAME).$(BINTYPE)
-BINTARGETPATH=bin/$(CONFIGURATION)/$(BINTARGET)
-ISNSOURCE=$(HOME)/Nupkgs
-PKGFILENAME=$(PRJNAME).$(VERSION).nupkg
-
diff --git a/scripts/make/versioning.mk b/scripts/make/versioning.mk
deleted file mode 100644
index 2adc45d2..00000000
--- a/scripts/make/versioning.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-
-ifndef PRJNAME
-PRJNAME := $(shell basename `pwd -P`)
-endif
-version := $(shell cat ../../version.txt)
-MAKE=make
-ISNSOURCE=$(HOME)/Nupkgs
-VERSION=$(version)
-CONFIGURATION=Debug
-
-version-check:
-ifndef version
- @echo no version number specification ... please, could you try and run 'echo 1.2.3 > ../../version.txt' ?.
-else
- @echo 'Got version number : $(version)'
-endif
diff --git a/scripts/version.sh b/scripts/version.sh
deleted file mode 100755
index f6e09210..00000000
--- a/scripts/version.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/bash
-
-version="$1"
-major=0
-minor=0
-build=0
-
-# break down the version number into it's components
-regex="([0-9]+).([0-9]+).([0-9]+)((-[A-Za-z]+)([0-9]+))?"
-if [[ $version =~ $regex ]]; then
- major="${BASH_REMATCH[1]}"
- minor="${BASH_REMATCH[2]}"
- build="${BASH_REMATCH[3]}"
- patchtype="${BASH_REMATCH[5]}"
- patchnum="${BASH_REMATCH[6]}"
-fi
-
-# check paramater to see which number to increment
-if [[ "$2" == "feature" ]]; then
- minor=$(echo $minor + 1 | bc)
- build=0
- patchtype=
- patchnum=
-elif [[ "$2" == "build" ]]; then
- build=$(echo $build + 1 | bc)
- patchtype=
- patchnum=
-elif [[ "$2" == "major" ]]; then
- major=$(echo $major+1 | bc)
- minor=0
- build=0
- patchtype=
- patchnum=
-elif [[ "$2" == "patch" ]]; then
- patchnum=$(echo $patchnum + 1 | bc)
-else
- echo "usage: ./version.sh version_number [major/feature/build/patch]" >&2
-
- exit -1
-fi
-
-# echo the new version number
-echo "${major}.${minor}.${build}${patchtype}${patchnum}"
-
diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj
new file mode 100644
index 00000000..a04a493f
--- /dev/null
+++ b/src/Api/Api.csproj
@@ -0,0 +1,10 @@
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
diff --git a/src/Api/Program.cs b/src/Api/Program.cs
new file mode 100644
index 00000000..9daf30a5
--- /dev/null
+++ b/src/Api/Program.cs
@@ -0,0 +1,77 @@
+/*
+ Copyright (c) 2024 HigginsSoft, Alexander Higgins - https://github.com/alexhiggins732/
+
+ Copyright (c) 2018, Brock Allen & Dominick Baier. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
+ Source code and license this software can be found
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+*/
+
+using Microsoft.AspNetCore.Mvc;
+
+internal class Program
+{
+ private static async Task Main(string[] args)
+ {
+ Console.Title = "API";
+
+ var builder = WebApplication.CreateBuilder(args);
+
+ var services = builder.Services;
+
+ // accepts any access token issued by identity server
+ // adds an authorization policy for scope 'api1'
+ services
+ .AddAuthorization(options =>
+ {
+ options.AddPolicy("ApiScope", policy =>
+ {
+ policy
+ .RequireAuthenticatedUser()
+ .RequireClaim("scope", "scope2");
+ });
+ })
+ .AddCors(options =>
+ {
+ // this defines a CORS policy called "default"
+ options.AddPolicy("default", policy =>
+ {
+ policy.WithOrigins("https://localhost:5003")
+ .AllowAnyHeader()
+ .AllowAnyMethod();
+ });
+ })
+ .AddControllers();
+
+ // accepts any access token issued by identity server
+ var authenticationBuilder = services.AddAuthentication()
+ .AddJwtBearer("Bearer", options =>
+ {
+ options.IncludeErrorDetails = true;
+ options.Authority = "https://localhost:5001";
+ options.TokenValidationParameters =
+ new() { ValidateAudience = false };
+ });
+
+ using (var app = builder.Build())
+ {
+ if (app.Environment.IsDevelopment())
+ app.UseDeveloperExceptionPage();
+
+ app
+ .UseRouting()
+ .UseAuthentication()
+ .UseAuthorization()
+ .UseCors("default");
+
+ app.MapGet("/identity", (HttpContext context) =>
+ new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value }))
+ ).RequireAuthorization("ApiScope");
+
+ await app.RunAsync();
+ }
+ }
+}
diff --git a/src/Api/appsettings.json b/src/Api/appsettings.json
new file mode 100644
index 00000000..d9d9a9bf
--- /dev/null
+++ b/src/Api/appsettings.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft": "Warning",
+ "Microsoft.Hosting.Lifetime": "Information"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Yavsc/Config.cs b/src/Yavsc/Config.cs
index 05be8631..68d95685 100644
--- a/src/Yavsc/Config.cs
+++ b/src/Yavsc/Config.cs
@@ -77,10 +77,12 @@ public static class Config
PostLogoutRedirectUris = { "https://localhost:5003/signout-callback-oidc" },
AllowOfflineAccess = true,
+
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
+ IdentityServerConstants.StandardScopes.OfflineAccess,
"scope2" }
},
};
diff --git a/src/Yavsc/Extensions/HostingExtensions.cs b/src/Yavsc/Extensions/HostingExtensions.cs
index 9520711e..50087ac7 100644
--- a/src/Yavsc/Extensions/HostingExtensions.cs
+++ b/src/Yavsc/Extensions/HostingExtensions.cs
@@ -2,6 +2,7 @@ using System.Globalization;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Util.Store;
using IdentityServer8;
+using IdentityServer8.Hosting;
using IdentityServer8.Services;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
@@ -187,8 +188,9 @@ internal static class HostingExtensions
.AddInMemoryClients(Config.Clients)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddAspNetIdentity()
+ .AddJwtBearerClientAuthentication()
;
- services.AddScoped();
+ //services.AddScoped();
if (builder.Environment.IsDevelopment())
{
@@ -207,7 +209,15 @@ internal static class HostingExtensions
// TODO .AddServerSideSessionStore()
- var authenticationBuilder = services.AddAuthentication();
+
+ var authenticationBuilder = services.AddAuthentication()
+ .AddJwtBearer("Bearer", options =>
+ {
+ options.IncludeErrorDetails=true;
+ options.Authority = "https://localhost:5001";
+ options.TokenValidationParameters =
+ new() { ValidateAudience = false };
+ });
authenticationBuilder.AddGoogle(options =>
{
@@ -251,13 +261,7 @@ internal static class HostingExtensions
};
});
- services.AddCors(options =>
- {
- options.AddPolicy("CorsPolicy", builder =>
- {
- _ = builder.WithOrigins("*");
- });
- });
+
// Add the system clock service
@@ -313,10 +317,10 @@ internal static class HostingExtensions
services.AddAuthorization(options =>
{
options.AddPolicy("ApiScope", policy =>
- {
- policy.RequireAuthenticatedUser()
- .RequireClaim("scope", "scope2");
- });
+ {
+ policy.RequireAuthenticatedUser()
+ .RequireClaim("scope", "scope2");
+ });
options.AddPolicy("Performer", policy =>
{
policy
@@ -334,11 +338,29 @@ internal static class HostingExtensions
// options.AddPolicy("BuildingEntry", policy => policy.Requirements.Add(new OfficeEntryRequirement()));
options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
options.AddPolicy("IsTheAuthor", policy => policy.Requirements.Add(new EditPermission()));
+ })
+ .AddCors(options =>
+ {
+ options.AddPolicy("CorsPolicy", builder =>
+ {
+ _ = builder.WithOrigins("*")
+ .AllowAnyHeader()
+ .AllowAnyMethod();
+ });
+
+ options.AddPolicy("default", policy =>
+ {
+ policy.WithOrigins("https://localhost:5003")
+ .AllowAnyHeader()
+ .AllowAnyMethod();
+ });
});
services.AddSingleton();
+// accepts any access token issued by identity server
+
return builder.Build();
}
public static WebApplication ConfigurePipeline(this WebApplication app)
@@ -357,9 +379,6 @@ internal static class HostingExtensions
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
- app.MapGet("/api/me", (HttpContext context) =>
- new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value }))
- ).RequireAuthorization("ApiScope");
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
diff --git a/src/Yavsc/Services/ProfileService.cs b/src/Yavsc/Services/ProfileService.cs
index d58e982d..e6160744 100644
--- a/src/Yavsc/Services/ProfileService.cs
+++ b/src/Yavsc/Services/ProfileService.cs
@@ -8,11 +8,11 @@ using Yavsc.Models;
namespace Yavsc.Services
{
- public class ProfileService : IProfileService
+ public class ProfileService : DefaultProfileService, IProfileService
{
private readonly UserManager _userManager;
public ProfileService(
- UserManager userManager)
+ UserManager userManager, ILogger logger) : base(logger)
{
_userManager = userManager;
}
@@ -21,50 +21,56 @@ namespace Yavsc.Services
ProfileDataRequestContext context,
ApplicationUser user)
{
+ var requestedApiResources = context.RequestedResources.Resources.ApiResources.Select(
+ r => r.Name
+ ).ToArray();
+ var requestedApiScopes = context.RequestedResources.Resources.ApiScopes.Select(
+ s => s.Name
+ ).ToArray();
- var allowedScopes = context.Client.AllowedScopes
- .Where(s => s != JwtClaimTypes.Subject)
+ var requestedScopes = context.Client.AllowedScopes
+ .Where(s => s != JwtClaimTypes.Subject
+ && requestedApiScopes.Contains(s))
.ToList();
- if (allowedScopes.Contains("profile"))
+
+ if (context.RequestedClaimTypes.Contains("profile"))
+ if (requestedScopes.Contains("profile"))
{
- allowedScopes.Remove("profile");
- allowedScopes.Add(JwtClaimTypes.Name);
- allowedScopes.Add(JwtClaimTypes.FamilyName);
- allowedScopes.Add(JwtClaimTypes.Email);
- allowedScopes.Add(JwtClaimTypes.PreferredUserName);
- allowedScopes.Add("http://schemas.microsoft.com/ws/2008/06/identity/claims/role");
+ requestedScopes.Remove("profile");
+ requestedScopes.Add(JwtClaimTypes.Name);
+ requestedScopes.Add(JwtClaimTypes.FamilyName);
+ requestedScopes.Add(JwtClaimTypes.Email);
+ requestedScopes.Add(JwtClaimTypes.PreferredUserName);
+ requestedScopes.Add(JwtClaimTypes.Role);
}
var claims = new List {
new Claim(JwtClaimTypes.Subject,user.Id.ToString()),
};
-
- foreach (var subClaim in context.Subject.Claims)
+ if (requestedScopes.Contains(JwtClaimTypes.Name)||
+ requestedScopes.Contains(JwtClaimTypes.FamilyName))
{
- if (allowedScopes.Contains(subClaim.Type))
- claims.Add(subClaim);
+ claims.Add(new Claim(JwtClaimTypes.Name, user.FullName));
}
- AddClaims(allowedScopes, claims, JwtClaimTypes.Email, user.Email);
- AddClaims(allowedScopes, claims, JwtClaimTypes.PreferredUserName, user.FullName);
-
- foreach (var scope in context.Client.AllowedScopes)
+ if (requestedScopes.Contains(JwtClaimTypes.PreferredUserName) )
{
- claims.Add(new Claim("scope", scope));
+ claims.Add(new Claim(JwtClaimTypes.Name, user.UserName));
+ }
+ if (requestedScopes.Contains(JwtClaimTypes.Email))
+ claims.Add(new Claim(JwtClaimTypes.Email, user.Email));
+
+ if (requestedScopes.Contains(JwtClaimTypes.Role))
+ {
+ var roles = await this._userManager.GetRolesAsync(user);
+ if (roles.Count()>0)
+ {
+ claims.Add(new Claim(JwtClaimTypes.Role,String.Join(" ",roles)));
+ }
}
-
return claims;
}
- private static void AddClaims(List allowedScopes, List claims,
- string claimType, string claimValue
- )
- {
- if (allowedScopes.Contains(claimType))
- if (!claims.Any(c => c.Type == claimType))
- claims.Add(new Claim(claimType, claimValue));
- }
-
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
@@ -72,7 +78,6 @@ namespace Yavsc.Services
context.IssuedClaims = await GetClaimsFromUserAsync(context, user);
}
-
public async Task IsActiveAsync(IsActiveContext context)
{
var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
diff --git a/src/sampleWebAsWebApiClient/Controllers/HomeController.cs b/src/sampleWebAsWebApiClient/Controllers/HomeController.cs
index de6b72f3..8dcd1bab 100755
--- a/src/sampleWebAsWebApiClient/Controllers/HomeController.cs
+++ b/src/sampleWebAsWebApiClient/Controllers/HomeController.cs
@@ -54,14 +54,31 @@ namespace testOauthClient.Controllers
public async Task GetUserInfo(CancellationToken cancellationToken)
{
var accessToken = await HttpContext.GetTokenAsync("access_token");
- var client = new HttpClient();
- client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+ var client = new HttpClient(new HttpClientHandler(){ AllowAutoRedirect=false });
client.DefaultRequestHeaders.Add("Accept", "application/json");
- var content = await client.GetStringAsync("https://localhost:5001/api/account/me");
- var obj = JsonSerializer.Deserialize(content);
+ client.SetBearerToken(accessToken);
+ var content = await client.GetAsync("https://localhost:5001/api/account/me");
+ content.EnsureSuccessStatusCode();
+ var json = await content.Content.ReadAsStreamAsync();
+ var obj = JsonSerializer.Deserialize(json);
return View("UserInfo", obj.ToString());
}
+ [HttpPost]
+ public async Task GetApiCall(CancellationToken cancellationToken)
+ {
+ var accessToken = await HttpContext.GetTokenAsync("access_token");
+ var client = new HttpClient(new HttpClientHandler(){ AllowAutoRedirect=false });
+ client.DefaultRequestHeaders.Add("Accept", "application/json");
+ client.SetBearerToken(accessToken);
+ var content = await client.GetAsync("https://localhost:6001/identity");
+ content.EnsureSuccessStatusCode();
+ var json = await content.Content.ReadAsStreamAsync();
+ var obj = JsonSerializer.Deserialize(json);
+ return View("UserInfo", obj.ToString());
+ }
+
+
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
diff --git a/src/sampleWebAsWebApiClient/Properties/launchSettings.json b/src/sampleWebAsWebApiClient/Properties/launchSettings.json
index 9add1af2..e12a4be3 100644
--- a/src/sampleWebAsWebApiClient/Properties/launchSettings.json
+++ b/src/sampleWebAsWebApiClient/Properties/launchSettings.json
@@ -4,8 +4,8 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
- "applicationUrl": "http://localhost:16967",
- "sslPort": 44387
+ "applicationUrl": "http://localhost:5002",
+ "sslPort": 5003
}
},
"profiles": {
@@ -13,7 +13,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
- "applicationUrl": "http://localhost:5164",
+ "applicationUrl": "http://localhost:5002",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@@ -22,7 +22,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
- "applicationUrl": "https://localhost:7055;http://localhost:5164",
+ "applicationUrl": "https://localhost:5003;http://localhost:5002",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/src/sampleWebAsWebApiClient/Startup.cs b/src/sampleWebAsWebApiClient/Startup.cs
index 176c7ea6..161e5a20 100644
--- a/src/sampleWebAsWebApiClient/Startup.cs
+++ b/src/sampleWebAsWebApiClient/Startup.cs
@@ -23,7 +23,6 @@ public class Startup
.AddOpenIdConnect("Yavsc", options =>
{
options.Authority = "https://localhost:5001";
-
options.ClientId = "mvc";
options.ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0";
options.ResponseType = "code";
@@ -32,6 +31,8 @@ public class Startup
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
+ options.Scope.Add("offline_access");
+ options.Scope.Add("scope2");
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
@@ -44,6 +45,7 @@ public class Startup
NameClaimType = "name",
RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
};
+
});
}
diff --git a/src/sampleWebAsWebApiClient/Views/Home/Index.cshtml b/src/sampleWebAsWebApiClient/Views/Home/Index.cshtml
index ba2d5ffc..7899726a 100755
--- a/src/sampleWebAsWebApiClient/Views/Home/Index.cshtml
+++ b/src/sampleWebAsWebApiClient/Views/Home/Index.cshtml
@@ -21,6 +21,11 @@
+
+
+
diff --git a/src/sampleWebAsWebApiClient/sampleWebAsWebApiClient.csproj b/src/sampleWebAsWebApiClient/sampleWebAsWebApiClient.csproj
index 0ca278ef..54e29a22 100644
--- a/src/sampleWebAsWebApiClient/sampleWebAsWebApiClient.csproj
+++ b/src/sampleWebAsWebApiClient/sampleWebAsWebApiClient.csproj
@@ -1,7 +1,8 @@
-
+
+
@@ -10,6 +11,7 @@
PreserveNewest
+
net8.0
enable
diff --git a/yavsc.sln b/yavsc.sln
index 6aeb11cb..a110375d 100644
--- a/yavsc.sln
+++ b/yavsc.sln
@@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yavsc", "src\Yavsc\Yavsc.cs
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sampleWebAsWebApiClient", "src\sampleWebAsWebApiClient\sampleWebAsWebApiClient.csproj", "{38AA74FE-3932-49C3-A382-338E7C861BB1}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Api", "src\Api\Api.csproj", "{16CCC793-BF57-4E8B-9BB5-76283379BA3F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -40,11 +42,16 @@ Global
{38AA74FE-3932-49C3-A382-338E7C861BB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38AA74FE-3932-49C3-A382-338E7C861BB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38AA74FE-3932-49C3-A382-338E7C861BB1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {16CCC793-BF57-4E8B-9BB5-76283379BA3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {16CCC793-BF57-4E8B-9BB5-76283379BA3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {16CCC793-BF57-4E8B-9BB5-76283379BA3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {16CCC793-BF57-4E8B-9BB5-76283379BA3F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5AFB6255-CF1B-4660-BB35-F24C8C75FECE} = {503DDD6B-BE10-4235-9EBD-E9B1FA6067DF}
{830F5A71-0192-4288-9F4D-D7849D958970} = {503DDD6B-BE10-4235-9EBD-E9B1FA6067DF}
{87DABC88-C38C-45DB-8F72-53B7C95ABC89} = {503DDD6B-BE10-4235-9EBD-E9B1FA6067DF}
{38AA74FE-3932-49C3-A382-338E7C861BB1} = {503DDD6B-BE10-4235-9EBD-E9B1FA6067DF}
+ {16CCC793-BF57-4E8B-9BB5-76283379BA3F} = {503DDD6B-BE10-4235-9EBD-E9B1FA6067DF}
EndGlobalSection
EndGlobal