├── .gitignore ├── IdentityServer.sln ├── LICENSE ├── README.md ├── docs └── project_structure.md └── src ├── .bowerrc ├── Areas ├── Admin │ ├── Controllers │ │ ├── AccountController.cs │ │ ├── Api │ │ │ └── ClientController.cs │ │ ├── ClientsController.cs │ │ ├── HomeController.cs │ │ ├── ResourceController.cs │ │ └── UsersController.cs │ ├── ViewComponents │ │ └── ClientList.cs │ ├── ViewModels │ │ └── AccountViewModels.cs │ └── Views │ │ ├── Account │ │ └── Login.cshtml │ │ ├── Clients │ │ ├── Index.cshtml │ │ └── _ViewStart.cshtml │ │ ├── Home │ │ ├── Clients.cshtml │ │ ├── Index.cshtml │ │ └── _ViewStart.cshtml │ │ ├── Resource │ │ ├── ApiResources.cshtml │ │ ├── IdentityResources.cshtml │ │ └── _ViewStart.cshtml │ │ ├── Shared │ │ ├── Components │ │ │ └── ClientList │ │ │ │ └── Default.cshtml │ │ ├── _AddClient.cshtml │ │ └── _AdminLayout.cshtml │ │ ├── Users │ │ ├── Index.cshtml │ │ └── _ViewStart.cshtml │ │ ├── _ViewImports.cshtml │ │ └── _ViewStart.cshtml └── Client │ ├── Controllers │ ├── AccountController.cs │ └── HomeController.cs │ └── Views │ ├── Account │ └── Login.cshtml │ ├── Home │ ├── Index.cshtml │ └── _ViewStart.cshtml │ ├── Shared │ └── _ClientLayout.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml ├── Configuration ├── Config.cs ├── GlobalConfiguration.cs └── TestConfig │ ├── TestConfig.cs │ └── TestUsers.cs ├── Constants ├── Messages.cs ├── Policies.cs └── Roles.cs ├── Controllers ├── Account │ ├── AccountController.cs │ ├── AccountController_UserManager.cs │ ├── AccountOptions.cs │ ├── AccountService.cs │ ├── ExternalProvider.cs │ ├── LoggedOutViewModel.cs │ ├── LoginInputModel.cs │ ├── LoginViewModel.cs │ ├── LogoutInputModel.cs │ └── LogoutViewModel.cs ├── Api │ └── SecurityController.cs ├── Consent │ ├── ConsentController.cs │ ├── ConsentInputModel.cs │ ├── ConsentOptions.cs │ ├── ConsentService.cs │ ├── ConsentViewModel.cs │ ├── ProcessConsentResult.cs │ └── ScopeViewModel.cs ├── Grants │ ├── GrantsController.cs │ └── GrantsViewModel.cs ├── Home │ ├── ErrorViewModel.cs │ └── HomeController.cs └── HomeController.cs ├── Data ├── DatabaseContext.cs └── Entities │ ├── ApplicationUser.cs │ ├── ExternalUser.cs │ ├── PasswordConfigs.cs │ └── Provider.cs ├── ExtensionGrant └── ExternalAuthenticationGrant.cs ├── Extensions ├── DbContextExtensions.cs ├── IdentityExtensions.cs ├── ServiceCollectionExtensions.cs └── UserManagerExtensions.cs ├── Filters ├── SecurityHeadersAttribute.cs └── ValidateModelState.cs ├── Helpers ├── ProviderType.cs └── QueryBuilder.cs ├── IdentityServer.Dashboard.csproj ├── Interfaces ├── ExternalProviders │ ├── IExternalAuthProvider.cs │ ├── IFacebookAuthProvider.cs │ ├── IGoogleAuthProvider.cs │ ├── ILinkedInAuthProvider.cs │ └── ITwitterAuthProvider.cs ├── IdentityServer │ └── IClientService.cs ├── Processors │ ├── IEmailUserProcessor.cs │ └── INonEmailUserProcessor.cs └── SecurityService │ ├── IIdentityResult.cs │ ├── ISecurityService.cs │ └── ITokenService.cs ├── Migrations ├── 20170925064019_init_identity.Designer.cs ├── 20170925064019_init_identity.cs ├── 20170928121323_client_id_field_added.Designer.cs ├── 20170928121323_client_id_field_added.cs ├── 20170929054125_config_tables.Designer.cs ├── 20170929054125_config_tables.cs ├── ConfigurationDb │ ├── 20170925053334_init_cnfi.Designer.cs │ ├── 20170925053334_init_cnfi.cs │ └── ConfigurationDbContextModelSnapshot.cs ├── DatabaseContextModelSnapshot.cs └── PersistedGrantDb │ ├── 20170925053610_init_grans.Designer.cs │ ├── 20170925053610_init_grans.cs │ └── PersistedGrantDbContextModelSnapshot.cs ├── Models └── BaseModel.cs ├── Processors ├── EmailUserProcessor.cs └── NonEmailUserProcessor.cs ├── Program.cs ├── Providers ├── FacebookAuthProvider.cs ├── GoogleAuthProvider.cs ├── LinkedInAuthProvider.cs └── TwitterAuthProvider.cs ├── Repositories ├── ExternalUserRepository.cs ├── GenericRepository.cs ├── IdentityServerRepositories │ ├── ClientRepository.cs │ └── ResourceRepository.cs ├── Interfaces │ ├── IExternalUserRepository.cs │ ├── IPasswordConfigRepository.cs │ ├── IProviderRepository.cs │ ├── IRepository.cs │ └── IdentityServerRepositories │ │ ├── IClientRepository.cs │ │ └── IResourcerRepository.cs ├── PasswordConfigRepository.cs ├── ProviderRepository.cs └── UnitOfWork │ ├── IUnitOfWork.cs │ └── UnitOfWork.cs ├── Services ├── IdentityServer │ └── ClientService.cs ├── SecurityService │ ├── Results │ │ ├── LoginViewModel.cs │ │ └── RegisterationResult.cs │ └── SecurityService.cs └── TokenService.cs ├── Startup.cs ├── ViewModels └── SecurityService │ └── RegisterViewModel.cs ├── Views ├── Account │ ├── LoggedOut.cshtml │ ├── Login.cshtml │ └── Logout.cshtml ├── Consent │ ├── Index.cshtml │ └── _ScopeListItem.cshtml ├── Grants │ └── Index.cshtml ├── Home │ ├── About.cshtml │ ├── GettingStarted.cshtml │ └── Index.cshtml ├── Shared │ ├── Error.cshtml │ ├── _Layout.cshtml │ └── _ValidationSummary.cshtml ├── _ViewImports.cshtml └── _ViewStart.cshtml ├── appsettings.json ├── bower.json ├── tempkey.rsa └── wwwroot ├── css └── site.css ├── js ├── extensions.js ├── helpers.js └── services │ └── clientService.js └── lib ├── caret ├── .bower.json ├── bower.json ├── jquery.caret.js ├── license.txt └── readme.md ├── dialog-polyfill ├── .bower.json ├── LICENSE ├── README.md ├── bower.json ├── dialog-polyfill.css ├── dialog-polyfill.js ├── package.json ├── suite.js └── test.html ├── jquery-tag-editor ├── .bower.json ├── bower.json ├── jquery.caret.min.js ├── jquery.tag-editor.css ├── jquery.tag-editor.js ├── jquery.tag-editor.min.js ├── tag-it.js └── tag-it.min.js └── jquery ├── .bower.json ├── AUTHORS.txt ├── LICENSE.txt ├── README.md ├── bower.json ├── dist ├── core.js ├── jquery.js ├── jquery.min.js ├── jquery.min.map ├── jquery.slim.js ├── jquery.slim.min.js └── jquery.slim.min.map ├── external └── sizzle │ ├── LICENSE.txt │ └── dist │ ├── sizzle.js │ ├── sizzle.min.js │ └── sizzle.min.map └── src ├── .eslintrc.json ├── ajax.js ├── ajax ├── jsonp.js ├── load.js ├── parseXML.js ├── script.js ├── var │ ├── location.js │ ├── nonce.js │ └── rquery.js └── xhr.js ├── attributes.js ├── attributes ├── attr.js ├── classes.js ├── prop.js ├── support.js └── val.js ├── callbacks.js ├── core.js ├── core ├── DOMEval.js ├── access.js ├── init.js ├── nodeName.js ├── parseHTML.js ├── ready-no-deferred.js ├── ready.js ├── readyException.js ├── stripAndCollapse.js ├── support.js └── var │ └── rsingleTag.js ├── css.js ├── css ├── addGetHookIf.js ├── adjustCSS.js ├── curCSS.js ├── hiddenVisibleSelectors.js ├── showHide.js ├── support.js └── var │ ├── cssExpand.js │ ├── getStyles.js │ ├── isHiddenWithinTree.js │ ├── rmargin.js │ ├── rnumnonpx.js │ └── swap.js ├── data.js ├── data ├── Data.js └── var │ ├── acceptData.js │ ├── dataPriv.js │ └── dataUser.js ├── deferred.js ├── deferred └── exceptionHook.js ├── deprecated.js ├── dimensions.js ├── effects.js ├── effects ├── Tween.js └── animatedSelector.js ├── event.js ├── event ├── ajax.js ├── alias.js ├── focusin.js ├── support.js └── trigger.js ├── exports ├── amd.js └── global.js ├── jquery.js ├── manipulation.js ├── manipulation ├── _evalUrl.js ├── buildFragment.js ├── getAll.js ├── setGlobalEval.js ├── support.js ├── var │ ├── rcheckableType.js │ ├── rscriptType.js │ └── rtagName.js └── wrapMap.js ├── offset.js ├── queue.js ├── queue └── delay.js ├── selector-native.js ├── selector-sizzle.js ├── selector.js ├── serialize.js ├── traversing.js ├── traversing ├── findFilter.js └── var │ ├── dir.js │ ├── rneedsContext.js │ └── siblings.js ├── var ├── ObjectFunctionString.js ├── arr.js ├── class2type.js ├── concat.js ├── document.js ├── documentElement.js ├── fnToString.js ├── getProto.js ├── hasOwn.js ├── indexOf.js ├── pnum.js ├── push.js ├── rcssNum.js ├── rnothtmlwhite.js ├── slice.js ├── support.js └── toString.js └── wrap.js /IdentityServer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{DF54CC6D-5F2C-49D3-AC74-D305434D43C7}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityServer.Dashboard", "src\IdentityServer.Dashboard.csproj", "{69A6EC7C-C9DD-429E-A27C-935F42DE973C}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{2C89E43B-7D5F-4600-981A-21C21A590103}" 11 | ProjectSection(SolutionItems) = preProject 12 | docs\project_structure.md = docs\project_structure.md 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {69A6EC7C-C9DD-429E-A27C-935F42DE973C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {69A6EC7C-C9DD-429E-A27C-935F42DE973C}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {69A6EC7C-C9DD-429E-A27C-935F42DE973C}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {69A6EC7C-C9DD-429E-A27C-935F42DE973C}.Release|Any CPU.Build.0 = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(SolutionProperties) = preSolution 27 | HideSolutionNode = FALSE 28 | EndGlobalSection 29 | GlobalSection(NestedProjects) = preSolution 30 | {69A6EC7C-C9DD-429E-A27C-935F42DE973C} = {DF54CC6D-5F2C-49D3-AC74-D305434D43C7} 31 | EndGlobalSection 32 | GlobalSection(ExtensibilityGlobals) = postSolution 33 | SolutionGuid = {2A49F662-10D8-4185-AEDD-D939B138C50F} 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Muhammad Waqas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | > **This project is currently under development and is not ready for production use.** 4 | 5 | 6 | # IdentityServer Admin Dashboard 7 | IdentityServer with admin UI for dynamic configuration of clients, users and resources. 8 | 9 | ## Introduction 10 | This solution is emphasized at providing a seamless configuration experience to users of IdentityServer. It provides UI tooling for managing all IdentityServer resources including Clients, Users, IdentityResources and ApiResources. Project is still in its initial state and most of its basic features are yet to be implemented, for which the open-source community is welcomed to contribute and scale the solution. 11 | 12 | ## Build Dependencies 13 | 14 | - .NET Core 2.0 15 | - MySql Connector for .NET [not required if using SQL-Server] 16 | - Visual Studio 2017 [optional] 17 | 18 | ## Features 19 | - EntityFrameworkCore 2.0+ backed stores for configuring users,clients and resources 20 | - Separate sections for Admins and Clients to manage resources. 21 | - Built-in support for authentication using external providers for ResourceOwner flow. 22 | 23 | 24 | ## Milestones 25 | 26 | - [x] Basic project structure 27 | - [x] Separate areas for clients and admins 28 | - [ ] Adding a client resource from admin section. 29 | - [ ] Adding an api resource from admin section. 30 | - [ ] Adding an identity resource from admin section. 31 | - [ ] Adding a user from admin section. 32 | - [ ] ... 33 | - [ ] ... 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/project_structure.md: -------------------------------------------------------------------------------- 1 | # Project Structure -------------------------------------------------------------------------------- /src/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "wwwroot/lib" 3 | } 4 | -------------------------------------------------------------------------------- /src/Areas/Admin/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Areas.Admin.ViewModels.AccountViewModels; 2 | using IdentityServer.Constants; 3 | using IdentityServer.Data.Entities; 4 | using IdentityServer.Extensions; 5 | using Microsoft.AspNetCore.Identity; 6 | using Microsoft.AspNetCore.Mvc; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using System.Security.Claims; 11 | using System.Threading.Tasks; 12 | 13 | namespace IdentityServer.Areas.Admin.Controllers 14 | { 15 | [Area("Admin")] 16 | public class AccountController:Controller 17 | { 18 | private readonly UserManager _userManager; 19 | private readonly SignInManager _signInManager; 20 | public AccountController(UserManager userManager,SignInManager signInManager) 21 | { 22 | _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); 23 | _signInManager = signInManager ?? throw new ArgumentNullException(nameof(signInManager)); 24 | 25 | } 26 | public async Task Login() 27 | { 28 | if(User != null && User.Identity.IsAuthenticated) 29 | { 30 | var principal = User as ClaimsPrincipal; 31 | var emailClaim = principal.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name); 32 | if(emailClaim != null) 33 | { 34 | var user = await _userManager.FindByEmailAsync(emailClaim.Value); 35 | if(user != null && await _userManager.IsSuperAdmin(user)) 36 | return RedirectToAction("Index", "Home"); 37 | } 38 | 39 | } 40 | return View(); 41 | } 42 | 43 | [HttpPost] 44 | public async Task Login(LoginViewModel model) 45 | { 46 | if (!ModelState.IsValid) 47 | return View(model); 48 | 49 | var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, false, false); 50 | 51 | if(result.Succeeded) 52 | { 53 | var user = await _userManager.FindByEmailAsync(model.Email); 54 | if (await _userManager.IsSuperAdmin(user)) 55 | { 56 | return RedirectToAction("Index", "Home"); 57 | } 58 | 59 | ModelState.AddModelError("", Messages.USER_NOT_ADMIN); 60 | return View(); 61 | } 62 | 63 | ModelState.AddModelError("", Messages.INVALID_LOGIN_REQUEST); 64 | return View(model); 65 | 66 | } 67 | 68 | [HttpGet] 69 | public async Task LogOut() 70 | { 71 | await _signInManager.SignOutAsync(); 72 | return Redirect("/Home"); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Areas/Admin/Controllers/ClientsController.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Dashboard.Areas.Admin.ViewComponents; 2 | using IdentityServer.Repositories.Interfaces.IdentityServerRepositories; 3 | using IdentityServer4.EntityFramework.Mappers; 4 | using IdentityServer4.Models; 5 | using IdentityServer4.Stores; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.Rendering; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Threading.Tasks; 12 | 13 | namespace IdentityServer.Areas.Admin.Controllers 14 | { 15 | [Area("Admin")] 16 | 17 | public class ClientsController:Controller 18 | { 19 | private readonly IClientRepository _clientRepository; 20 | private readonly IResourcesRepository _resourceRepository; 21 | public ClientsController(IClientRepository clientRepository,IResourcesRepository resourceRepository) 22 | { 23 | _clientRepository = clientRepository; 24 | _resourceRepository = resourceRepository; 25 | } 26 | public IActionResult Index() 27 | { 28 | 29 | 30 | ViewBag.ApiResources = _resourceRepository.GetApiResources().ToList().Select(x => x.Name); 31 | ViewBag.IdentityResources = _resourceRepository.GetIdentityResources().ToList().Select(x => x.Name); 32 | 33 | return View(); 34 | } 35 | 36 | public IActionResult GetClients() 37 | { 38 | return ViewComponent(nameof(ClientList)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Areas/Admin/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Mvc; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityServer.Areas.Admin.Controllers 9 | { 10 | public class HomeController:Controller 11 | { 12 | [Area("Admin")] 13 | [Authorize] 14 | public IActionResult Index() 15 | { 16 | return View(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Areas/Admin/Controllers/ResourceController.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Repositories.Interfaces.IdentityServerRepositories; 2 | using IdentityServer4.EntityFramework.Mappers; 3 | using IdentityServer4.Models; 4 | using Microsoft.AspNetCore.Mvc; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace IdentityServer.Areas.Admin.Controllers 11 | { 12 | [Area("Admin")] 13 | public class ResourceController:Controller 14 | { 15 | private readonly IResourcesRepository _resourceRepository; 16 | public ResourceController(IResourcesRepository resourceRepository) 17 | { 18 | _resourceRepository = resourceRepository; 19 | } 20 | 21 | public IActionResult ApiResources() 22 | { 23 | var apiResources = _resourceRepository.GetApiResources().ToList(); 24 | var list = new List(); 25 | apiResources.ForEach((item) => list.Add(item.ToModel())); 26 | 27 | return View(list); 28 | } 29 | 30 | public IActionResult IdentityResources() 31 | { 32 | var identityResources = _resourceRepository.GetIdentityResources().ToList(); 33 | var list = new List(); 34 | identityResources.ForEach((item) => list.Add(item.ToModel())); 35 | 36 | return View(list); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Areas/Admin/Controllers/UsersController.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using IdentityServer.Extensions; 3 | using Microsoft.AspNetCore.Identity; 4 | using Microsoft.AspNetCore.Mvc; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace IdentityServer.Areas.Admin.Controllers 11 | { 12 | [Area("Admin")] 13 | public class UsersController:Controller 14 | { 15 | private readonly UserManager _userManager; 16 | public UsersController(UserManager userManager) 17 | { 18 | _userManager = userManager; 19 | } 20 | public IActionResult Index() 21 | { 22 | var users = _userManager.GetAllUsers(); 23 | return View(users); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Areas/Admin/ViewComponents/ClientList.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Repositories.Interfaces.IdentityServerRepositories; 2 | using IdentityServer4.EntityFramework.Mappers; 3 | using Microsoft.AspNetCore.Mvc; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace IdentityServer.Dashboard.Areas.Admin.ViewComponents 10 | { 11 | [ViewComponent] 12 | public class ClientList : ViewComponent 13 | { 14 | private readonly IClientRepository _clientRepository; 15 | public ClientList(IClientRepository clientRepository) 16 | { 17 | _clientRepository = clientRepository; 18 | } 19 | 20 | public async Task InvokeAsync() 21 | { 22 | var clients = _clientRepository.Get().ToList(); 23 | var list = new List(); 24 | clients.ForEach((ele) => list.Add(ele.ToModel())); 25 | 26 | return View(list); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Areas/Admin/ViewModels/AccountViewModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Areas.Admin.ViewModels.AccountViewModels 8 | { 9 | public class LoginViewModel 10 | { 11 | [Required] 12 | [DataType(DataType.EmailAddress)] 13 | public string Email { get; set; } 14 | 15 | [Required] 16 | 17 | public string Password { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Areas/Admin/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @model IdentityServer.Areas.Admin.ViewModels.AccountViewModels.LoginViewModel 2 |
3 |

Administrator login

4 |
5 | 6 |

Provide your administrator credentials to login as an administrator.

7 |
8 |
9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 | 17 | 18 |
19 |
20 | 23 |
24 |
25 |
26 | 27 | -------------------------------------------------------------------------------- /src/Areas/Admin/Views/Clients/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_AdminLayout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/Areas/Admin/Views/Home/Clients.cshtml: -------------------------------------------------------------------------------- 1 | 

Clients

-------------------------------------------------------------------------------- /src/Areas/Admin/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
2 | 3 | 4 |
5 |
MANAGE
6 |
7 |
    8 |
  • 9 | 10 | person 11 | Bryan Cranston 12 | 13 |
  • 14 |
  • 15 | 16 | person 17 | Aaron Paul 18 | 19 |
  • 20 |
  • 21 | 22 | person 23 | Bob Odenkirk 24 | 25 |
  • 26 |
27 |
28 | 29 | 30 |
-------------------------------------------------------------------------------- /src/Areas/Admin/Views/Home/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_AdminLayout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/Areas/Admin/Views/Resource/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_AdminLayout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/Areas/Admin/Views/Shared/Components/ClientList/Default.cshtml: -------------------------------------------------------------------------------- 1 | @model IEnumerable 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | @foreach (var client in Model) 14 | { 15 | 16 | 17 | 18 | 25 | 28 | 39 | 40 | 41 | } 42 | 43 | 44 | 45 |
Client IDClient NameEnabledToken ExpiryActions
@client.ClientId@client.ClientName 19 | 24 | 26 | @client.AccessTokenLifetime 27 | 29 | 32 | 35 | 38 |
-------------------------------------------------------------------------------- /src/Areas/Admin/Views/Users/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_AdminLayout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/Areas/Admin/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 2 | @using IdentityServer4.Models 3 | @using IdentityServer.Dashboard.Areas.Admin.ViewComponents -------------------------------------------------------------------------------- /src/Areas/Admin/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/Areas/Client/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Areas.Client.Controllers 8 | { 9 | [Area("Client")] 10 | public class AccountController : Controller 11 | { 12 | public IActionResult Login() 13 | { 14 | return View(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Areas/Client/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Areas.Client.Controllers 8 | { 9 | [Area("Client")] 10 | public class HomeController:Controller 11 | { 12 | public IActionResult Index() 13 | { 14 | return View(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Areas/Client/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | 
2 |

Client login

3 |
4 | 5 |

Provide your client credentials to login as a Client.

6 |
7 |
8 | 9 | 10 |
11 |
12 |
13 | 14 | 15 |
16 |
17 | @**@ 20 | Login 21 |
22 |
-------------------------------------------------------------------------------- /src/Areas/Client/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
2 |

Hi client,

3 |
-------------------------------------------------------------------------------- /src/Areas/Client/Views/Home/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_ClientLayout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/Areas/Client/Views/Shared/_ClientLayout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 | IDENTITY SERVER 17 | 18 |
19 | 20 | 26 |
27 |
28 |
29 | Identity Server 30 | 36 |
37 |
38 |
@RenderBody()
39 |
40 |
41 | 42 | @RenderSection("Scripts", false) 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/Areas/Client/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 2 | -------------------------------------------------------------------------------- /src/Areas/Client/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/Configuration/GlobalConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServer.Dashboard.Configuration 7 | { 8 | public static class GlobalConfiguration 9 | { 10 | public static bool IsRunningTestMode = false; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Configuration/TestConfig/TestUsers.cs: -------------------------------------------------------------------------------- 1 | using IdentityModel; 2 | using IdentityServer4.Test; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Security.Claims; 7 | using System.Threading.Tasks; 8 | 9 | namespace IdentityServer.Dashboard.Configuration.TestConfig 10 | { 11 | public static class TestUsers 12 | { 13 | public static List Users = new List 14 | { 15 | new TestUser{SubjectId = "818727", Username = "alice", Password = "alice", 16 | Claims = 17 | { 18 | new Claim(JwtClaimTypes.Name, "Alice Smith"), 19 | new Claim(JwtClaimTypes.GivenName, "Alice"), 20 | new Claim(JwtClaimTypes.FamilyName, "Smith"), 21 | new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"), 22 | new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), 23 | new Claim(JwtClaimTypes.WebSite, "http://alice.com"), 24 | new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json) 25 | } 26 | }, 27 | new TestUser{SubjectId = "88421113", Username = "bob", Password = "bob", 28 | Claims = 29 | { 30 | new Claim(JwtClaimTypes.Name, "Bob Smith"), 31 | new Claim(JwtClaimTypes.GivenName, "Bob"), 32 | new Claim(JwtClaimTypes.FamilyName, "Smith"), 33 | new Claim(JwtClaimTypes.Email, "BobSmith@email.com"), 34 | new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), 35 | new Claim(JwtClaimTypes.WebSite, "http://bob.com"), 36 | new Claim(JwtClaimTypes.Address, @"{ 'street_address': 'One Hacker Way', 'locality': 'Heidelberg', 'postal_code': 69118, 'country': 'Germany' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json), 37 | new Claim("location", "somewhere") 38 | } 39 | } 40 | }; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Constants/Messages.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServer.Constants 7 | { 8 | public static class Messages 9 | { 10 | public static string USER_NOT_EXISTS = "The specified user doesn't exist.Please try again with the correct credentials"; 11 | public static string USER_ALREADY_EXISTS = "User already exists, please try different credentials"; 12 | public static string USER_INVALID = "User is invalid."; 13 | public static string USER_EXISTS = "User exists."; 14 | public static string USER_NOT_ADMIN = "User does not have administrator priviliges."; 15 | public static string EMAIL_NOT_CONFIRMED = "Email has not yet been confirmed, please confirm your email and try again."; 16 | public static string INVALID_USERNAME_PASSWORD = "Email or password is invalid, please try again."; 17 | public static string GENERATE_TOKEN_FAILED = "could not generate access token , please try again."; 18 | public static string USER_REGISTER_SUCCESS = "user successfully registered."; 19 | public static string USER_NOT_FOUND = "specified user could not be found."; 20 | public static string CLAIM_ALREADY_EXIST = "specified claim is already assigned to user, try different value"; 21 | public static string CLAIM_ADDED = "claim successfully assigned to user."; 22 | public static string CLAIM_ADDING_FAILED = "failed to add claim"; 23 | public static string USER_CLAIM_NOT_ASSIGNED = "user does not have the specified claim assigned."; 24 | public static string CLAIM_REMOVE_SUCCESS = "claim removed successfully."; 25 | public static string CLAIM_REMOVE_FAILED = "failed to remove claim"; 26 | public static string PASSWORD_CHANGE_SUCCESS = "password changed successfully."; 27 | public static string PASSWORD_CHANGE_FAILED = "failed to change password"; 28 | public static string GENERATE_EMAIL_CODE_FAILED = "could not generate email verification code."; 29 | public static string GENERATE_EMAIL_CODE_SUCCESS = "email verification code generated successfully."; 30 | public static string PASSWORD_RESET_SUCCEESS = "password was reset successfully."; 31 | public static string PASSWORD_RESET_FAILED = "password reset failed."; 32 | public static string EMAIL_CONFIRM_SUCCESS = "email confirmed successfully."; 33 | public static string EMAIL_CONFIRM_FAILED = "email confirmation failed."; 34 | 35 | public static string INVALID_LOGIN_REQUEST = "Invalid Login Request."; 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Constants/Policies.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServer.Constants 7 | { 8 | public class Policies 9 | { 10 | public const string ID_SERVER_ADMIN_POLICY = "IdSrvAdmin"; 11 | public const string ID_SERVER_CORS_POLICY = "Cors"; 12 | public const string ID_SERVER_ADMIN_REQUIRED_CLAIM = "IdSrvAdmin"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Constants/Roles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServer.Constants 7 | { 8 | public class Roles 9 | { 10 | public const string ROLE_SUPER_ADMIN = "SuperAdmin"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Controllers/Account/AccountOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System; 6 | 7 | namespace IdentityServer.Dashboard 8 | { 9 | public class AccountOptions 10 | { 11 | public static bool AllowLocalLogin = true; 12 | public static bool AllowRememberLogin = true; 13 | public static TimeSpan RememberMeLoginDuration = TimeSpan.FromDays(30); 14 | 15 | public static bool ShowLogoutPrompt = true; 16 | public static bool AutomaticRedirectAfterSignOut = false; 17 | 18 | // to enable windows authentication, the host (IIS or IIS Express) also must have 19 | // windows auth enabled. 20 | public static bool WindowsAuthenticationEnabled = true; 21 | public static bool IncludeWindowsGroups = false; 22 | // specify the Windows authentication scheme and display name 23 | public static readonly string WindowsAuthenticationSchemeName = "Windows"; 24 | 25 | public static string InvalidCredentialsErrorMessage = "Invalid username or password"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Controllers/Account/ExternalProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer.Dashboard 6 | { 7 | public class ExternalProvider 8 | { 9 | public string DisplayName { get; set; } 10 | public string AuthenticationScheme { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Controllers/Account/LoggedOutViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer.Dashboard 6 | { 7 | public class LoggedOutViewModel 8 | { 9 | public string PostLogoutRedirectUri { get; set; } 10 | public string ClientName { get; set; } 11 | public string SignOutIframeUrl { get; set; } 12 | 13 | public bool AutomaticRedirectAfterSignOut { get; set; } 14 | 15 | public string LogoutId { get; set; } 16 | public bool TriggerExternalSignout => ExternalAuthenticationScheme != null; 17 | public string ExternalAuthenticationScheme { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/Controllers/Account/LoginInputModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.ComponentModel.DataAnnotations; 6 | 7 | namespace IdentityServer.Dashboard 8 | { 9 | public class LoginInputModel 10 | { 11 | [Required] 12 | public string Username { get; set; } 13 | [Required] 14 | public string Password { get; set; } 15 | public bool RememberLogin { get; set; } 16 | public string ReturnUrl { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Controllers/Account/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | 9 | namespace IdentityServer.Dashboard 10 | { 11 | public class LoginViewModel : LoginInputModel 12 | { 13 | public bool AllowRememberLogin { get; set; } 14 | public bool EnableLocalLogin { get; set; } 15 | 16 | public IEnumerable ExternalProviders { get; set; } 17 | public IEnumerable VisibleExternalProviders => ExternalProviders.Where(x => !String.IsNullOrWhiteSpace(x.DisplayName)); 18 | 19 | public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1; 20 | public string ExternalLoginScheme => ExternalProviders?.SingleOrDefault()?.AuthenticationScheme; 21 | } 22 | } -------------------------------------------------------------------------------- /src/Controllers/Account/LogoutInputModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer.Dashboard 6 | { 7 | public class LogoutInputModel 8 | { 9 | public string LogoutId { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Controllers/Account/LogoutViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer.Dashboard 6 | { 7 | public class LogoutViewModel : LogoutInputModel 8 | { 9 | public bool ShowLogoutPrompt { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Controllers/Consent/ConsentController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityServer4.Services; 6 | using IdentityServer4.Stores; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.Extensions.Logging; 9 | using System.Threading.Tasks; 10 | 11 | namespace IdentityServer.Dashboard 12 | { 13 | /// 14 | /// This controller processes the consent UI 15 | /// 16 | [SecurityHeaders] 17 | public class ConsentController : Controller 18 | { 19 | private readonly ConsentService _consent; 20 | 21 | public ConsentController( 22 | IIdentityServerInteractionService interaction, 23 | IClientStore clientStore, 24 | IResourceStore resourceStore, 25 | ILogger logger) 26 | { 27 | _consent = new ConsentService(interaction, clientStore, resourceStore, logger); 28 | } 29 | 30 | /// 31 | /// Shows the consent screen 32 | /// 33 | /// 34 | /// 35 | [HttpGet] 36 | public async Task Index(string returnUrl) 37 | { 38 | var vm = await _consent.BuildViewModelAsync(returnUrl); 39 | if (vm != null) 40 | { 41 | return View("Index", vm); 42 | } 43 | 44 | return View("Error"); 45 | } 46 | 47 | /// 48 | /// Handles the consent screen postback 49 | /// 50 | [HttpPost] 51 | [ValidateAntiForgeryToken] 52 | public async Task Index(ConsentInputModel model) 53 | { 54 | var result = await _consent.ProcessConsent(model); 55 | 56 | if (result.IsRedirect) 57 | { 58 | return Redirect(result.RedirectUri); 59 | } 60 | 61 | if (result.HasValidationError) 62 | { 63 | ModelState.AddModelError("", result.ValidationError); 64 | } 65 | 66 | if (result.ShowView) 67 | { 68 | return View("Index", result.ViewModel); 69 | } 70 | 71 | return View("Error"); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /src/Controllers/Consent/ConsentInputModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.Collections.Generic; 6 | 7 | namespace IdentityServer.Dashboard 8 | { 9 | public class ConsentInputModel 10 | { 11 | public string Button { get; set; } 12 | public IEnumerable ScopesConsented { get; set; } 13 | public bool RememberConsent { get; set; } 14 | public string ReturnUrl { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Controllers/Consent/ConsentOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer.Dashboard 6 | { 7 | public class ConsentOptions 8 | { 9 | public static bool EnableOfflineAccess = true; 10 | public static string OfflineAccessDisplayName = "Offline Access"; 11 | public static string OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; 12 | 13 | public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission"; 14 | public static readonly string InvalidSelectionErrorMessage = "Invalid selection"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Controllers/Consent/ConsentViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using System.Collections.Generic; 6 | 7 | namespace IdentityServer.Dashboard 8 | { 9 | public class ConsentViewModel : ConsentInputModel 10 | { 11 | public string ClientName { get; set; } 12 | public string ClientUrl { get; set; } 13 | public string ClientLogoUrl { get; set; } 14 | public bool AllowRememberConsent { get; set; } 15 | 16 | public IEnumerable IdentityScopes { get; set; } 17 | public IEnumerable ResourceScopes { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Controllers/Consent/ProcessConsentResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer.Dashboard 6 | { 7 | public class ProcessConsentResult 8 | { 9 | public bool IsRedirect => RedirectUri != null; 10 | public string RedirectUri { get; set; } 11 | 12 | public bool ShowView => ViewModel != null; 13 | public ConsentViewModel ViewModel { get; set; } 14 | 15 | public bool HasValidationError => ValidationError != null; 16 | public string ValidationError { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Controllers/Consent/ScopeViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | namespace IdentityServer.Dashboard 6 | { 7 | public class ScopeViewModel 8 | { 9 | public string Name { get; set; } 10 | public string DisplayName { get; set; } 11 | public string Description { get; set; } 12 | public bool Emphasize { get; set; } 13 | public bool Required { get; set; } 14 | public bool Checked { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Controllers/Grants/GrantsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace IdentityServer.Dashboard 5 | { 6 | public class GrantsViewModel 7 | { 8 | public IEnumerable Grants { get; set; } 9 | } 10 | 11 | public class GrantViewModel 12 | { 13 | public string ClientId { get; set; } 14 | public string ClientName { get; set; } 15 | public string ClientUrl { get; set; } 16 | public string ClientLogoUrl { get; set; } 17 | public DateTime Created { get; set; } 18 | public DateTime? Expires { get; set; } 19 | public IEnumerable IdentityGrantNames { get; set; } 20 | public IEnumerable ApiGrantNames { get; set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Controllers/Home/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityServer4.Models; 6 | 7 | namespace IdentityServer.Dashboard 8 | { 9 | public class ErrorViewModel 10 | { 11 | public ErrorMessage Error { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/Controllers/Home/HomeController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using IdentityServer4.Services; 6 | using Microsoft.AspNetCore.Mvc; 7 | using System.Threading.Tasks; 8 | 9 | namespace IdentityServer.Dashboard 10 | { 11 | // [SecurityHeaders] 12 | public class HomeController : Controller 13 | { 14 | private readonly IIdentityServerInteractionService _interaction; 15 | 16 | public HomeController(IIdentityServerInteractionService interaction) 17 | { 18 | _interaction = interaction; 19 | } 20 | 21 | public IActionResult Index() 22 | { 23 | return View(); 24 | } 25 | 26 | /// 27 | /// Shows the error page 28 | /// 29 | public async Task Error(string errorId) 30 | { 31 | var vm = new ErrorViewModel(); 32 | 33 | // retrieve error details from identityserver 34 | var message = await _interaction.GetErrorContextAsync(errorId); 35 | if (message != null) 36 | { 37 | vm.Error = message; 38 | } 39 | 40 | return View("Error", vm); 41 | } 42 | 43 | public IActionResult About() 44 | { 45 | return View(); 46 | } 47 | 48 | [Route("getting-started")] 49 | public IActionResult GettingStarted() 50 | { 51 | return View(); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Controllers 8 | { 9 | public class HomeController:Controller 10 | { 11 | public IActionResult Index() 12 | { 13 | return View(); 14 | } 15 | public IActionResult About() 16 | { 17 | return View(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Data/DatabaseContext.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace IdentityServer.Data 10 | { 11 | public class DatabaseContext:IdentityDbContext 12 | { 13 | public DatabaseContext(DbContextOptions options) 14 | : base(options) 15 | { 16 | 17 | 18 | } 19 | 20 | public DbSet ExternalUsers { get; set; } 21 | public DbSet PasswordConfigs { get; set; } 22 | public DbSet Providers { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Data/Entities/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Data.Entities 8 | { 9 | public class ApplicationUser:IdentityUser 10 | { 11 | public string ClientId { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Data/Entities/ExternalUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Data.Entities 8 | { 9 | public class ExternalUser 10 | { 11 | public int Id { get; set; } 12 | public string Provider { get; set; } 13 | 14 | public string ExternalId { get; set; } 15 | 16 | public string UserId { get; set; } 17 | 18 | [ForeignKey("UserId")] 19 | public virtual ApplicationUser User { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Data/Entities/PasswordConfigs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServer.Data.Entities 7 | { 8 | public class PasswordConfigs 9 | { 10 | public int Id { get; set; } 11 | public string ClientId { get; set; } 12 | public int RequiredLength { get; set; } = 6; 13 | public int RequiredUniqueChars { get; set; } = 1; 14 | public bool RequireNonAlphanumeric { get; set; } = false; 15 | public bool RequireLowercase { get; set; } = false; 16 | public bool RequireUppercase { get; set; } = false; 17 | public bool RequireDigit { get; set; } = false; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Data/Entities/Provider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Data.Entities 8 | { 9 | public class Provider 10 | { 11 | [Key] 12 | public int ProviderId { get; set; } 13 | public string Name { get; set; } 14 | public string UserInfoEndPoint { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Extensions/DbContextExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Infrastructure; 3 | using Microsoft.EntityFrameworkCore.Migrations; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace IdentityServer.Extensions 10 | { 11 | 12 | public static class DbContextExtensions 13 | { 14 | public static bool AllMigrationsApplied(this DbContext context) 15 | { 16 | var applied = context.GetService() 17 | .GetAppliedMigrations() 18 | .Select(m => m.MigrationId); 19 | 20 | var total = context.GetService() 21 | .Migrations 22 | .Select(m => m.Key); 23 | 24 | return !total.Except(applied).Any(); 25 | } 26 | 27 | public static void RunAllPendingMigrations(this DbContext context) 28 | { 29 | if (!context.AllMigrationsApplied()) 30 | context.Database.Migrate(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Extensions/UserManagerExtensions.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Constants; 2 | using IdentityServer.Data.Entities; 3 | using Microsoft.AspNetCore.Identity; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Security.Claims; 7 | using System.Threading.Tasks; 8 | 9 | namespace IdentityServer.Extensions 10 | { 11 | public static class UserManagerExtensions 12 | { 13 | public static ApplicationUser FindByClientId(this UserManager userManager,string clientId) 14 | { 15 | return userManager.Users.FirstOrDefault(x => x.ClientId.ToLower() == clientId.ToLower()); 16 | } 17 | 18 | public static ApplicationUser FindByClientId(this UserManager userManager, string clientId,string email) 19 | { 20 | return userManager 21 | .Users 22 | .FirstOrDefault(x => x.ClientId.ToLower().Equals(clientId.ToLower()) && x.Email.Equals(email)); 23 | } 24 | 25 | public static async Task IsSuperAdmin(this UserManager userManager, ApplicationUser user) 26 | { 27 | var claims = await userManager.GetClaimsAsync(user); 28 | if (!claims.Any()) 29 | return false; 30 | 31 | return claims. 32 | FirstOrDefault(x => x.Type == ClaimTypes.Role && x.Value == Roles.ROLE_SUPER_ADMIN) == null; 33 | 34 | } 35 | 36 | public static List GetAllUsers(this UserManager userManager) 37 | { 38 | return userManager.Users.ToList(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Filters/SecurityHeadersAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. 3 | 4 | 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.Filters; 7 | 8 | namespace IdentityServer.Dashboard 9 | { 10 | public class SecurityHeadersAttribute : ActionFilterAttribute 11 | { 12 | public override void OnResultExecuting(ResultExecutingContext context) 13 | { 14 | //var result = context.Result; 15 | //if (result is ViewResult) 16 | //{ 17 | // if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) 18 | // { 19 | // context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); 20 | // } 21 | // if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) 22 | // { 23 | // context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); 24 | // } 25 | 26 | // var csp = "default-src 'self';"; 27 | // // an example if you need client images to be displayed from twitter 28 | // //var csp = "default-src 'self'; img-src 'self' https://pbs.twimg.com"; 29 | 30 | // // once for standards compliant browsers 31 | // if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) 32 | // { 33 | // context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); 34 | // } 35 | // // and once again for IE 36 | // if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) 37 | // { 38 | // context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); 39 | // } 40 | //} 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Filters/ValidateModelState.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Models; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Mvc.Filters; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace IdentityServer 10 | { 11 | public class ValidateModelState : ActionFilterAttribute 12 | { 13 | public override void OnActionExecuting(ActionExecutingContext context) 14 | { 15 | if (!context.ModelState.IsValid) 16 | { 17 | var validationErrors = string.Join(",", 18 | context.ModelState.Values.Where(E => E.Errors.Count > 0) 19 | .SelectMany(E => E.Errors) 20 | .Select(E => E.ErrorMessage) 21 | .ToArray()); 22 | 23 | context.Result = new ObjectResult(BaseModel.Error(validationErrors)); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Helpers/ProviderType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServer.Helpers 7 | { 8 | public enum ProviderType 9 | { 10 | Facebook, 11 | Twitter, 12 | Google, 13 | LinkedIn 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/IdentityServer.Dashboard.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | All 31 | 32 | 33 | 34 | All 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/Interfaces/ExternalProviders/IExternalAuthProvider.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Interfaces.ExternalProviders 8 | { 9 | public interface IExternalAuthProvider 10 | { 11 | JObject GetUserInfo(string accessToken); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Interfaces/ExternalProviders/IFacebookAuthProvider.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Interfaces.ExternalProviders 8 | { 9 | public interface IFacebookAuthProvider : IExternalAuthProvider 10 | { 11 | Provider Provider { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Interfaces/ExternalProviders/IGoogleAuthProvider.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Interfaces.ExternalProviders 8 | { 9 | public interface IGoogleAuthProvider:IExternalAuthProvider 10 | { 11 | Provider Provider { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Interfaces/ExternalProviders/ILinkedInAuthProvider.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Interfaces.ExternalProviders 8 | { 9 | public interface ILinkedInAuthProvider : IExternalAuthProvider 10 | { 11 | Provider Provider { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Interfaces/ExternalProviders/ITwitterAuthProvider.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Interfaces.ExternalProviders 8 | { 9 | public interface ITwitterAuthProvider : IExternalAuthProvider 10 | { 11 | Provider Provider { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Interfaces/IdentityServer/IClientService.cs: -------------------------------------------------------------------------------- 1 |  2 | using IdentityServer4.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityServer.Interfaces.IdentityServer 9 | { 10 | public interface IClientService 11 | { 12 | bool SetClientStatus(string clientId, bool enableStatus); 13 | Task AddClient(Client client); 14 | Task GetClientById(string Id); 15 | void Update(Client client); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Interfaces/Processors/IEmailUserProcessor.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer4.Validation; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityServer.Interfaces.Processors 9 | { 10 | public interface IEmailUserProcessor 11 | { 12 | Task Process(JObject userInfo,string email, string provider); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Interfaces/Processors/INonEmailUserProcessor.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer4.Validation; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityServer.Interfaces.Processors 9 | { 10 | public interface INonEmailUserProcessor 11 | { 12 | Task Process(JObject userInfo,string provider); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Interfaces/SecurityService/IIdentityResult.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Interfaces.SecurityService 8 | { 9 | public interface IIdentityResult 10 | { 11 | Object Transform(T user, object extra = null) 12 | where TKey : IEquatable 13 | where T : IdentityUser; 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Interfaces/SecurityService/ISecurityService.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using IdentityServer.Models; 3 | using Microsoft.AspNetCore.Identity; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace IdentityServer.Interfaces.SecurityService 10 | { 11 | public interface ISecurityServiceBase where T: IdentityUser 12 | { 13 | Task CreateUser(T user, string password,bool createActivated) where TMap : class, IIdentityResult, new(); 14 | Task Login(string clientID, string clientSecret, string email, string password, string scopes); 15 | Task GetPasswordResetToken(string email); 16 | Task GetEmailVerificationToken(string email); 17 | Task VerifyEmail(string userId, string verificationToken); 18 | Task ResetPassword(string userId, string resetToken, string newPassword); 19 | 20 | Task AddUserClaim(string userId, string claimType, string claimValue); 21 | Task RemoveUserClaim(string userId, string claimType, string claimValue); 22 | 23 | Task UserExists(string email); 24 | Task ChangePassword(string email, string currentPassword, string newPassword); 25 | 26 | 27 | 28 | } 29 | 30 | public interface ISecurityService: ISecurityServiceBase 31 | { 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Interfaces/SecurityService/ITokenService.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Interfaces.SecurityService 8 | { 9 | public interface ITokenService 10 | { 11 | Task GetToken(string clientId, string clientSecret, string email, string password, string scopes); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Migrations/20170928121323_client_id_field_added.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace IdentityServer.Migrations 6 | { 7 | public partial class client_id_field_added : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.AddColumn( 12 | name: "ClientId", 13 | table: "AspNetUsers", 14 | type: "longtext", 15 | nullable: true); 16 | } 17 | 18 | protected override void Down(MigrationBuilder migrationBuilder) 19 | { 20 | migrationBuilder.DropColumn( 21 | name: "ClientId", 22 | table: "AspNetUsers"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Migrations/20170929054125_config_tables.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace IdentityServer.Migrations 7 | { 8 | public partial class config_tables : Migration 9 | { 10 | protected override void Up(MigrationBuilder migrationBuilder) 11 | { 12 | migrationBuilder.CreateTable( 13 | name: "PasswordConfigs", 14 | columns: table => new 15 | { 16 | Id = table.Column(type: "int", nullable: false) 17 | .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), 18 | ClientId = table.Column(type: "longtext", nullable: true), 19 | RequireDigit = table.Column(type: "bit", nullable: false), 20 | RequireLowercase = table.Column(type: "bit", nullable: false), 21 | RequireNonAlphanumeric = table.Column(type: "bit", nullable: false), 22 | RequireUppercase = table.Column(type: "bit", nullable: false), 23 | RequiredLength = table.Column(type: "int", nullable: false), 24 | RequiredUniqueChars = table.Column(type: "int", nullable: false) 25 | }, 26 | constraints: table => 27 | { 28 | table.PrimaryKey("PK_PasswordConfigs", x => x.Id); 29 | }); 30 | 31 | migrationBuilder.CreateTable( 32 | name: "Providers", 33 | columns: table => new 34 | { 35 | ProviderId = table.Column(type: "int", nullable: false) 36 | .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), 37 | Name = table.Column(type: "longtext", nullable: true), 38 | UserInfoEndPoint = table.Column(type: "longtext", nullable: true) 39 | }, 40 | constraints: table => 41 | { 42 | table.PrimaryKey("PK_Providers", x => x.ProviderId); 43 | }); 44 | } 45 | 46 | protected override void Down(MigrationBuilder migrationBuilder) 47 | { 48 | migrationBuilder.DropTable( 49 | name: "PasswordConfigs"); 50 | 51 | migrationBuilder.DropTable( 52 | name: "Providers"); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Migrations/PersistedGrantDb/20170925053610_init_grans.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using IdentityServer4.EntityFramework.DbContexts; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage; 8 | using Microsoft.EntityFrameworkCore.Storage.Internal; 9 | using System; 10 | 11 | namespace IdentityServer.Migrations.PersistedGrantDb 12 | { 13 | [DbContext(typeof(PersistedGrantDbContext))] 14 | [Migration("20170925053610_init_grans")] 15 | partial class init_grans 16 | { 17 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 18 | { 19 | #pragma warning disable 612, 618 20 | modelBuilder 21 | .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) 22 | .HasAnnotation("ProductVersion", "2.0.0-rtm-26452"); 23 | 24 | modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => 25 | { 26 | b.Property("Key") 27 | .HasMaxLength(200); 28 | 29 | b.Property("ClientId") 30 | .IsRequired() 31 | .HasMaxLength(200); 32 | 33 | b.Property("CreationTime"); 34 | 35 | b.Property("Data") 36 | .IsRequired() 37 | .HasMaxLength(50000); 38 | 39 | b.Property("Expiration"); 40 | 41 | b.Property("SubjectId") 42 | .HasMaxLength(200); 43 | 44 | b.Property("Type") 45 | .IsRequired() 46 | .HasMaxLength(50); 47 | 48 | b.HasKey("Key"); 49 | 50 | b.HasIndex("SubjectId", "ClientId", "Type"); 51 | 52 | b.ToTable("PersistedGrants"); 53 | }); 54 | #pragma warning restore 612, 618 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Migrations/PersistedGrantDb/20170925053610_init_grans.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace IdentityServer.Migrations.PersistedGrantDb 6 | { 7 | public partial class init_grans : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "PersistedGrants", 13 | columns: table => new 14 | { 15 | Key = table.Column(type: "varchar(200)", maxLength: 200, nullable: false), 16 | ClientId = table.Column(type: "varchar(200)", maxLength: 200, nullable: false), 17 | CreationTime = table.Column(type: "datetime(6)", nullable: false), 18 | Data = table.Column(type: "longtext", maxLength: 50000, nullable: false), 19 | Expiration = table.Column(type: "datetime(6)", nullable: true), 20 | SubjectId = table.Column(type: "varchar(200)", maxLength: 200, nullable: true), 21 | Type = table.Column(type: "varchar(50)", maxLength: 50, nullable: false) 22 | }, 23 | constraints: table => 24 | { 25 | table.PrimaryKey("PK_PersistedGrants", x => x.Key); 26 | }); 27 | 28 | migrationBuilder.CreateIndex( 29 | name: "IX_PersistedGrants_SubjectId_ClientId_Type", 30 | table: "PersistedGrants", 31 | columns: new[] { "SubjectId", "ClientId", "Type" }); 32 | } 33 | 34 | protected override void Down(MigrationBuilder migrationBuilder) 35 | { 36 | migrationBuilder.DropTable( 37 | name: "PersistedGrants"); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Migrations/PersistedGrantDb/PersistedGrantDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using IdentityServer4.EntityFramework.DbContexts; 3 | using Microsoft.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | using Microsoft.EntityFrameworkCore.Metadata; 6 | using Microsoft.EntityFrameworkCore.Migrations; 7 | using Microsoft.EntityFrameworkCore.Storage; 8 | using Microsoft.EntityFrameworkCore.Storage.Internal; 9 | using System; 10 | 11 | namespace IdentityServer.Migrations.PersistedGrantDb 12 | { 13 | [DbContext(typeof(PersistedGrantDbContext))] 14 | partial class PersistedGrantDbContextModelSnapshot : ModelSnapshot 15 | { 16 | protected override void BuildModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) 21 | .HasAnnotation("ProductVersion", "2.0.0-rtm-26452"); 22 | 23 | modelBuilder.Entity("IdentityServer4.EntityFramework.Entities.PersistedGrant", b => 24 | { 25 | b.Property("Key") 26 | .HasMaxLength(200); 27 | 28 | b.Property("ClientId") 29 | .IsRequired() 30 | .HasMaxLength(200); 31 | 32 | b.Property("CreationTime"); 33 | 34 | b.Property("Data") 35 | .IsRequired() 36 | .HasMaxLength(50000); 37 | 38 | b.Property("Expiration"); 39 | 40 | b.Property("SubjectId") 41 | .HasMaxLength(200); 42 | 43 | b.Property("Type") 44 | .IsRequired() 45 | .HasMaxLength(50); 46 | 47 | b.HasKey("Key"); 48 | 49 | b.HasIndex("SubjectId", "ClientId", "Type"); 50 | 51 | b.ToTable("PersistedGrants"); 52 | }); 53 | #pragma warning restore 612, 618 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Models/BaseModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServer.Models 7 | { 8 | public class BaseModel 9 | { 10 | public bool success { get; set; } 11 | public object data { get; set; } 12 | public string message { get; set; } 13 | public int total { get; set; } 14 | 15 | public BaseModel() 16 | { 17 | 18 | } 19 | 20 | public BaseModel(bool success, object data = null, string message = "", int total = 0) 21 | { 22 | this.success = success; 23 | this.data = data; 24 | this.message = message; 25 | this.total = total; 26 | } 27 | 28 | public static BaseModel Create(bool success, object data = null, string message = "", int total = 0) 29 | { 30 | return new BaseModel() { success = success, data = data, message = message, total = total }; 31 | } 32 | 33 | public static BaseModel Error(string message, object data = null, int total = 0) 34 | { 35 | return new BaseModel(false, data, message, total); 36 | } 37 | 38 | public static BaseModel Success(object data = null, int total = 0, string message = "") 39 | { 40 | return new BaseModel(true, data, message, total); 41 | } 42 | 43 | public static BaseModel Success(string message) 44 | { 45 | return new BaseModel 46 | { 47 | success = true, 48 | message = message 49 | }; 50 | } 51 | public static BaseModel Success(string msg,object data) 52 | { 53 | return new BaseModel 54 | { 55 | success = true, 56 | message = msg, 57 | data = data 58 | }; 59 | } 60 | 61 | public static BaseModel Error(string msg) 62 | { 63 | return new BaseModel 64 | { 65 | success = false, 66 | message = msg, 67 | data = null 68 | }; 69 | } 70 | 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Processors/EmailUserProcessor.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Interfaces.Processors; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using IdentityServer4.Validation; 7 | using IdentityServer.Repositories.Interfaces; 8 | using IdentityServer.Data.Entities; 9 | using Microsoft.AspNetCore.Identity; 10 | using Newtonsoft.Json.Linq; 11 | using IdentityServer4.Models; 12 | using IdentityServer.Data; 13 | using IdentityServer.Repositories.UnitOfWork; 14 | 15 | namespace IdentityServer.Processors 16 | { 17 | public class EmailUserProcessor : IEmailUserProcessor 18 | { 19 | private readonly IExternalUserRepository _externalUserRepository; 20 | private readonly UserManager _userManager; 21 | private readonly IUnitOfWork _unitOfWork; 22 | public EmailUserProcessor( 23 | IExternalUserRepository externalUserRepository, 24 | UserManager userManager, 25 | IUnitOfWork unitOfWork 26 | ) 27 | { 28 | _externalUserRepository = externalUserRepository ?? throw new ArgumentNullException(nameof(externalUserRepository)); 29 | _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); 30 | _unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork)); 31 | } 32 | public async Task Process(JObject userInfo,string email,string provider) 33 | { 34 | var userEmail = email; 35 | var userExternalId = userInfo.Value("id"); 36 | 37 | if (string.IsNullOrWhiteSpace(userExternalId)) 38 | { 39 | return new GrantValidationResult(TokenRequestErrors.InvalidRequest, "could not retrieve user Id from the token provided"); 40 | 41 | } 42 | 43 | var existingUser = _userManager.FindByEmailAsync(userEmail).Result; 44 | if(existingUser != null) 45 | { 46 | return new GrantValidationResult(TokenRequestErrors.InvalidRequest, "User with specified email already exists"); 47 | } 48 | 49 | var new_user = new ApplicationUser { Email = userEmail ,UserName = userEmail}; 50 | var identityResult = await _userManager.CreateAsync(new_user); 51 | if (identityResult.Succeeded) 52 | { 53 | await _externalUserRepository.AddAsync(new ExternalUser { ExternalId = userExternalId, Provider = provider, UserId = new_user.Id }).ConfigureAwait(false); 54 | await _unitOfWork.SaveChangesAsync(); 55 | var userClaims = _userManager.GetClaimsAsync(new_user).Result; 56 | return new GrantValidationResult(new_user.Id, provider, userClaims, provider, null); 57 | 58 | } 59 | return new GrantValidationResult(TokenRequestErrors.InvalidRequest, "could not create user , please try again."); 60 | 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | 11 | namespace IdentityServer 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | BuildWebHost(args).Run(); 18 | } 19 | 20 | public static IWebHost BuildWebHost(string[] args) => 21 | WebHost.CreateDefaultBuilder(args) 22 | .UseStartup() 23 | .ConfigureAppConfiguration((hostingContext,config) => 24 | { 25 | var env = hostingContext.HostingEnvironment; 26 | config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); 27 | 28 | }) 29 | .Build(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Providers/FacebookAuthProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Newtonsoft.Json.Linq; 5 | using IdentityServer.Repositories.Interfaces; 6 | using IdentityServer.Data.Entities; 7 | using IdentityServer.Helpers; 8 | using System.Net.Http; 9 | using IdentityServer.Interfaces.ExternalProviders; 10 | 11 | namespace IdentityServer.Providers 12 | { 13 | public class FacebookAuthProvider : IFacebookAuthProvider 14 | { 15 | private readonly IExternalUserRepository _externalUserRepository; 16 | private readonly IProviderRepository _providerRepository; 17 | private readonly HttpClient _httpClient; 18 | public FacebookAuthProvider( 19 | IExternalUserRepository externalUserRepository, 20 | IProviderRepository providerRepository, 21 | HttpClient httpClient 22 | ) 23 | { 24 | _externalUserRepository = externalUserRepository; 25 | _providerRepository = providerRepository; 26 | _httpClient = httpClient; 27 | } 28 | 29 | public Provider Provider => _providerRepository.Get() 30 | .FirstOrDefault(x => x.Name.ToLower() == ProviderType.Facebook.ToString().ToLower()); 31 | 32 | public JObject GetUserInfo(string accessToken) 33 | { 34 | if(Provider == null) 35 | { 36 | throw new ArgumentNullException(nameof(Provider)); 37 | } 38 | 39 | var request = new Dictionary(); 40 | 41 | request.Add("fields", "id,email,name,gender,birthday"); 42 | request.Add("access_token", accessToken); 43 | 44 | var result = _httpClient.GetAsync(Provider.UserInfoEndPoint + QueryBuilder.GetQuery(request, ProviderType.Facebook)).Result; 45 | if (result.IsSuccessStatusCode) 46 | { 47 | var infoObject = JObject.Parse(result.Content.ReadAsStringAsync().Result); 48 | return infoObject; 49 | } 50 | return null; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Providers/GoogleAuthProvider.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using IdentityServer.Data.Entities; 7 | using Newtonsoft.Json.Linq; 8 | using IdentityServer.Repositories.Interfaces; 9 | using System.Net.Http; 10 | using IdentityServer.Helpers; 11 | using IdentityServer.Interfaces.ExternalProviders; 12 | 13 | namespace IdentityServer.Providers 14 | { 15 | public class GoogleAuthProvider : IGoogleAuthProvider 16 | { 17 | private readonly IExternalUserRepository _externalUserRepository; 18 | private readonly IProviderRepository _providerRepository; 19 | private readonly HttpClient _httpClient; 20 | public GoogleAuthProvider( 21 | IExternalUserRepository externalUserRepository, 22 | IProviderRepository providerRepository, 23 | HttpClient httpClient 24 | ) 25 | { 26 | _externalUserRepository = externalUserRepository; 27 | _providerRepository = providerRepository; 28 | _httpClient = httpClient; 29 | } 30 | public Provider Provider => _providerRepository.Get() 31 | .FirstOrDefault(x => x.Name.ToLower() == ProviderType.Google.ToString().ToLower()); 32 | public JObject GetUserInfo(string accessToken) 33 | { 34 | var request = new Dictionary(); 35 | request.Add("token", accessToken); 36 | 37 | var result = _httpClient.GetAsync(Provider.UserInfoEndPoint + QueryBuilder.GetQuery(request, ProviderType.Google)).Result; 38 | if (result.IsSuccessStatusCode) 39 | { 40 | var infoObject = JObject.Parse(result.Content.ReadAsStringAsync().Result); 41 | return infoObject; 42 | } 43 | return null; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Providers/LinkedInAuthProvider.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using IdentityServer.Data.Entities; 7 | using Newtonsoft.Json.Linq; 8 | using IdentityServer.Repositories.Interfaces; 9 | using System.Net.Http; 10 | using IdentityServer.Helpers; 11 | using IdentityServer.Interfaces.ExternalProviders; 12 | 13 | namespace IdentityServer.Providers 14 | { 15 | public class LinkedInAuthProvider : ILinkedInAuthProvider 16 | { 17 | private readonly IExternalUserRepository _externalUserRepository; 18 | private readonly IProviderRepository _providerRepository; 19 | private readonly HttpClient _httpClient; 20 | public LinkedInAuthProvider( 21 | IExternalUserRepository externalUserRepository, 22 | IProviderRepository providerRepository, 23 | HttpClient httpClient 24 | ) 25 | { 26 | _externalUserRepository = externalUserRepository; 27 | _providerRepository = providerRepository; 28 | _httpClient = httpClient; 29 | } 30 | public Provider Provider => _providerRepository.Get() 31 | .FirstOrDefault(x => x.Name.ToLower() == ProviderType.LinkedIn.ToString().ToLower()); 32 | 33 | public JObject GetUserInfo(string accessToken) 34 | { 35 | var urlParams = $"oauth2_access_token={accessToken}&format=json"; 36 | 37 | var result = _httpClient.GetAsync($"{Provider.UserInfoEndPoint}{urlParams}").Result; 38 | if (result.IsSuccessStatusCode) 39 | { 40 | var infoObject = JObject.Parse(result.Content.ReadAsStringAsync().Result); 41 | return infoObject; 42 | } 43 | return null; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Providers/TwitterAuthProvider.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using IdentityServer.Data.Entities; 7 | using Newtonsoft.Json.Linq; 8 | using IdentityServer.Repositories.Interfaces; 9 | using System.Net.Http; 10 | using IdentityServer.Helpers; 11 | using System.Net.Http.Headers; 12 | using IdentityServer.Interfaces.ExternalProviders; 13 | 14 | namespace IdentityServer.Providers 15 | { 16 | public class TwitterAuthProvider : ITwitterAuthProvider 17 | { 18 | private readonly IExternalUserRepository _externalUserRepository; 19 | private readonly IProviderRepository _providerRepository; 20 | private readonly HttpClient _httpClient; 21 | public TwitterAuthProvider( 22 | IExternalUserRepository externalUserRepository, 23 | IProviderRepository providerRepository, 24 | HttpClient httpClient 25 | ) 26 | { 27 | _externalUserRepository = externalUserRepository; 28 | _providerRepository = providerRepository; 29 | _httpClient = httpClient; 30 | } 31 | public Provider Provider => _providerRepository.Get() 32 | .FirstOrDefault(x => x.Name.ToLower() == ProviderType.Twitter.ToString().ToLower()); 33 | 34 | public JObject GetUserInfo(string accessToken) 35 | { 36 | if (Provider == null) 37 | { 38 | throw new ArgumentNullException(nameof(Provider)); 39 | } 40 | 41 | var request = new Dictionary(); 42 | request.Add("tokenString", accessToken); 43 | request.Add("endpoint", Provider.UserInfoEndPoint); 44 | 45 | var authorizationHeaderParams = QueryBuilder.GetQuery(request, ProviderType.Twitter); 46 | 47 | _httpClient.DefaultRequestHeaders.Clear(); 48 | _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded")); 49 | _httpClient.DefaultRequestHeaders.Add("Authorization", authorizationHeaderParams); 50 | 51 | var result = _httpClient.GetAsync(Provider.UserInfoEndPoint).Result; 52 | 53 | if (result.IsSuccessStatusCode) 54 | { 55 | var infoObject = JObject.Parse(result.Content.ReadAsStringAsync().Result); 56 | return infoObject; 57 | } 58 | return null; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Repositories/ExternalUserRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data; 2 | using IdentityServer.Data.Entities; 3 | using IdentityServer.Repositories.Interfaces; 4 | using Microsoft.EntityFrameworkCore; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace IdentityServer.Repositories 11 | { 12 | 13 | 14 | public class ExternalUserRepository : GenericRepository, IExternalUserRepository 15 | { 16 | public ExternalUserRepository(DatabaseContext dbContext) : base(dbContext) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Repositories/GenericRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Repositories.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using System.Linq.Expressions; 7 | using IdentityServer.Data; 8 | using Microsoft.EntityFrameworkCore; 9 | 10 | namespace IdentityServer.Repositories 11 | { 12 | public class GenericRepository : IRepository where T : class 13 | { 14 | private readonly DatabaseContext _dbContext; 15 | private readonly DbSet _dbSet; 16 | public GenericRepository(DatabaseContext dbContext) 17 | { 18 | _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); 19 | _dbSet = _dbContext.Set(); 20 | } 21 | public async Task AddAsync(T entity) 22 | { 23 | await _dbSet.AddAsync(entity).ConfigureAwait(false); 24 | await _dbContext.SaveChangesAsync(); 25 | } 26 | 27 | public async Task AddAsync(IEnumerable entities) 28 | { 29 | await _dbSet.AddRangeAsync(entities).ConfigureAwait(false); 30 | await _dbContext.SaveChangesAsync(); 31 | } 32 | 33 | public void Delete(T entity) 34 | { 35 | _dbSet.Remove(entity); 36 | _dbContext.SaveChanges(); 37 | } 38 | 39 | public void Delete(IEnumerable entities) 40 | { 41 | _dbSet.RemoveRange(entities); 42 | _dbContext.SaveChanges(); 43 | } 44 | 45 | public IQueryable Get() 46 | { 47 | return _dbSet.AsQueryable() ; 48 | } 49 | 50 | public IQueryable Get(Expression> predicate) 51 | { 52 | return _dbSet.Where(predicate); 53 | } 54 | 55 | public void Update(T entity) 56 | { 57 | _dbSet.Update(entity); 58 | _dbContext.SaveChanges(); 59 | } 60 | 61 | public void Update(IEnumerable entities) 62 | { 63 | _dbSet.UpdateRange(entities); 64 | _dbContext.SaveChanges(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Repositories/IdentityServerRepositories/ClientRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer4.EntityFramework.Stores; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using IdentityServer4.EntityFramework.Interfaces; 7 | using Microsoft.Extensions.Logging; 8 | using IdentityServer.Repositories.Interfaces.IdentityServerRepositories; 9 | using IdentityServer4.EntityFramework.Entities; 10 | using System.Linq.Expressions; 11 | using Microsoft.EntityFrameworkCore; 12 | 13 | namespace IdentityServer.Repositories.IdentityServerRepositories 14 | { 15 | public class ClientRepository : ClientStore,IClientRepository 16 | { 17 | private readonly IConfigurationDbContext _dbContext; 18 | private readonly DbSet _dbSet; 19 | public ClientRepository(IConfigurationDbContext context, ILogger logger) : base(context, logger) 20 | { 21 | _dbContext = context; 22 | _dbSet = _dbContext.Clients; 23 | 24 | } 25 | 26 | public async Task AddAsync(Client entity) 27 | { 28 | await _dbSet.AddAsync(entity); 29 | await _dbContext.SaveChangesAsync(); 30 | } 31 | 32 | public async Task AddAsync(IEnumerable entities) 33 | { 34 | await _dbSet.AddRangeAsync(entities); 35 | await _dbContext.SaveChangesAsync(); 36 | } 37 | 38 | public void Delete(Client entity) 39 | { 40 | _dbSet.Remove(entity); 41 | _dbContext.SaveChanges(); 42 | } 43 | 44 | public void Delete(IEnumerable entities) 45 | { 46 | _dbSet.RemoveRange(entities); 47 | _dbContext.SaveChanges(); 48 | } 49 | 50 | public IQueryable Get() 51 | { 52 | return _dbContext.Clients.AsQueryable(); 53 | } 54 | 55 | public IQueryable Get(Expression> predicate) 56 | { 57 | return _dbSet.Where(predicate); 58 | } 59 | 60 | public void Update(Client entity) 61 | { 62 | // _dbSet.Attach(entity); 63 | _dbSet.Update(entity); 64 | _dbContext.SaveChanges(); 65 | } 66 | 67 | public void Update(IEnumerable entities) 68 | { 69 | throw new NotImplementedException(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Repositories/IdentityServerRepositories/ResourceRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Repositories.Interfaces.IdentityServerRepositories; 2 | using IdentityServer4.EntityFramework.Stores; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using IdentityServer4.EntityFramework.Interfaces; 8 | using Microsoft.Extensions.Logging; 9 | using IdentityServer4.EntityFramework.Entities; 10 | 11 | namespace IdentityServer.Repositories.IdentityServerRepositories 12 | { 13 | public class ResourceRepository : ResourceStore, IResourcesRepository 14 | { 15 | private readonly IConfigurationDbContext _dbContext; 16 | public ResourceRepository(IConfigurationDbContext context, ILogger logger) : base(context, logger) 17 | { 18 | _dbContext = context; 19 | } 20 | 21 | public IQueryable GetApiResources() 22 | { 23 | return _dbContext.ApiResources.AsQueryable(); 24 | } 25 | 26 | public IQueryable GetIdentityResources() 27 | { 28 | return _dbContext.IdentityResources.AsQueryable(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Repositories/Interfaces/IExternalUserRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Repositories.Interfaces 8 | { 9 | public interface IExternalUserRepository:IRepository 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Repositories/Interfaces/IPasswordConfigRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Repositories.Interfaces 8 | { 9 | public interface IPasswordConfigRepository:IRepository 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Repositories/Interfaces/IProviderRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data.Entities; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Repositories.Interfaces 8 | { 9 | public interface IProviderRepository : IRepository 10 | { 11 | 12 | 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Repositories/Interfaces/IRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Repositories.Interfaces 8 | { 9 | public interface IRepository 10 | { 11 | IQueryable Get(); 12 | IQueryable Get(Expression> predicate); 13 | 14 | Task AddAsync(T entity); 15 | Task AddAsync(IEnumerable entities); 16 | 17 | void Delete(T entity); 18 | void Delete(IEnumerable entities); 19 | 20 | void Update(T entity); 21 | void Update(IEnumerable entities); 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Repositories/Interfaces/IdentityServerRepositories/IClientRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer4.EntityFramework.Entities; 2 | using IdentityServer4.Stores; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityServer.Repositories.Interfaces.IdentityServerRepositories 9 | { 10 | public interface IClientRepository : IClientStore,IRepository 11 | { 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Repositories/Interfaces/IdentityServerRepositories/IResourcerRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer4.EntityFramework.Entities; 2 | using IdentityServer4.Stores; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityServer.Repositories.Interfaces.IdentityServerRepositories 9 | { 10 | public interface IResourcesRepository : IResourceStore 11 | { 12 | IQueryable GetApiResources(); 13 | IQueryable GetIdentityResources(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Repositories/PasswordConfigRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Repositories.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using IdentityServer.Data.Entities; 7 | using IdentityServer.Configuration; 8 | using IdentityServer.Data; 9 | 10 | namespace IdentityServer.Repositories 11 | { 12 | public class PasswordConfigRepository : GenericRepository, IPasswordConfigRepository 13 | { 14 | public PasswordConfigRepository(DatabaseContext dbContext) : base(dbContext) 15 | { 16 | 17 | 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Repositories/ProviderRepository.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Repositories.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using IdentityServer.Data.Entities; 7 | using IdentityServer.Helpers; 8 | using IdentityServer.Data; 9 | 10 | namespace IdentityServer.Repositories 11 | { 12 | public class ProviderRepository : GenericRepository, IProviderRepository 13 | { 14 | public ProviderRepository(DatabaseContext dbContext) : base(dbContext) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Repositories/UnitOfWork/IUnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | 6 | namespace IdentityServer.Repositories.UnitOfWork 7 | { 8 | public interface IUnitOfWork 9 | { 10 | Task SaveChangesAsync(); 11 | void SaveChanges(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Repositories/UnitOfWork/UnitOfWork.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Data; 2 | using Microsoft.EntityFrameworkCore; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityServer.Repositories.UnitOfWork 9 | { 10 | public class UnitOfWork : IUnitOfWork where T: DbContext 11 | { 12 | private readonly T _dbContext; 13 | public UnitOfWork(T dbContext) 14 | { 15 | _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); 16 | 17 | } 18 | public void SaveChanges() 19 | { 20 | _dbContext.SaveChanges(); 21 | } 22 | 23 | public async Task SaveChangesAsync() 24 | { 25 | await _dbContext.SaveChangesAsync(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Services/IdentityServer/ClientService.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Interfaces.IdentityServer; 2 | using IdentityServer.Repositories.Interfaces.IdentityServerRepositories; 3 | using IdentityServer4.EntityFramework.Mappers; 4 | using IdentityServer4.Models; 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | 11 | 12 | namespace IdentityServer.Services.IdentityServer 13 | { 14 | public class ClientService : IClientService 15 | { 16 | private readonly IClientRepository _clientRepository; 17 | 18 | public ClientService(IClientRepository clientRepository) 19 | { 20 | _clientRepository = clientRepository; 21 | } 22 | 23 | public async Task AddClient(Client client) 24 | { 25 | await _clientRepository.AddAsync(client.ToEntity()); 26 | } 27 | 28 | public async Task GetClientById(string Id) 29 | { 30 | // return await _clientRepository.FindClientByIdAsync(Id); 31 | return _clientRepository.Get(x => x.ClientId == Id).FirstOrDefault().ToModel(); 32 | } 33 | 34 | public bool SetClientStatus(string clientId, bool enableStatus) 35 | { 36 | try 37 | { 38 | var client = _clientRepository.Get(x => x.ClientId == clientId).FirstOrDefault(); 39 | if(client != null) 40 | { 41 | client.Enabled = enableStatus; 42 | _clientRepository.Update(client); 43 | return true; 44 | } 45 | return false; 46 | } 47 | catch (Exception) 48 | { 49 | throw; 50 | } 51 | } 52 | 53 | public void Update(Client client) 54 | { 55 | var entry = client.ToEntity(); 56 | entry.Id = 21; 57 | _clientRepository.Update(entry); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Services/SecurityService/Results/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.Services.SecurityService.Results 8 | { 9 | public class LoginViewModel 10 | { 11 | [Required] 12 | [EmailAddress] 13 | public string Email { get; set; } 14 | 15 | [Required] 16 | [DataType(DataType.Password)] 17 | public string Password { get; set; } 18 | 19 | [Required] 20 | public string ClientId { get; set; } 21 | 22 | [Required] 23 | public string ClientSecret { get; set; } 24 | 25 | [Required] 26 | public string Scopes { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Services/SecurityService/Results/RegisterationResult.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Interfaces.SecurityService; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Identity; 7 | 8 | namespace IdentityServer.Services.SecurityService.Results 9 | { 10 | public class RegisterationResult : IIdentityResult 11 | { 12 | public string emailConfirmationToken { get; set; } 13 | public string userId { get; set; } 14 | public string email { get; set; } 15 | public object Transform(T user, object token = null) 16 | where T : IdentityUser 17 | where TKey : IEquatable 18 | { 19 | emailConfirmationToken = token != null ? token.ToString() : ""; 20 | userId = user.Id?.ToString(); 21 | email = user.Email; 22 | return this; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Services/TokenService.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer.Interfaces.SecurityService; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using IdentityServer.Models; 7 | using IdentityModel.Client; 8 | using Newtonsoft.Json.Linq; 9 | 10 | namespace IdentityServer.Services 11 | { 12 | public class TokenService : ITokenService 13 | { 14 | 15 | public TokenService() 16 | { 17 | 18 | } 19 | public async Task GetToken(string clientId, string clientSecret, string email, string password, string scopes) 20 | { 21 | try 22 | { 23 | var authority = "[authority]"; 24 | var tokenClient = new TokenClient(authority + "/connect/token", clientId, clientSecret); 25 | 26 | var response = await tokenClient.RequestResourceOwnerPasswordAsync(email, password, scopes); 27 | 28 | if (!response.IsError && response.Json != null) 29 | return BaseModel.Success("", response.Json); 30 | 31 | if (response.IsError) 32 | { 33 | var error = response.Json["error"].ToString(); 34 | 35 | JToken errorDescription; 36 | var hasDescription = response.Json.TryGetValue("error_description", out errorDescription); 37 | 38 | if (hasDescription) 39 | return BaseModel.Error(errorDescription.ToString()); 40 | 41 | return BaseModel.Error(error); 42 | } 43 | 44 | return null; 45 | } 46 | catch (Exception) 47 | { 48 | 49 | throw; 50 | } 51 | 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/ViewModels/SecurityService/RegisterViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | 7 | namespace IdentityServer.ViewModels.SecurityService 8 | { 9 | public class RegisterViewModel 10 | { 11 | [Required] 12 | public string ClientID { get; set; } 13 | [Required] 14 | [EmailAddress] 15 | [Display(Name = "Email")] 16 | public string Email { get; set; } 17 | 18 | [Required] 19 | // [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 20 | [DataType(DataType.Password)] 21 | 22 | public string Password { get; set; } 23 | 24 | public bool CreateActivated { get; set; } 25 | [DataType(DataType.Password)] 26 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 27 | public string ConfirmPassword { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Views/Account/LoggedOut.cshtml: -------------------------------------------------------------------------------- 1 | @model LoggedOutViewModel 2 | 3 | @{ 4 | // set this so the layout rendering sees an anonymous user 5 | ViewData["signed-out"] = true; 6 | } 7 | 8 |
9 |

Logout

10 |
11 | 12 |

You are now logged out

13 | @if (Model.PostLogoutRedirectUri != null) 14 | { 15 |
16 | Click here to return to the 17 | @Model.ClientName application. 18 |
19 | } 20 | 21 | @if (Model.SignOutIframeUrl != null) 22 | { 23 | 24 | } 25 |
26 | 27 | @section scripts 28 | { 29 | @if (Model.AutomaticRedirectAfterSignOut) 30 | { 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Views/Account/Logout.cshtml: -------------------------------------------------------------------------------- 1 | @model LogoutViewModel 2 | 3 | 4 | 5 |
6 |

Logout

7 |
8 |

Would you like to logout of IdentityServer?

9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 |
17 |
-------------------------------------------------------------------------------- /src/Views/Consent/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model ConsentViewModel 2 | 3 |
4 |
5 |
6 |
7 | 8 | @if (Model.ClientLogoUrl != null) 9 | { 10 | 11 | } 12 |

@Model.ClientName

13 | 14 | 15 | 16 | is requesting your permission 17 | 18 | @Html.Partial("_ValidationSummary") 19 | 67 |
68 | 69 | 74 | 75 |
76 |
77 |
-------------------------------------------------------------------------------- /src/Views/Consent/_ScopeListItem.cshtml: -------------------------------------------------------------------------------- 1 | @model ScopeViewModel 2 | 3 |
  • 4 | 24 | @if (Model.Required) 25 | { 26 | (required) 27 | } 28 | @if (Model.Description != null) 29 | { 30 | 33 | } 34 |
  • -------------------------------------------------------------------------------- /src/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | 
    2 |

    About

    3 |
    -------------------------------------------------------------------------------- /src/Views/Home/GettingStarted.cshtml: -------------------------------------------------------------------------------- 1 | 
    2 |

    Getting Started

    3 |
    -------------------------------------------------------------------------------- /src/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
    2 | 3 |
    4 | 13 | 14 |
    15 |
    16 |

    17 | IdentityServer publishes a 18 | discovery document 19 | where you can find metadata and links to all the endpoints, key material, etc. 20 |

    21 |
    22 |
    23 |

    24 | Click here to manage your stored grants. 25 |

    26 |
    27 |
    28 |
    29 |
    30 |

    31 | Here are links to the 32 | source code repository, 33 | and ready to use samples. 34 |

    35 |
    36 |
    37 |
    38 |
    -------------------------------------------------------------------------------- /src/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Hosting 2 | @model ErrorViewModel 3 | @inject IHostingEnvironment host 4 | 5 | @{ 6 | var error = Model?.Error?.Error; 7 | var errorDescription = host.IsDevelopment() ? Model?.Error?.ErrorDescription : null; 8 | var request_id = Model?.Error?.RequestId; 9 | } 10 | 11 |
    12 | 15 | 16 |
    17 |
    18 |
    19 | Sorry, there was an error 20 | 21 | @if (error != null) 22 | { 23 | 24 | 25 | : @error 26 | 27 | 28 | 29 | if (errorDescription != null) 30 | { 31 |
    @errorDescription
    32 | } 33 | } 34 |
    35 | 36 | @if (request_id != null) 37 | { 38 |
    Request Id: @request_id
    39 | } 40 |
    41 |
    42 |
    43 | -------------------------------------------------------------------------------- /src/Views/Shared/_ValidationSummary.cshtml: -------------------------------------------------------------------------------- 1 | @if (ViewContext.ModelState.IsValid == false) 2 | { 3 |
    4 | Error 5 |
    6 |
    7 | } -------------------------------------------------------------------------------- /src/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using IdentityServer.Dashboard 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | -------------------------------------------------------------------------------- /src/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /src/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=localhost;port=3306;database=IdentityServer;uid=root;Password=Liverpool1" 4 | }, 5 | 6 | "IdentityServer": { 7 | "Authority" : "" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "asp.net", 3 | "private": true, 4 | "dependencies": { 5 | "dialog-polyfill": "0.4.9", 6 | "jquery-tag-editor" : "1.0.20" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/tempkey.rsa: -------------------------------------------------------------------------------- 1 | {"KeyId":"4a874b23720e98907baf326cc863fda5","Parameters":{"D":"AdpjJi1pbm9YHth11p+LeAAX+eRsLUwsBCpNKDgviT23gjGkUpbLgilw4YV5ycbUxUPHVeBUgHKxsceQHvceu1rv8jhMDuOeGJs5t0SCQAeihsdq8gxkKZ+3UKu6ltBVsbxkQlC9hbsenb1VfeqCxTcg4LlMOJDDEVAjSt3YJV2cZnX5CfwBec8bPQCt+bhQ6Qz+xzPU2XXHaSmuW+8px/umhgU/qmfPK+4N6UUjkQg6hjBsray1asYIT37aHGOfMWttW6ht/+/qRooP1pvreaCP+aEjCfwo4ap4i0CECq6cj3rPA9E6f3hItbHChyWufV/MKoGtfUD7ziO44r+b3Q==","DP":"QPi/aWLDwlmNxHeAE1tsv9/HsHhnoRolEKjjhPCOQchXsMU1sjAC0NCwZkCJkt4xCi9OOMbIKEwE0+R5Tt15w7AT7Dy65NvK4WAQx8/nv/X/9JG+ZLjjhVk/UwWzAAdlLNHdVB3yz3lyNcko9ONGOPvTr7o+8V5dq3o4P2fMCEc=","DQ":"Q607jpYH5d2egOX0F0IhnbSiS59KqQx9/tasrcuRg95Y/u+hAerN5nj4Iy9RTXsHzIdnvHHzQ9ZySD4kONKHhjwDcoiDQ0nnDbxHWwgyCDstwt6B64aMfmNizxFIzeqjYkcGokD7JIPe6ovnoQIMdMlEIz3OPtcMFFr7H3bgrBk=","Exponent":"AQAB","InverseQ":"m72l6Y9NIkE7dne7MACGx/8hMiEHI3LIG227cwGBzmGpE2IUI6Le3qsCGPbJtkqRLotDxhv7GSaoKhzFlbil2acJIuj7B7qywc+LWrGysu/yw22B/6hoOFSB9MoSyvWKV5DdcSoTEXk+tmCwj9RxJn8WIQDwRhNhzG0dHsc1s4s=","Modulus":"rb22OhIrKO+5BPlKvjezp/FXho4gIFtO3VLjQgxc0HtUkXON0Yfo6UZVUc001KUB3cZas1V4xvBN0NmCNTFUxmEpzwNl4dmKJ04gaNOCNik46xqiafdJnolRFIaBHUVnq8v+D797mDlCmoiw+/jtOLrQs4VKS84OrU4690Ko6ZOwz/TzrobyE0BzZDYX0h1F1bYEGlKj9ROKw7bBRdi1N/cfuF+xByf36wjYneTYmpC28Q2TMyt/1C7f78BqlRwYeYH9QURBr8Zz17iJL4FqbRo30bd005WTeYjb1LrbT0Ulc0+c7P7WoRwc4CuR3PUyZ+A+4qZW+IDO0/Em4eU8KQ==","P":"09Upe1jsIkAP3nHjr89M01E1vCvC1kMlCGruW+BNqqCqrB8bQmmxiIHrYVNGw76WnfPN7KEKuXWT0mw+Pl0oJRwaSlv3TxwuRVhZdDJGYC08cCWIFjOvO7o3jnYv/A6Vv7k3ikMaeFsBU9S7zQ9pXZhdk3249Je/BUIoi6+A2Q8=","Q":"0fdcruthJNwh6j1uP5QakAxo54n9ShvpEBofXpQ68IjbdwPtBCqoCDonaZ8zMzHAZQN+U2YJqxdkFhwrhMJ9E5QdEVqTBjgQ9kv5fvPMCgyUT9e57cdhcovqUAjSLkmaERe3NH6WPoWLJ4q3GolZbGmXWOEjlsZl1xM9D3zsZ0c="}} -------------------------------------------------------------------------------- /src/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 |  2 | body { 3 | padding:0; 4 | margin:0; 5 | } 6 | 7 | .page-content { 8 | width:100%; 9 | } 10 | .page-content .page-content { 11 | width: 70%; 12 | margin: auto; 13 | color: grey; 14 | } 15 | 16 | .overview_stats { 17 | margin-top:15px; 18 | float:right; 19 | } 20 | 21 | 22 | .resource-card-event.mdl-card { 23 | width: 256px; 24 | height: 128px; 25 | background: #3E4EB8; 26 | } 27 | 28 | .resource-card-event > .mdl-card__actions { 29 | border-color: rgba(255, 255, 255, 0.2); 30 | } 31 | 32 | .resource-card-event > .mdl-card__title { 33 | align-items: flex-start; 34 | } 35 | 36 | .resource-card-event > .mdl-card__title > h4 { 37 | margin-top: 0; 38 | } 39 | 40 | .resource-card-event > .mdl-card__actions { 41 | display: flex; 42 | box-sizing: border-box; 43 | align-items: center; 44 | } 45 | 46 | .resource-card-event > .mdl-card__actions > .material-icons { 47 | padding-right: 10px; 48 | } 49 | 50 | .resource-card-event > .mdl-card__title, 51 | .resource-card-event > .mdl-card__actions, 52 | .resource-card-event > .mdl-card__actions > .mdl-button { 53 | color: #fff; 54 | } 55 | 56 | .page-content .toolbar .toolbar-title { 57 | float:left; 58 | } 59 | .page-content .toolbar .toolbar-controls { 60 | float:right; 61 | } 62 | 63 | 64 | .default-dialog { 65 | width:70% 66 | } 67 | .dialog-app-type{ 68 | width:100%; 69 | margin:10px; 70 | } 71 | .full-width { 72 | width:100%; 73 | } 74 | .consent-row { 75 | width:50%; 76 | margin:auto; 77 | } 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/wwwroot/js/extensions.js: -------------------------------------------------------------------------------- 1 | String.prototype.isClassSelector = isClassSelector; 2 | String.prototype.isIdSelector = isIdSelector; 3 | 4 | function isClassSelector() { 5 | return this.toString().charAt(0) == "."; 6 | } 7 | function isIdSelector() { 8 | return this.toString().charAt(0) == "#"; 9 | } -------------------------------------------------------------------------------- /src/wwwroot/js/helpers.js: -------------------------------------------------------------------------------- 1 | function registerDialog(dialogId, actionBtnId,parent) { 2 | if (actionBtnId.isIdSelector()) { 3 | 4 | var dialog = document.querySelector(dialogId); 5 | var btn = document.querySelector(actionBtnId); 6 | 7 | if (!dialog.showModal) { 8 | dialogPolyfill.registerDialog(dialog); 9 | } 10 | 11 | btn.addEventListener('click', function () { 12 | if (parent) { 13 | var parentdialog = document.querySelector(parent); 14 | if (parentdialog) { 15 | parentdialog.close(); 16 | } 17 | } 18 | dialog.showModal(); 19 | }); 20 | 21 | var dialogBtn = dialog.querySelector('.close'); 22 | if (dialogBtn) { 23 | dialogBtn.addEventListener('click', function () { 24 | dialog.close(); 25 | }); 26 | } 27 | 28 | } else if (actionBtnId.isClassSelector()) { 29 | 30 | var btns = document.querySelectorAll(actionBtnId); 31 | var dialog = document.querySelector(dialogId); 32 | 33 | Array.from(btns).forEach((element) => { 34 | element.addEventListener('click', function () { 35 | 36 | dialog.showModal(); 37 | }); 38 | }); 39 | dialog.querySelector('.close').addEventListener('click', function () { 40 | dialog.close(); 41 | }); 42 | } 43 | 44 | 45 | 46 | } 47 | 48 | 49 | function configureToggle(toggleId, callback) { 50 | var input = document.querySelector(toggleId); 51 | if (input) { 52 | input.addEventListener("change", callback) 53 | } 54 | } -------------------------------------------------------------------------------- /src/wwwroot/js/services/clientService.js: -------------------------------------------------------------------------------- 1 | var clientService = { 2 | post: (url, clientData, successCallback, failedCallback) => { 3 | 4 | $.ajax({ 5 | method: "POST", 6 | url: url, 7 | traditional:true, 8 | data: clientData, 9 | success: function (data) { 10 | successCallback(data); 11 | }, 12 | error: function (err) { 13 | failedCallback(err); 14 | } 15 | 16 | }) 17 | }, 18 | updateClientStatus : (url,clientId, enableStatus, successCallback,failedCallback) => { 19 | $.ajax({ 20 | method: "GET", 21 | url:url, 22 | success: function (data) { 23 | successCallback(data) 24 | }, 25 | error: function (err) { 26 | failedCallback(err); 27 | } 28 | }) 29 | } 30 | } -------------------------------------------------------------------------------- /src/wwwroot/lib/caret/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "caret", 3 | "description": "Manipulate the caret's position in a text box or content-editable element.", 4 | "main": "jquery.caret.js", 5 | "license": [ 6 | "BSD-3-Clause" 7 | ], 8 | "ignore": [ 9 | "bower_components", 10 | "node_modules", 11 | "test.html" 12 | ], 13 | "keywords": [ 14 | "caret" 15 | ], 16 | "authors": [ 17 | { 18 | "name": "Gideon Sireling", 19 | "homepage": "https://www.linkedin.com/in/gideonsireling" 20 | } 21 | ], 22 | "homepage": "https://bitbucket.org/accursoft/caret", 23 | "dependencies": { 24 | "jquery": ">=1.3" 25 | }, 26 | "version": "1.0.0", 27 | "_release": "1.0.0", 28 | "_resolution": { 29 | "type": "version", 30 | "tag": "v1.0.0", 31 | "commit": "8cd0910544f4267d91ca527117ae459832978411" 32 | }, 33 | "_source": "https://github.com/accursoft/caret.git", 34 | "_target": "*", 35 | "_originalSource": "caret" 36 | } -------------------------------------------------------------------------------- /src/wwwroot/lib/caret/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "caret", 3 | "description": "Manipulate the caret's position in a text box or content-editable element.", 4 | "main": "jquery.caret.js", 5 | "license": ["BSD-3-Clause"], 6 | "ignore": [ 7 | "bower_components", 8 | "node_modules", 9 | "test.html" 10 | ], 11 | "keywords": ["caret"], 12 | "authors": [{ 13 | "name": "Gideon Sireling", 14 | "homepage": "https://www.linkedin.com/in/gideonsireling" 15 | }], 16 | "homepage": "https://bitbucket.org/accursoft/caret", 17 | "dependencies": { 18 | "jquery": ">=1.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/wwwroot/lib/caret/jquery.caret.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $.fn.caret = function(pos) { 3 | var target = this[0]; 4 | var isContentEditable = target && target.contentEditable === 'true'; 5 | if (arguments.length == 0) { 6 | //get 7 | if (target) { 8 | //HTML5 9 | if (window.getSelection) { 10 | //contenteditable 11 | if (isContentEditable) { 12 | target.focus(); 13 | var range1 = window.getSelection().getRangeAt(0), 14 | range2 = range1.cloneRange(); 15 | range2.selectNodeContents(target); 16 | range2.setEnd(range1.endContainer, range1.endOffset); 17 | return range2.toString().length; 18 | } 19 | //textarea 20 | return target.selectionStart; 21 | } 22 | //IE<9 23 | if (document.selection) { 24 | target.focus(); 25 | //contenteditable 26 | if (isContentEditable) { 27 | var range1 = document.selection.createRange(), 28 | range2 = document.body.createTextRange(); 29 | range2.moveToElementText(target); 30 | range2.setEndPoint('EndToEnd', range1); 31 | return range2.text.length; 32 | } 33 | //textarea 34 | var pos = 0, 35 | range = target.createTextRange(), 36 | range2 = document.selection.createRange().duplicate(), 37 | bookmark = range2.getBookmark(); 38 | range.moveToBookmark(bookmark); 39 | while (range.moveStart('character', -1) !== 0) pos++; 40 | return pos; 41 | } 42 | // Addition for jsdom support 43 | if (target.selectionStart) 44 | return target.selectionStart; 45 | } 46 | //not supported 47 | return; 48 | } 49 | //set 50 | if (target) { 51 | if (pos == -1) 52 | pos = this[isContentEditable? 'text' : 'val']().length; 53 | //HTML5 54 | if (window.getSelection) { 55 | //contenteditable 56 | if (isContentEditable) { 57 | target.focus(); 58 | window.getSelection().collapse(target.firstChild, pos); 59 | } 60 | //textarea 61 | else 62 | target.setSelectionRange(pos, pos); 63 | } 64 | //IE<9 65 | else if (document.body.createTextRange) { 66 | if (isContentEditable) { 67 | var range = document.body.createTextRange(); 68 | range.moveToElementText(target); 69 | range.moveStart('character', pos); 70 | range.collapse(true); 71 | range.select(); 72 | } else { 73 | var range = target.createTextRange(); 74 | range.move('character', pos); 75 | range.select(); 76 | } 77 | } 78 | if (!isContentEditable) 79 | target.focus(); 80 | } 81 | return this; 82 | } 83 | })(jQuery); 84 | -------------------------------------------------------------------------------- /src/wwwroot/lib/caret/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009, Gideon Sireling 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Gideon Sireling nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /src/wwwroot/lib/caret/readme.md: -------------------------------------------------------------------------------- 1 | jQuery Caret 2 | ============ 3 | 4 | - get the caret's position: `pos = $(textarea).caret()` 5 | - set the caret's position: `$(textarea).caret(pos)` 6 | - set the caret's position to the end: `$(textarea).caret(-1)` 7 | 8 | Return value: the current/new caret position -------------------------------------------------------------------------------- /src/wwwroot/lib/dialog-polyfill/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dialog-polyfill", 3 | "main": [ 4 | "dialog-polyfill.js", 5 | "dialog-polyfill.css" 6 | ], 7 | "homepage": "https://github.com/GoogleChrome/dialog-polyfill", 8 | "authors": [ 9 | "The Chromium Authors" 10 | ], 11 | "description": "Polyfill for the element", 12 | "keywords": [ 13 | "html5", 14 | "polyfill", 15 | "dialog" 16 | ], 17 | "license": "BSD", 18 | "ignore": [ 19 | "**/.*", 20 | "node_modules", 21 | "bower_components", 22 | "test", 23 | "tests" 24 | ], 25 | "devDependencies": { 26 | "mocha": "", 27 | "chai": "" 28 | }, 29 | "version": "0.4.9", 30 | "_release": "0.4.9", 31 | "_resolution": { 32 | "type": "version", 33 | "tag": "0.4.9", 34 | "commit": "1b68912846f089ed21c5fb0e1ae0694a07dbfac0" 35 | }, 36 | "_source": "https://github.com/GoogleChrome/dialog-polyfill.git", 37 | "_target": "0.4.9", 38 | "_originalSource": "dialog-polyfill" 39 | } -------------------------------------------------------------------------------- /src/wwwroot/lib/dialog-polyfill/LICENSE: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/wwwroot/lib/dialog-polyfill/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dialog-polyfill", 3 | "main": ["dialog-polyfill.js", "dialog-polyfill.css"], 4 | "homepage": "https://github.com/GoogleChrome/dialog-polyfill", 5 | "authors": [ 6 | "The Chromium Authors" 7 | ], 8 | "description": "Polyfill for the element", 9 | "keywords": [ 10 | "html5", 11 | "polyfill", 12 | "dialog" 13 | ], 14 | "license": "BSD", 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ], 22 | "devDependencies": { 23 | "mocha": "", 24 | "chai": "" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/wwwroot/lib/dialog-polyfill/dialog-polyfill.css: -------------------------------------------------------------------------------- 1 | dialog { 2 | position: absolute; 3 | left: 0; right: 0; 4 | width: -moz-fit-content; 5 | width: -webkit-fit-content; 6 | width: fit-content; 7 | height: -moz-fit-content; 8 | height: -webkit-fit-content; 9 | height: fit-content; 10 | margin: auto; 11 | border: solid; 12 | padding: 1em; 13 | background: white; 14 | color: black; 15 | display: block; 16 | } 17 | 18 | dialog:not([open]) { 19 | display: none; 20 | } 21 | 22 | dialog + .backdrop { 23 | position: fixed; 24 | top: 0; right: 0; bottom: 0; left: 0; 25 | background: rgba(0,0,0,0.1); 26 | } 27 | 28 | ._dialog_overlay { 29 | position: fixed; 30 | top: 0; right: 0; bottom: 0; left: 0; 31 | } 32 | 33 | dialog.fixed { 34 | position: fixed; 35 | top: 50%; 36 | transform: translate(0, -50%); 37 | } -------------------------------------------------------------------------------- /src/wwwroot/lib/dialog-polyfill/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dialog-polyfill", 3 | "version": "0.4.8", 4 | "description": "Polyfill for the dialog element", 5 | "main": "dialog-polyfill.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/GoogleChrome/dialog-polyfill.git" 9 | }, 10 | "author": "The Chromium Authors", 11 | "license": "BSD", 12 | "homepage": "https://github.com/GoogleChrome/dialog-polyfill" 13 | } 14 | -------------------------------------------------------------------------------- /src/wwwroot/lib/dialog-polyfill/test.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 48 |
    49 | 50 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery-tag-editor/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-tag-editor", 3 | "description": "A powerful and lightweight tag editor plugin for jQuery.", 4 | "version": "1.0.20", 5 | "dependencies": { 6 | "jquery": ">=1.7", 7 | "caret": null 8 | }, 9 | "homepage": "https://github.com/Pixabay/jQuery-tagEditor", 10 | "authors": [ 11 | { 12 | "name": "Simon Steinberger", 13 | "url": "https://pixabay.com/users/Simon/", 14 | "email": "simon@pixabay.com" 15 | } 16 | ], 17 | "keywords": [ 18 | "tags", 19 | "keywords", 20 | "editor", 21 | "drag and drop", 22 | "editable", 23 | "edit" 24 | ], 25 | "licenses": [ 26 | { 27 | "type": "MIT", 28 | "url": "http://www.opensource.org/licenses/mit-license.php" 29 | } 30 | ], 31 | "ignore": [ 32 | "bower.json", 33 | "demo.html", 34 | "readme.md", 35 | "tag-editor.jquery.json" 36 | ], 37 | "_release": "1.0.20", 38 | "_resolution": { 39 | "type": "version", 40 | "tag": "1.0.20", 41 | "commit": "dec0ce153c41d857a8fa33acc4ee6f7e46ad275f" 42 | }, 43 | "_source": "https://github.com/Pixabay/jQuery-tagEditor.git", 44 | "_target": "1.0.20", 45 | "_originalSource": "jquery-tag-editor" 46 | } -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery-tag-editor/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery-tag-editor", 3 | "description": "A powerful and lightweight tag editor plugin for jQuery.", 4 | "version": "1.0.20", 5 | "dependencies": { 6 | "jquery": ">=1.7", 7 | "caret": null 8 | }, 9 | "homepage": "https://github.com/Pixabay/jQuery-tagEditor", 10 | "authors": [{ 11 | "name": "Simon Steinberger", 12 | "url": "https://pixabay.com/users/Simon/", 13 | "email": "simon@pixabay.com" 14 | }], 15 | "keywords": [ 16 | "tags", 17 | "keywords", 18 | "editor", 19 | "drag and drop", 20 | "editable", 21 | "edit" 22 | ], 23 | "licenses": [{ 24 | "type": "MIT", 25 | "url": "http://www.opensource.org/licenses/mit-license.php" 26 | }], 27 | "ignore": [ 28 | "bower.json", 29 | "demo.html", 30 | "readme.md", 31 | "tag-editor.jquery.json" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery-tag-editor/jquery.caret.min.js: -------------------------------------------------------------------------------- 1 | // http://code.accursoft.com/caret - 1.3.3 2 | !function(e){e.fn.caret=function(e){var t=this[0],n="true"===t.contentEditable;if(0==arguments.length){if(window.getSelection){if(n){t.focus();var o=window.getSelection().getRangeAt(0),r=o.cloneRange();return r.selectNodeContents(t),r.setEnd(o.endContainer,o.endOffset),r.toString().length}return t.selectionStart}if(document.selection){if(t.focus(),n){var o=document.selection.createRange(),r=document.body.createTextRange();return r.moveToElementText(t),r.setEndPoint("EndToEnd",o),r.text.length}var e=0,c=t.createTextRange(),r=document.selection.createRange().duplicate(),a=r.getBookmark();for(c.moveToBookmark(a);0!==c.moveStart("character",-1);)e++;return e}return t.selectionStart?t.selectionStart:0}if(-1==e&&(e=this[n?"text":"val"]().length),window.getSelection)n?(t.focus(),window.getSelection().collapse(t.firstChild,e)):t.setSelectionRange(e,e);else if(document.body.createTextRange)if(n){var c=document.body.createTextRange();c.moveToElementText(t),c.moveStart("character",e),c.collapse(!0),c.select()}else{var c=t.createTextRange();c.move("character",e),c.select()}return n||t.focus(),e}}(jQuery); 3 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery-tag-editor/jquery.tag-editor.css: -------------------------------------------------------------------------------- 1 | /* surrounding tag container */ 2 | .tag-editor { 3 | list-style-type: none; padding: 0 5px 0 0; margin: 0; overflow: hidden; border: 1px solid #eee; cursor: text; 4 | font: normal 14px sans-serif; color: #555; background: #fff; line-height: 20px; 5 | } 6 | 7 | /* core styles usually need no change */ 8 | .tag-editor li { display: block; float: left; overflow: hidden; margin: 3px 0; } 9 | .tag-editor div { float: left; padding: 0 4px; } 10 | .tag-editor .placeholder { padding: 0 8px; color: #bbb; } 11 | .tag-editor .tag-editor-spacer { padding: 0; width: 8px; overflow: hidden; color: transparent; background: none; } 12 | .tag-editor input { 13 | vertical-align: inherit; border: 0; outline: none; padding: 0; margin: 0; cursor: text; 14 | font-family: inherit; font-weight: inherit; font-size: inherit; font-style: inherit; 15 | box-shadow: none; background: none; color: #444; 16 | } 17 | /* hide original input field or textarea visually to allow tab navigation */ 18 | .tag-editor-hidden-src { position: absolute !important; left: -99999px; } 19 | /* hide IE10 "clear field" X */ 20 | .tag-editor ::-ms-clear { display: none; } 21 | 22 | /* tag style */ 23 | .tag-editor .tag-editor-tag { 24 | padding-left: 5px; color: #46799b; background: #e0eaf1; white-space: nowrap; 25 | overflow: hidden; cursor: pointer; border-radius: 2px 0 0 2px; 26 | } 27 | 28 | /* delete icon */ 29 | .tag-editor .tag-editor-delete { background: #e0eaf1; cursor: pointer; border-radius: 0 2px 2px 0; padding-left: 3px; padding-right: 4px; } 30 | .tag-editor .tag-editor-delete i { line-height: 18px; display: inline-block; } 31 | .tag-editor .tag-editor-delete i:before { font-size: 16px; color: #8ba7ba; content: "×"; font-style: normal; } 32 | .tag-editor .tag-editor-delete:hover i:before { color: #d65454; } 33 | .tag-editor .tag-editor-tag.active+.tag-editor-delete, .tag-editor .tag-editor-tag.active+.tag-editor-delete i { visibility: hidden; cursor: text; } 34 | 35 | .tag-editor .tag-editor-tag.active { background: none !important; } 36 | 37 | /* jQuery UI autocomplete - code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css */ 38 | .ui-autocomplete { position: absolute; top: 0; left: 0; cursor: default; font-size: 14px; } 39 | .ui-front { z-index: 9999; } 40 | .ui-menu { list-style: none; padding: 1px; margin: 0; display: block; outline: none; } 41 | .ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.4; min-height: 0; /* support: IE7 */ } 42 | .ui-widget-content { border: 1px solid #bbb; background: #fff; color: #555; } 43 | .ui-widget-content a { color: #46799b; } 44 | .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { background: #e0eaf1; } 45 | .ui-helper-hidden-accessible { display: none; } 46 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ], 14 | "homepage": "https://github.com/jquery/jquery-dist", 15 | "version": "3.2.1", 16 | "_release": "3.2.1", 17 | "_resolution": { 18 | "type": "version", 19 | "tag": "3.2.1", 20 | "commit": "77d2a51d0520d2ee44173afdf4e40a9201f5964e" 21 | }, 22 | "_source": "https://github.com/jquery/jquery-dist.git", 23 | "_target": ">=1.7", 24 | "_originalSource": "jquery" 25 | } -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery/README.md: -------------------------------------------------------------------------------- 1 | # jQuery 2 | 3 | > jQuery is a fast, small, and feature-rich JavaScript library. 4 | 5 | For information on how to get started and how to use jQuery, please see [jQuery's documentation](http://api.jquery.com/). 6 | For source files and issues, please visit the [jQuery repo](https://github.com/jquery/jquery). 7 | 8 | If upgrading, please see the [blog post for 3.2.1](https://blog.jquery.com/2017/03/20/jquery-3-2-1-now-available/). This includes notable differences from the previous version and a more readable changelog. 9 | 10 | ## Including jQuery 11 | 12 | Below are some of the most common ways to include jQuery. 13 | 14 | ### Browser 15 | 16 | #### Script tag 17 | 18 | ```html 19 | 20 | ``` 21 | 22 | #### Babel 23 | 24 | [Babel](http://babeljs.io/) is a next generation JavaScript compiler. One of the features is the ability to use ES6/ES2015 modules now, even though browsers do not yet support this feature natively. 25 | 26 | ```js 27 | import $ from "jquery"; 28 | ``` 29 | 30 | #### Browserify/Webpack 31 | 32 | There are several ways to use [Browserify](http://browserify.org/) and [Webpack](https://webpack.github.io/). For more information on using these tools, please refer to the corresponding project's documention. In the script, including jQuery will usually look like this... 33 | 34 | ```js 35 | var $ = require("jquery"); 36 | ``` 37 | 38 | #### AMD (Asynchronous Module Definition) 39 | 40 | AMD is a module format built for the browser. For more information, we recommend [require.js' documentation](http://requirejs.org/docs/whyamd.html). 41 | 42 | ```js 43 | define(["jquery"], function($) { 44 | 45 | }); 46 | ``` 47 | 48 | ### Node 49 | 50 | To include jQuery in [Node](nodejs.org), first install with npm. 51 | 52 | ```sh 53 | npm install jquery 54 | ``` 55 | 56 | For jQuery to work in Node, a window with a document is required. Since no such window exists natively in Node, one can be mocked by tools such as [jsdom](https://github.com/tmpvar/jsdom). This can be useful for testing purposes. 57 | 58 | ```js 59 | require("jsdom").env("", function(err, window) { 60 | if (err) { 61 | console.error(err); 62 | return; 63 | } 64 | 65 | var $ = require("jquery")(window); 66 | }); 67 | ``` 68 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jquery", 3 | "main": "dist/jquery.js", 4 | "license": "MIT", 5 | "ignore": [ 6 | "package.json" 7 | ], 8 | "keywords": [ 9 | "jquery", 10 | "javascript", 11 | "browser", 12 | "library" 13 | ] 14 | } -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery/external/sizzle/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright jQuery Foundation and other contributors, https://jquery.org/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/sizzle 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery/src/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | 4 | "extends": "../.eslintrc-browser.json" 5 | } 6 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery/src/ajax/load.js: -------------------------------------------------------------------------------- 1 | define( [ 2 | "../core", 3 | "../core/stripAndCollapse", 4 | "../core/parseHTML", 5 | "../ajax", 6 | "../traversing", 7 | "../manipulation", 8 | "../selector" 9 | ], function( jQuery, stripAndCollapse ) { 10 | 11 | "use strict"; 12 | 13 | /** 14 | * Load a url into a page 15 | */ 16 | jQuery.fn.load = function( url, params, callback ) { 17 | var selector, type, response, 18 | self = this, 19 | off = url.indexOf( " " ); 20 | 21 | if ( off > -1 ) { 22 | selector = stripAndCollapse( url.slice( off ) ); 23 | url = url.slice( 0, off ); 24 | } 25 | 26 | // If it's a function 27 | if ( jQuery.isFunction( params ) ) { 28 | 29 | // We assume that it's the callback 30 | callback = params; 31 | params = undefined; 32 | 33 | // Otherwise, build a param string 34 | } else if ( params && typeof params === "object" ) { 35 | type = "POST"; 36 | } 37 | 38 | // If we have elements to modify, make the request 39 | if ( self.length > 0 ) { 40 | jQuery.ajax( { 41 | url: url, 42 | 43 | // If "type" variable is undefined, then "GET" method will be used. 44 | // Make value of this field explicit since 45 | // user can override it through ajaxSetup method 46 | type: type || "GET", 47 | dataType: "html", 48 | data: params 49 | } ).done( function( responseText ) { 50 | 51 | // Save response for use in complete callback 52 | response = arguments; 53 | 54 | self.html( selector ? 55 | 56 | // If a selector was specified, locate the right elements in a dummy div 57 | // Exclude scripts to avoid IE 'Permission Denied' errors 58 | jQuery( "
    " ).append( jQuery.parseHTML( responseText ) ).find( selector ) : 59 | 60 | // Otherwise use the full result 61 | responseText ); 62 | 63 | // If the request succeeds, this function gets "data", "status", "jqXHR" 64 | // but they are ignored because response was set above. 65 | // If it fails, this function gets "jqXHR", "status", "error" 66 | } ).always( callback && function( jqXHR, status ) { 67 | self.each( function() { 68 | callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] ); 69 | } ); 70 | } ); 71 | } 72 | 73 | return this; 74 | }; 75 | 76 | } ); 77 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery/src/ajax/parseXML.js: -------------------------------------------------------------------------------- 1 | define( [ 2 | "../core" 3 | ], function( jQuery ) { 4 | 5 | "use strict"; 6 | 7 | // Cross-browser xml parsing 8 | jQuery.parseXML = function( data ) { 9 | var xml; 10 | if ( !data || typeof data !== "string" ) { 11 | return null; 12 | } 13 | 14 | // Support: IE 9 - 11 only 15 | // IE throws on parseFromString with invalid input. 16 | try { 17 | xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); 18 | } catch ( e ) { 19 | xml = undefined; 20 | } 21 | 22 | if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { 23 | jQuery.error( "Invalid XML: " + data ); 24 | } 25 | return xml; 26 | }; 27 | 28 | return jQuery.parseXML; 29 | 30 | } ); 31 | -------------------------------------------------------------------------------- /src/wwwroot/lib/jquery/src/ajax/script.js: -------------------------------------------------------------------------------- 1 | define( [ 2 | "../core", 3 | "../var/document", 4 | "../ajax" 5 | ], function( jQuery, document ) { 6 | 7 | "use strict"; 8 | 9 | // Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) 10 | jQuery.ajaxPrefilter( function( s ) { 11 | if ( s.crossDomain ) { 12 | s.contents.script = false; 13 | } 14 | } ); 15 | 16 | // Install script dataType 17 | jQuery.ajaxSetup( { 18 | accepts: { 19 | script: "text/javascript, application/javascript, " + 20 | "application/ecmascript, application/x-ecmascript" 21 | }, 22 | contents: { 23 | script: /\b(?:java|ecma)script\b/ 24 | }, 25 | converters: { 26 | "text script": function( text ) { 27 | jQuery.globalEval( text ); 28 | return text; 29 | } 30 | } 31 | } ); 32 | 33 | // Handle cache's special case and crossDomain 34 | jQuery.ajaxPrefilter( "script", function( s ) { 35 | if ( s.cache === undefined ) { 36 | s.cache = false; 37 | } 38 | if ( s.crossDomain ) { 39 | s.type = "GET"; 40 | } 41 | } ); 42 | 43 | // Bind script tag hack transport 44 | jQuery.ajaxTransport( "script", function( s ) { 45 | 46 | // This transport only deals with cross domain requests 47 | if ( s.crossDomain ) { 48 | var script, callback; 49 | return { 50 | send: function( _, complete ) { 51 | script = jQuery( "