Commit 862349c5 authored by alan.f's avatar alan.f

Add project files.

parents
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- Backup*.rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using System.Net.Http;
using System.Threading.Tasks;
namespace Api.AuthRequirement
{
public class JwtRequirement : IAuthorizationRequirement { }
public class JwtRequirementHandler : AuthorizationHandler<JwtRequirement>
{
private readonly HttpClient _client;
private readonly HttpContext _httpContext;
public JwtRequirementHandler(
IHttpClientFactory httpClientFactory,
IHttpContextAccessor httpContextAccessor)
{
_client = httpClientFactory.CreateClient();
_httpContext = httpContextAccessor.HttpContext;
}
protected override async Task HandleRequirementAsync(
AuthorizationHandlerContext context,
JwtRequirement requirement)
{
if (_httpContext.Request.Headers.TryGetValue("Authorization", out var authHeader))
{
var accessToken = authHeader.ToString().Split(' ')[1];
var response = await _client
.GetAsync($"https://localhost:44382/oauth/validate?access_token={accessToken}");
if(response.StatusCode == System.Net.HttpStatusCode.OK)
{
context.Succeed(requirement);
}
}
}
}
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Api.Controllers
{
public class SecretController : Controller
{
[Authorize]
public string Index()
{
return "secret message";
}
}
}
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
namespace Api
{
public class CustomeAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public CustomeAuthenticationHandler(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock) { }
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
return Task.FromResult(AuthenticateResult.Fail("Failed Authentication"));
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Api
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:54609",
"sslPort": 44332
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Api": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
using Api.AuthRequirement;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Api
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("DefaultAuth")
.AddScheme<AuthenticationSchemeOptions, CustomeAuthenticationHandler>("DefaultAuth", null);
services.AddAuthorization(config =>
{
var defaultAuthBuilder = new AuthorizationPolicyBuilder();
var defaultAuthPolicy = defaultAuthBuilder
.AddRequirements(new JwtRequirement())
.Build();
config.DefaultPolicy = defaultAuthPolicy;
});
services.AddScoped<IAuthorizationHandler, JwtRequirementHandler>();
services.AddHttpClient()
.AddHttpContextAccessor();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0" />
</ItemGroup>
</Project>
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
namespace ApiOne.Controllers
{
public class SecretController : Controller
{
[Route("/secret")]
[Authorize]
public string Index()
{
var claims = User.Claims.ToList();
return "secret message from ApiOne";
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace ApiOne
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59871",
"sslPort": 44337
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ApiOne": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://192.168.1.107:5003;http://192.168.1.107:5002",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ApiOne
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", config =>
{
config.Authority = "http://192.168.1.107:5000/";
config.Audience = "ApiOne";
config.RequireHttpsMetadata = false;
});
services.AddCors(confg =>
confg.AddPolicy("AllowAll",
p => p.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()));
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("AllowAll");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IdentityModel" Version="4.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0" />
</ItemGroup>
</Project>
using IdentityModel.Client;
using Microsoft.AspNetCore.Mvc;
using System.Net.Http;
using System.Threading.Tasks;
namespace ApiTwo.Controllers
{
public class HomeController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;
public HomeController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[Route("/home")]
public async Task<IActionResult> Index()
{
//retrieve access token
var serverClient = _httpClientFactory.CreateClient();
var discoveryDocument = await serverClient.GetDiscoveryDocumentAsync("https://localhost:44305/");
var tokenResponse = await serverClient.RequestClientCredentialsTokenAsync(
new ClientCredentialsTokenRequest
{
Address = discoveryDocument.TokenEndpoint,
ClientId = "client_id",
ClientSecret = "client_secret",
Scope = "ApiOne",
});
//retrieve secret data
var apiClient = _httpClientFactory.CreateClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);
var response = await apiClient.GetAsync("https://localhost:44337/secret");
var content = await response.Content.ReadAsStringAsync();
return Ok(new
{
access_token = tokenResponse.AccessToken,
message = content,
});
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace ApiTwo
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:59902",
"sslPort": 44316
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"ApiTwo": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ApiTwo
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", config => {
config.Authority = "https://localhost:44305/";
config.Audience = "ApiTwo";
});
services.AddHttpClient();
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29324.140
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Basics", "Basics\Basics.csproj", "{CB8DA3CE-CF95-4547-9DDE-A7A4102A3130}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityExample", "IdentityExample\IdentityExample.csproj", "{BD528B93-CC27-46DB-80FA-DC9BF617E820}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "basic", "basic", "{7543969E-0B5E-40EA-B9FC-7E22857D7B5D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "oauth", "oauth", "{85A8A5DC-9E6A-4694-9919-767DC72BC960}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{EBC70960-000B-4F1F-A41F-52A91AEAF6E6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{4707EDF0-4DB1-473B-9435-5FEBDA1042B3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Api", "Api\Api.csproj", "{A51D18DA-8122-44E1-867B-1251C088832A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identityserver4", "identityserver4", "{9D8AD979-7C11-45DF-AA44-FDE88CA65FF4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityServer", "IdentityServer\IdentityServer.csproj", "{BD1A1261-3980-48F9-9F9F-EEE214B97728}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiOne", "ApiOne\ApiOne.csproj", "{7EEF41C6-A90F-47F2-8BC8-91D1C3F966FE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiTwo", "ApiTwo\ApiTwo.csproj", "{89877242-92A7-419E-9DC6-ED18C40DA704}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MvcClient", "MvcClient\MvcClient.csproj", "{DECF9AE7-E0AE-485E-8FF4-ED3276A785F5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JavascriptClient", "JavascriptClient\JavascriptClient.csproj", "{29A7FDE8-6760-4796-82AE-00FBA7B1C0B4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfApp", "WpfApp\WpfApp.csproj", "{FCC518A9-909C-4F86-9DD0-C16C0ED67B68}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamarinApp.Android", "XamarinApp\XamarinApp.Android\XamarinApp.Android.csproj", "{6DFCB525-A543-46D2-B7AF-761B7E5AF160}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamarinApp", "XamarinApp\XamarinApp\XamarinApp.csproj", "{A32ACF58-7FD4-4DD5-BF46-78597D93CEE2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CB8DA3CE-CF95-4547-9DDE-A7A4102A3130}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB8DA3CE-CF95-4547-9DDE-A7A4102A3130}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB8DA3CE-CF95-4547-9DDE-A7A4102A3130}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB8DA3CE-CF95-4547-9DDE-A7A4102A3130}.Release|Any CPU.Build.0 = Release|Any CPU
{BD528B93-CC27-46DB-80FA-DC9BF617E820}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD528B93-CC27-46DB-80FA-DC9BF617E820}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD528B93-CC27-46DB-80FA-DC9BF617E820}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD528B93-CC27-46DB-80FA-DC9BF617E820}.Release|Any CPU.Build.0 = Release|Any CPU
{EBC70960-000B-4F1F-A41F-52A91AEAF6E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBC70960-000B-4F1F-A41F-52A91AEAF6E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBC70960-000B-4F1F-A41F-52A91AEAF6E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBC70960-000B-4F1F-A41F-52A91AEAF6E6}.Release|Any CPU.Build.0 = Release|Any CPU
{4707EDF0-4DB1-473B-9435-5FEBDA1042B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4707EDF0-4DB1-473B-9435-5FEBDA1042B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4707EDF0-4DB1-473B-9435-5FEBDA1042B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4707EDF0-4DB1-473B-9435-5FEBDA1042B3}.Release|Any CPU.Build.0 = Release|Any CPU
{A51D18DA-8122-44E1-867B-1251C088832A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A51D18DA-8122-44E1-867B-1251C088832A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A51D18DA-8122-44E1-867B-1251C088832A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A51D18DA-8122-44E1-867B-1251C088832A}.Release|Any CPU.Build.0 = Release|Any CPU
{BD1A1261-3980-48F9-9F9F-EEE214B97728}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD1A1261-3980-48F9-9F9F-EEE214B97728}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD1A1261-3980-48F9-9F9F-EEE214B97728}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD1A1261-3980-48F9-9F9F-EEE214B97728}.Release|Any CPU.Build.0 = Release|Any CPU
{7EEF41C6-A90F-47F2-8BC8-91D1C3F966FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EEF41C6-A90F-47F2-8BC8-91D1C3F966FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EEF41C6-A90F-47F2-8BC8-91D1C3F966FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EEF41C6-A90F-47F2-8BC8-91D1C3F966FE}.Release|Any CPU.Build.0 = Release|Any CPU
{89877242-92A7-419E-9DC6-ED18C40DA704}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89877242-92A7-419E-9DC6-ED18C40DA704}.Debug|Any CPU.Build.0 = Debug|Any CPU
{89877242-92A7-419E-9DC6-ED18C40DA704}.Release|Any CPU.ActiveCfg = Release|Any CPU
{89877242-92A7-419E-9DC6-ED18C40DA704}.Release|Any CPU.Build.0 = Release|Any CPU
{DECF9AE7-E0AE-485E-8FF4-ED3276A785F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DECF9AE7-E0AE-485E-8FF4-ED3276A785F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DECF9AE7-E0AE-485E-8FF4-ED3276A785F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DECF9AE7-E0AE-485E-8FF4-ED3276A785F5}.Release|Any CPU.Build.0 = Release|Any CPU
{29A7FDE8-6760-4796-82AE-00FBA7B1C0B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29A7FDE8-6760-4796-82AE-00FBA7B1C0B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29A7FDE8-6760-4796-82AE-00FBA7B1C0B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29A7FDE8-6760-4796-82AE-00FBA7B1C0B4}.Release|Any CPU.Build.0 = Release|Any CPU
{FCC518A9-909C-4F86-9DD0-C16C0ED67B68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FCC518A9-909C-4F86-9DD0-C16C0ED67B68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FCC518A9-909C-4F86-9DD0-C16C0ED67B68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FCC518A9-909C-4F86-9DD0-C16C0ED67B68}.Release|Any CPU.Build.0 = Release|Any CPU
{6DFCB525-A543-46D2-B7AF-761B7E5AF160}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6DFCB525-A543-46D2-B7AF-761B7E5AF160}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6DFCB525-A543-46D2-B7AF-761B7E5AF160}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{6DFCB525-A543-46D2-B7AF-761B7E5AF160}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6DFCB525-A543-46D2-B7AF-761B7E5AF160}.Release|Any CPU.Build.0 = Release|Any CPU
{6DFCB525-A543-46D2-B7AF-761B7E5AF160}.Release|Any CPU.Deploy.0 = Release|Any CPU
{A32ACF58-7FD4-4DD5-BF46-78597D93CEE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A32ACF58-7FD4-4DD5-BF46-78597D93CEE2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A32ACF58-7FD4-4DD5-BF46-78597D93CEE2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A32ACF58-7FD4-4DD5-BF46-78597D93CEE2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{CB8DA3CE-CF95-4547-9DDE-A7A4102A3130} = {7543969E-0B5E-40EA-B9FC-7E22857D7B5D}
{BD528B93-CC27-46DB-80FA-DC9BF617E820} = {7543969E-0B5E-40EA-B9FC-7E22857D7B5D}
{EBC70960-000B-4F1F-A41F-52A91AEAF6E6} = {85A8A5DC-9E6A-4694-9919-767DC72BC960}
{4707EDF0-4DB1-473B-9435-5FEBDA1042B3} = {85A8A5DC-9E6A-4694-9919-767DC72BC960}
{A51D18DA-8122-44E1-867B-1251C088832A} = {85A8A5DC-9E6A-4694-9919-767DC72BC960}
{BD1A1261-3980-48F9-9F9F-EEE214B97728} = {9D8AD979-7C11-45DF-AA44-FDE88CA65FF4}
{7EEF41C6-A90F-47F2-8BC8-91D1C3F966FE} = {9D8AD979-7C11-45DF-AA44-FDE88CA65FF4}
{89877242-92A7-419E-9DC6-ED18C40DA704} = {9D8AD979-7C11-45DF-AA44-FDE88CA65FF4}
{DECF9AE7-E0AE-485E-8FF4-ED3276A785F5} = {9D8AD979-7C11-45DF-AA44-FDE88CA65FF4}
{29A7FDE8-6760-4796-82AE-00FBA7B1C0B4} = {9D8AD979-7C11-45DF-AA44-FDE88CA65FF4}
{FCC518A9-909C-4F86-9DD0-C16C0ED67B68} = {9D8AD979-7C11-45DF-AA44-FDE88CA65FF4}
{6DFCB525-A543-46D2-B7AF-761B7E5AF160} = {9D8AD979-7C11-45DF-AA44-FDE88CA65FF4}
{A32ACF58-7FD4-4DD5-BF46-78597D93CEE2} = {9D8AD979-7C11-45DF-AA44-FDE88CA65FF4}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {451D3CFF-AF11-410B-BFA4-4E8F0D85C3FE}
EndGlobalSection
EndGlobal
using Microsoft.AspNetCore.Authorization;
using System.Linq;
using System.Threading.Tasks;
namespace Basics.AuthorizationRequirements
{
public class CustomRequireClaim : IAuthorizationRequirement
{
public CustomRequireClaim(string claimType)
{
ClaimType = claimType;
}
public string ClaimType { get; }
}
public class CustomRequireClaimHandler : AuthorizationHandler<CustomRequireClaim>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
CustomRequireClaim requirement)
{
var hasClaim = context.User.Claims.Any(x => x.Type == requirement.ClaimType);
if (hasClaim)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public static class AuthorizationPolicyBuilderExtensions
{
public static AuthorizationPolicyBuilder RequireCustomClaim(
this AuthorizationPolicyBuilder builder,
string claimType)
{
builder.AddRequirements(new CustomRequireClaim(claimType));
return builder;
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
using Basics.CustomPolicyProvider;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Basics.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[Authorize]
public IActionResult Secret()
{
return View();
}
[Authorize(Policy = "Claim.DoB")]
public IActionResult SecretPolicy()
{
return View("Secret");
}
[Authorize(Roles = "Admin")]
public IActionResult SecretRole()
{
return View("Secret");
}
[SecurityLevel(5)]
public IActionResult SecretLevel()
{
return View("Secret");
}
[SecurityLevel(10)]
public IActionResult SecretHigherLevel()
{
return View("Secret");
}
[AllowAnonymous]
public IActionResult Authenticate()
{
var grandmaClaims = new List<Claim>()
{
new Claim(ClaimTypes.Name, "Bob"),
new Claim(ClaimTypes.Email, "Bob@fmail.com"),
new Claim(ClaimTypes.DateOfBirth, "11/11/2000"),
new Claim(ClaimTypes.Role, "Admin"),
new Claim(ClaimTypes.Role, "AdminTwo"),
new Claim(DynamicPolicies.SecurityLevel, "7"),
new Claim("Grandma.Says", "Very nice boi."),
};
var licenseClaims = new List<Claim>()
{
new Claim(ClaimTypes.Name, "Bob K Foo"),
new Claim("DrivingLicense", "A+"),
};
var grandmaIdentity = new ClaimsIdentity(grandmaClaims, "Grandma Identity");
var licenseIdentity = new ClaimsIdentity(licenseClaims, "Government");
var userPrincipal = new ClaimsPrincipal(new[] { grandmaIdentity, licenseIdentity });
//-----------------------------------------------------------
HttpContext.SignInAsync(userPrincipal);
return RedirectToAction("Index");
}
public async Task<IActionResult> DoStuff(
[FromServices] IAuthorizationService authorizationService)
{
// we are doing stuff here
var builder = new AuthorizationPolicyBuilder("Schema");
var customPolicy = builder.RequireClaim("Hello").Build();
var authResult = await authorizationService.AuthorizeAsync(User, customPolicy);
if (authResult.Succeeded)
{
return View("Index");
}
return View("Index");
}
}
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
namespace Basics.Controllers
{
public class OperationsController : Controller
{
private readonly IAuthorizationService _authorizationService;
public OperationsController(IAuthorizationService authorizationService)
{
_authorizationService = authorizationService;
}
public async Task<IActionResult> Open()
{
var cookieJar = new CookieJar(); // get cookie jar from db
await _authorizationService.AuthorizeAsync(User, cookieJar, CookieJarAuthOperations.Open);
return View();
}
}
public class CookieJarAuthorizationHandler
: AuthorizationHandler<OperationAuthorizationRequirement, CookieJar>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
OperationAuthorizationRequirement requirement,
CookieJar cookieJar)
{
if (requirement.Name == CookieJarOperations.Look)
{
if (context.User.Identity.IsAuthenticated)
{
context.Succeed(requirement);
}
}
else if (requirement.Name == CookieJarOperations.ComeNear)
{
if (context.User.HasClaim("Friend", "Good"))
{
context.Succeed(requirement);
}
}
return Task.CompletedTask;
}
}
public static class CookieJarAuthOperations
{
public static OperationAuthorizationRequirement Open = new OperationAuthorizationRequirement
{
Name = CookieJarOperations.Open
};
}
public static class CookieJarOperations
{
public static string Open = "Open";
public static string TakeCookie = "TakeCookie";
public static string ComeNear = "ComeNear";
public static string Look = "Look";
}
public class CookieJar
{
public string Name { get; set; }
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Basics.CustomPolicyProvider
{
public class SecurityLevelAttribute : AuthorizeAttribute
{
public SecurityLevelAttribute(int level)
{
Policy = $"{DynamicPolicies.SecurityLevel}.{level}";
}
}
// {type}
public static class DynamicPolicies
{
public static IEnumerable<string> Get()
{
yield return SecurityLevel;
yield return Rank;
}
public const string SecurityLevel = "SecurityLevel";
public const string Rank = "Rank";
}
public static class DynamicAuthorizationPilicyFactory
{
public static AuthorizationPolicy Create(string policyName)
{
var parts = policyName.Split('.');
var type = parts.First();
var value = parts.Last();
switch (type)
{
case DynamicPolicies.Rank:
return new AuthorizationPolicyBuilder()
.RequireClaim("Rank", value)
.Build();
case DynamicPolicies.SecurityLevel:
return new AuthorizationPolicyBuilder()
.AddRequirements(new SecurityLevelRequirement(Convert.ToInt32(value)))
.Build();
default:
return null;
}
}
}
public class SecurityLevelRequirement : IAuthorizationRequirement
{
public int Level { get; }
public SecurityLevelRequirement(int level)
{
Level = level;
}
}
public class SecurityLevelHandler : AuthorizationHandler<SecurityLevelRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
SecurityLevelRequirement requirement)
{
var claimValue = Convert.ToInt32(context.User.Claims
.FirstOrDefault(x => x.Type == DynamicPolicies.SecurityLevel)
?.Value ?? "0");
if (requirement.Level <= claimValue)
{
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public class CustomAuthorizationPolicyProvider
: DefaultAuthorizationPolicyProvider
{
public CustomAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options) : base(options)
{
}
public override Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
{
foreach (var customPolicy in DynamicPolicies.Get())
{
if (policyName.StartsWith(customPolicy))
{
var policy = DynamicAuthorizationPilicyFactory.Create(policyName);
return Task.FromResult(policy);
}
}
return base.GetPolicyAsync(policyName);
}
}
}
@page
@model Basics.Pages.Razor.IndexModel
@{
}
<h1>Index page, anone can visit this inside public folder.</h1>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Basics.Pages.Razor
{
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
}
@page
@model Basics.Pages.Razor.PolicyModel
@{
}
<h1>Secured by a policy Admin</h1>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Basics.Pages.Razor
{
public class PolicyModel : PageModel
{
public void OnGet()
{
}
}
}
@page
@model Basics.Pages.Razor.SecuredModel
@{
}
<h1>This is a secured page.</h1>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Basics.Pages.Razor
{
public class SecuredModel : PageModel
{
public void OnGet()
{
}
}
}
@page
@model Basics.Pages.RazorSecured.AnonModel
@{
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Basics.Pages.RazorSecured
{
public class AnonModel : PageModel
{
public void OnGet()
{
}
}
}
@page
@model Basics.Pages.RazorSecured.IndexModel
@{
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Basics.Pages.RazorSecured
{
public class IndexModel : PageModel
{
public void OnGet()
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Basics
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:50690",
"sslPort": 44315
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Basics": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
using Basics.AuthorizationRequirements;
using Basics.Controllers;
using Basics.CustomPolicyProvider;
using Basics.Transformer;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Security.Claims;
namespace Basics
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication("CookieAuth")
.AddCookie("CookieAuth", config =>
{
config.Cookie.Name = "Grandmas.Cookie";
config.LoginPath = "/Home/Authenticate";
});
services.AddAuthorization(config =>
{
//var defaultAuthBuilder = new AuthorizationPolicyBuilder();
//var defaultAuthPolicy = defaultAuthBuilder
// .RequireAuthenticatedUser()
// .RequireClaim(ClaimTypes.DateOfBirth)
// .Build();
//config.DefaultPolicy = defaultAuthPolicy;
//config.AddPolicy("Claim.DoB", policyBuilder =>
//{
// policyBuilder.RequireClaim(ClaimTypes.DateOfBirth);
//});
config.AddPolicy("Admin", policyBuilder => policyBuilder.RequireClaim(ClaimTypes.Role, "Admin"));
config.AddPolicy("Claim.DoB", policyBuilder =>
{
policyBuilder.RequireCustomClaim(ClaimTypes.DateOfBirth);
});
});
services.AddSingleton<IAuthorizationPolicyProvider, CustomAuthorizationPolicyProvider>();
services.AddScoped<IAuthorizationHandler, SecurityLevelHandler>();
services.AddScoped<IAuthorizationHandler, CustomRequireClaimHandler>();
services.AddScoped<IAuthorizationHandler, CookieJarAuthorizationHandler>();
services.AddScoped<IClaimsTransformation, ClaimsTransformation>();
services.AddControllersWithViews(config =>
{
var defaultAuthBuilder = new AuthorizationPolicyBuilder();
var defaultAuthPolicy = defaultAuthBuilder
.RequireAuthenticatedUser()
.Build();
// global authorization filter
//config.Filters.Add(new AuthorizeFilter(defaultAuthPolicy));
});
services.AddRazorPages()
.AddRazorPagesOptions(config =>
{
config.Conventions.AuthorizePage("/Razor/Secured");
config.Conventions.AuthorizePage("/Razor/Policy", "Admin");
config.Conventions.AuthorizeFolder("/RazorSecured");
config.Conventions.AllowAnonymousToPage("/RazorSecured/Anon");
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
// who are you?
app.UseAuthentication();
// are you allowed?
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapRazorPages();
});
}
}
}
using Microsoft.AspNetCore.Authentication;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Basics.Transformer
{
public class ClaimsTransformation : IClaimsTransformation
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
var hasFriendClaim = principal.Claims.Any(x => x.Type == "Friend");
if (!hasFriendClaim)
{
((ClaimsIdentity)principal.Identity).AddClaim(new Claim("Friend", "Bad"));
}
return Task.FromResult(principal);
}
}
}
<h1>Home Page</h1>
@* Simple access quick checks *@
@if (User.Identity.IsAuthenticated)
{
<h1>User is authenticated</h1>
}
else
{
<h1>User is NOT authenticated</h1>
}
@* Big guns reusable functions *@
@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService authorizationService
@if ((await authorizationService.AuthorizeAsync(User, "Claim.DoB")).Succeeded)
{
<h1>User has DoB Claim</h1>
}
\ No newline at end of file
<h1>Secret Page</h1>
\ No newline at end of file
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
</Project>
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace Client.Controllers
{
public class HomeController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;
public HomeController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public IActionResult Index()
{
return View();
}
[Authorize]
public async Task<IActionResult> Secret()
{
var serverResponse = await AccessTokenRefreshWrapper(
() => SecuredGetRequest("https://localhost:44382/secret/index"));
var apiResponse = await AccessTokenRefreshWrapper(
() => SecuredGetRequest("https://localhost:44332/secret/index"));
return View();
}
private async Task<HttpResponseMessage> SecuredGetRequest(string url)
{
var token = await HttpContext.GetTokenAsync("access_token");
var client = _httpClientFactory.CreateClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
return await client.GetAsync(url);
}
public async Task<HttpResponseMessage> AccessTokenRefreshWrapper(
Func<Task<HttpResponseMessage>> initialRequest)
{
var response = await initialRequest();
if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
await RefreshAccessToken();
response = await initialRequest();
}
return response;
}
private async Task RefreshAccessToken()
{
var refreshToken = await HttpContext.GetTokenAsync("refresh_token");
var refreshTokenClient = _httpClientFactory.CreateClient();
var requestData = new Dictionary<string, string>
{
["grant_type"] = "refresh_token",
["refresh_token"] = refreshToken
};
var request = new HttpRequestMessage(HttpMethod.Post, "https://localhost:44382/oauth/token")
{
Content = new FormUrlEncodedContent(requestData)
};
var basicCredentials = "username:password";
var encodedCredentials = Encoding.UTF8.GetBytes(basicCredentials);
var base64Credentials = Convert.ToBase64String(encodedCredentials);
request.Headers.Add("Authorization", $"Basic {base64Credentials}");
var response = await refreshTokenClient.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
var responseData = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseString);
var newAccessToken = responseData.GetValueOrDefault("access_token");
var newRefreshToken = responseData.GetValueOrDefault("refresh_token");
var authInfo = await HttpContext.AuthenticateAsync("ClientCookie");
authInfo.Properties.UpdateTokenValue("access_token", newAccessToken);
authInfo.Properties.UpdateTokenValue("refresh_token", newRefreshToken);
await HttpContext.SignInAsync("ClientCookie", authInfo.Principal, authInfo.Properties);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Client
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:49459",
"sslPort": 44342
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Client": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
namespace Client
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(config => {
// We check the cookie to confirm that we are authenticated
config.DefaultAuthenticateScheme = "ClientCookie";
// When we sign in we will deal out a cookie
config.DefaultSignInScheme = "ClientCookie";
// use this to check if we are allowed to do something.
config.DefaultChallengeScheme = "OurServer";
})
.AddCookie("ClientCookie")
.AddOAuth("OurServer", config => {
config.ClientId = "client_id";
config.ClientSecret = "client_secret";
config.CallbackPath = "/oauth/callback";
config.AuthorizationEndpoint = "https://localhost:44382/oauth/authorize";
config.TokenEndpoint = "https://localhost:44382/oauth/token";
config.SaveTokens = true;
config.Events = new OAuthEvents()
{
OnCreatingTicket = context =>
{
var accessToken = context.AccessToken;
var base64payload = accessToken.Split('.')[1];
var bytes = Convert.FromBase64String(base64payload);
var jsonPayload = Encoding.UTF8.GetString(bytes);
var claims = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonPayload);
foreach(var claim in claims)
{
context.Identity.AddClaim(new Claim(claim.Key, claim.Value));
}
return Task.CompletedTask;
}
};
});
services.AddHttpClient();
services.AddControllersWithViews()
.AddRazorRuntimeCompilation();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
}
<h1>Client Home Page</h1>
<h1>Client Secret Page</h1>
\ No newline at end of file
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using NETCore.MailKit.Core;
using System.Threading.Tasks;
namespace IdentityExample.Controllers
{
public class HomeController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly IEmailService _emailService;
public HomeController(
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
IEmailService emailService)
{
_userManager = userManager;
_signInManager = signInManager;
_emailService = emailService;
}
public IActionResult Index()
{
return View();
}
[Authorize]
public IActionResult Secret()
{
return View();
}
public IActionResult Login()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login(string username, string password)
{
//login functionality
var user = await _userManager.FindByNameAsync(username);
if (user != null)
{
//sign in
var signInResult = await _signInManager.PasswordSignInAsync(user, password, false, false);
if (signInResult.Succeeded)
{
return RedirectToAction("Index");
}
}
return RedirectToAction("Index");
}
public IActionResult Register()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Register(string username, string password)
{
//register functionality
var user = new IdentityUser
{
UserName = username,
Email = "",
};
var result = await _userManager.CreateAsync(user, password);
if (result.Succeeded)
{
//generation of the email token
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var link = Url.Action(nameof(VerifyEmail), "Home", new { userId = user.Id, code }, Request.Scheme, Request.Host.ToString());
await _emailService.SendAsync("test@test.com", "email verify", $"<a href=\"{link}\">Verify Email</a>", true);
return RedirectToAction("EmailVerification");
}
return RedirectToAction("Index");
}
public async Task<IActionResult> VerifyEmail(string userId, string code)
{
var user = await _userManager.FindByIdAsync(userId);
if (user == null) return BadRequest();
var result = await _userManager.ConfirmEmailAsync(user, code);
if (result.Succeeded)
{
return View();
}
return BadRequest();
}
public IActionResult EmailVerification() => View();
public async Task<IActionResult> LogOut()
{
await _signInManager.SignOutAsync();
return RedirectToAction("Index");
}
}
}
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace IdentityExample.Data
{
// IdentityDbContext contains all the user tables
public class AppDbContext : IdentityDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0" />
<PackageReference Include="NETCore.MailKit" Version="2.0.2" />
</ItemGroup>
</Project>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace IdentityExample
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:58375",
"sslPort": 0
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IdentityExample": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
using IdentityExample.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NETCore.MailKit.Extensions;
using NETCore.MailKit.Infrastructure.Internal;
namespace IdentityExample
{
public class Startup
{
private IConfiguration _config;
public Startup(IConfiguration config)
{
_config = config;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(config =>
{
config.UseInMemoryDatabase("Memory");
});
// AddIdentity registers the services
services.AddIdentity<IdentityUser, IdentityRole>(config =>
{
config.Password.RequiredLength = 4;
config.Password.RequireDigit = false;
config.Password.RequireNonAlphanumeric = false;
config.Password.RequireUppercase = false;
config.SignIn.RequireConfirmedEmail = true;
})
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(config =>
{
config.Cookie.Name = "Identity.Cookie";
config.LoginPath = "/Home/Login";
});
services.AddMailKit(config => config.UseMailKit(_config.GetSection("Email").Get<MailKitOptions>()));
services.AddControllersWithViews();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
}

<h2>Email has been sent</h2>
<h3>Please verify it.</h3>
\ No newline at end of file
<h1>Home Page</h1>
\ No newline at end of file
<h1>Login Page</h1>
<form action="/Home/Login" method="post">
<input type="text" name="username" value="" />
<input type="text" name="password" value="" />
<button type="submit">Login</button>
</form>
<h1>Register Page</h1>
<form action="/Home/Register" method="post">
<input type="text" name="username" value="" />
<input type="text" name="password" value="" />
<button type="submit">Register</button>
</form>
<h1>Secret Page</h1>
\ No newline at end of file

<h2>Thank you for verifying your email please login here</h2>
<a href="/Home/Login">Go to Login </a>
\ No newline at end of file
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
{
"Email": {
"Server": "127.0.0.1",
"Port": 25,
"SenderName": "Anton",
"SenderEmail": "Testo@testo.com"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;
using System.Collections.Generic;
namespace IdentityServer
{
public static class Configuration
{
public static IEnumerable<IdentityResource> GetIdentityResources() =>
new List<IdentityResource>
{
new IdentityResources.OpenId(),
//new IdentityResources.Profile(),
new IdentityResource
{
Name = "rc.scope",
UserClaims =
{
"rc.garndma"
}
}
};
public static IEnumerable<ApiResource> GetApis() =>
new List<ApiResource> {
new ApiResource("ApiOne"),
new ApiResource("ApiTwo", new string[] { "rc.api.garndma" }),
};
public static IEnumerable<Client> GetClients() =>
new List<Client> {
new Client {
ClientId = "client_id",
ClientSecrets = { new Secret("client_secret".ToSha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = { "ApiOne" }
},
new Client {
ClientId = "client_id_mvc",
ClientSecrets = { new Secret("client_secret_mvc".ToSha256()) },
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
RedirectUris = { "https://localhost:44322/signin-oidc" },
PostLogoutRedirectUris = { "https://localhost:44322/Home/Index" },
AllowedScopes = {
"ApiOne",
"ApiTwo",
IdentityServerConstants.StandardScopes.OpenId,
//IdentityServerConstants.StandardScopes.Profile,
"rc.scope",
},
// puts all the claims in the id token
//AlwaysIncludeUserClaimsInIdToken = true,
AllowOfflineAccess = true,
RequireConsent = false,
},
new Client {
ClientId = "client_id_js",
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
RequireClientSecret = false,
RedirectUris = { "https://localhost:44345/home/signin" },
PostLogoutRedirectUris = { "https://localhost:44345/Home/Index" },
AllowedCorsOrigins = { "https://localhost:44345" },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
"ApiOne",
"ApiTwo",
"rc.scope",
},
AccessTokenLifetime = 1,
AllowAccessTokensViaBrowser = true,
RequireConsent = false,
},
new Client {
ClientId = "wpf",
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
RequireClientSecret = false,
RedirectUris = { "http://localhost/sample-wpf-app" },
AllowedCorsOrigins = { "http://localhost" },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
"ApiOne",
},
AllowAccessTokensViaBrowser = true,
RequireConsent = false,
},
new Client {
ClientId = "xamarin",
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
RequireClientSecret = false,
RedirectUris = { "xamarinformsclients://callback" },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
"ApiOne",
},
AllowAccessTokensViaBrowser = true,
RequireConsent = false,
},
new Client {
ClientId = "flutter",
AllowedGrantTypes = GrantTypes.Code,
RequirePkce = true,
RequireClientSecret = false,
RedirectUris = { "http://localhost:4000/" },
AllowedCorsOrigins = { "http://localhost:4000" },
AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId,
"ApiOne",
},
AllowAccessTokensViaBrowser = true,
RequireConsent = false,
},
};
}
}
using IdentityServer4.Services;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using System.Threading.Tasks;
namespace IdentityServer.Controllers
{
public class AuthController : Controller
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
private readonly IIdentityServerInteractionService _interactionService;
public AuthController(
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
IIdentityServerInteractionService interactionService)
{
_signInManager = signInManager;
_userManager = userManager;
_interactionService = interactionService;
}
[HttpGet]
public async Task<IActionResult> Logout(string logoutId)
{
await _signInManager.SignOutAsync();
var logoutRequest = await _interactionService.GetLogoutContextAsync(logoutId);
if (string.IsNullOrEmpty(logoutRequest.PostLogoutRedirectUri))
{
return RedirectToAction("Index", "Home");
}
return Redirect(logoutRequest.PostLogoutRedirectUri);
}
[HttpGet]
public async Task<IActionResult> Login(string returnUrl)
{
var externalProviders = await _signInManager.GetExternalAuthenticationSchemesAsync();
return View(new LoginViewModel
{
ReturnUrl = returnUrl,
ExternalProviders = externalProviders
});
}
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel vm)
{
// check if the model is valid
var result = await _signInManager.PasswordSignInAsync(vm.Username, vm.Password, false, false);
if (result.Succeeded)
{
return Redirect(vm.ReturnUrl);
}
else if (result.IsLockedOut)
{
}
return View();
}
[HttpGet]
public IActionResult Register(string returnUrl)
{
return View(new RegisterViewModel { ReturnUrl = returnUrl });
}
[HttpPost]
public async Task<IActionResult> Register(RegisterViewModel vm)
{
if (!ModelState.IsValid)
{
return View(vm);
}
var user = new IdentityUser(vm.Username);
var result = await _userManager.CreateAsync(user, vm.Password);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, false);
return Redirect(vm.ReturnUrl);
}
return View();
}
public async Task<IActionResult> ExternalLogin(string provider, string returnUrl)
{
var redirectUri = Url.Action(nameof(ExteranlLoginCallback), "Auth", new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUri);
return Challenge(properties, provider);
}
public async Task<IActionResult> ExteranlLoginCallback(string returnUrl)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction("Login");
}
var result = await _signInManager
.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false);
if (result.Succeeded)
{
return Redirect(returnUrl);
}
var username = info.Principal.FindFirst(ClaimTypes.Name.Replace(" ", "_")).Value;
return View("ExternalRegister", new ExternalRegisterViewModel
{
Username = username,
ReturnUrl = returnUrl
});
}
public async Task<IActionResult> ExternalRegister(ExternalRegisterViewModel vm)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction("Login");
}
var user = new IdentityUser(vm.Username);
var result = await _userManager.CreateAsync(user);
if (!result.Succeeded)
{
return View(vm);
}
result = await _userManager.AddLoginAsync(user, info);
if (!result.Succeeded)
{
return View(vm);
}
await _signInManager.SignInAsync(user, false);
return Redirect(vm.ReturnUrl);
}
}
}
namespace IdentityServer.Controllers
{
public class ExternalRegisterViewModel
{
public string Username { get; set; }
public string ReturnUrl { get; set; }
}
}
using Microsoft.AspNetCore.Authentication;
using System.Collections.Generic;
namespace IdentityServer.Controllers
{
public class LoginViewModel
{
public string Username { get; set; }
public string Password { get; set; }
public string ReturnUrl { get; set; }
public IEnumerable<AuthenticationScheme> ExternalProviders { get; set; }
}
}
\ No newline at end of file
using System.ComponentModel.DataAnnotations;
namespace IdentityServer.Controllers
{
public class RegisterViewModel
{
[Required]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required]
[DataType(DataType.Password)]
[Compare("Password")]
public string ConfirmPassword { get; set; }
public string ReturnUrl { get; set; }
}
}
\ No newline at end of file
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace IdentityServer.Data
{
// IdentityDbContext contains all the user tables
public class AppDbContext : IdentityDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
}
}
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace IdentityServer.Data.Migrations.AppMigrations
{
public partial class init : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserName = table.Column<string>(maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
Email = table.Column<string>(maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(nullable: false),
PasswordHash = table.Column<string>(nullable: true),
SecurityStamp = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
PhoneNumber = table.Column<string>(nullable: true),
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
TwoFactorEnabled = table.Column<bool>(nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnabled = table.Column<bool>(nullable: false),
AccessFailedCount = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RoleId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
UserId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(nullable: false),
ProviderKey = table.Column<string>(nullable: false),
ProviderDisplayName = table.Column<string>(nullable: true),
UserId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
RoleId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
LoginProvider = table.Column<string>(nullable: false),
Name = table.Column<string>(nullable: false),
Value = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true,
filter: "[NormalizedName] IS NOT NULL");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true,
filter: "[NormalizedUserName] IS NOT NULL");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}
// <auto-generated />
using System;
using IdentityServer4.EntityFramework.DbContexts;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace IdentityServer.Data.Migrations.IdentityServer.PersistedGrantDb
{
[DbContext(typeof(PersistedGrantDbContext))]
[Migration("20191201205312_InitialIdentityServerPersistedGrantDbMigration")]
partial class InitialIdentityServerPersistedGrantDbMigration
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.DeviceFlowCodes", b =>
{
b.Property<string>("UserCode")
.HasColumnType("nvarchar(200)")
.HasMaxLength(200);
b.Property<string>("ClientId")
.IsRequired()
.HasColumnType("nvarchar(200)")
.HasMaxLength(200);
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<string>("Data")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasMaxLength(50000);
b.Property<string>("DeviceCode")
.IsRequired()
.HasColumnType("nvarchar(200)")
.HasMaxLength(200);
b.Property<DateTime?>("Expiration")
.IsRequired()
.HasColumnType("datetime2");
b.Property<string>("SubjectId")
.HasColumnType("nvarchar(200)")
.HasMaxLength(200);
b.HasKey("UserCode");
b.HasIndex("DeviceCode")
.IsUnique();
b.HasIndex("Expiration");
b.ToTable("DeviceCodes");
});
modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b =>
{
b.Property<string>("Key")
.HasColumnType("nvarchar(200)")
.HasMaxLength(200);
b.Property<string>("ClientId")
.IsRequired()
.HasColumnType("nvarchar(200)")
.HasMaxLength(200);
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<string>("Data")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasMaxLength(50000);
b.Property<DateTime?>("Expiration")
.HasColumnType("datetime2");
b.Property<string>("SubjectId")
.HasColumnType("nvarchar(200)")
.HasMaxLength(200);
b.Property<string>("Type")
.IsRequired()
.HasColumnType("nvarchar(50)")
.HasMaxLength(50);
b.HasKey("Key");
b.HasIndex("Expiration");
b.HasIndex("SubjectId", "ClientId", "Type");
b.ToTable("PersistedGrants");
});
#pragma warning restore 612, 618
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
@model ExternalRegisterViewModel
<form asp-controller="Auth" asp-action="ExternalRegister" method="post">
<input type="hidden" asp-for="ReturnUrl" />
<div>
<label>Username</label>
<input asp-for="Username" />
<span asp-validation-for="Username"></span>
</div>
<div>
<button type="submit">Sign Up</button>
</div>
</form>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment