diff --git a/Config.cs b/Config.cs deleted file mode 100644 index 678f530..0000000 --- a/Config.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Collections.Generic; -using IdentityServer4; -using IdentityServer4.Models; -using IdentityServer4.Test; - -namespace nuget_host -{ - public static class Config -{ - public static IEnumerable IdentityResources => - new List - { - new IdentityResources.OpenId(), - new IdentityResources.Profile(), - }; - - public static IEnumerable ApiResources => - new List - { - new ApiResource(IdentityServerConstants.LocalApi.ScopeName), - new ApiResource(scope_packages) - }; - - public const string scope_packages = "packages"; - - public static IEnumerable Clients => - new List - { - // machine to machine client - new Client - { - ClientId = "client", - ClientSecrets = { new Secret("secret".Sha256()) }, - - AllowedGrantTypes = GrantTypes.ClientCredentials, - // scopes that client has access to - AllowedScopes = { scope_packages, - IdentityServerConstants.LocalApi.ScopeName } - }, - - // interactive ASP.NET Core MVC client - new Client - { - ClientId = "mvc", - ClientSecrets = { new Secret("secret".Sha256()) }, - - AllowedGrantTypes = GrantTypes.Code, - - // where to redirect to after login - RedirectUris = { "https://localhost:5002/signin-oidc" }, - - // where to redirect to after logout - PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" }, - - AllowedScopes = new List - { - IdentityServerConstants.StandardScopes.OpenId, - IdentityServerConstants.StandardScopes.Profile, - IdentityServerConstants.LocalApi.ScopeName, - scope_packages - } - } - }; - - public static List TestUsers { get; internal set; } - } -} \ No newline at end of file diff --git a/Controllers/AccountController.cs b/Controllers/AccountController.cs index 53cf395..2d9c9f5 100644 --- a/Controllers/AccountController.cs +++ b/Controllers/AccountController.cs @@ -1,15 +1,6 @@ // Copyright (c) Brock Allen & Dominick Baier. All rights reserved. // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - -using IdentityModel; -using IdentityServer4; -using IdentityServer4.Events; -using IdentityServer4.Extensions; -using IdentityServer4.Models; -using IdentityServer4.Services; -using IdentityServer4.Stores; -using IdentityServer4.Test; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -30,27 +21,18 @@ namespace nuget_host.Controllers [SecurityHeaders] [AllowAnonymous] public class AccountController : Controller - { - private readonly IIdentityServerInteractionService _interaction; - private readonly IClientStore _clientStore; + { private readonly IAuthenticationSchemeProvider _schemeProvider; - private readonly IEventService _events; private readonly SignInManager _signInManager; private readonly UserManager _userManager; public AccountController( - IIdentityServerInteractionService interaction, - IClientStore clientStore, IAuthenticationSchemeProvider schemeProvider, - IEventService events, SignInManager signInManager, UserManager userManager) { - _interaction = interaction; - _clientStore = clientStore; _schemeProvider = schemeProvider; - _events = events; _signInManager = signInManager; _userManager = userManager; } @@ -80,35 +62,13 @@ namespace nuget_host.Controllers [ValidateAntiForgeryToken] public async Task Login(LoginInputModel model, string button) { - // check if we are in the context of an authorization request - var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - + // the user clicked the "cancel" button if (button != "login") { - if (context != null) - { - // if the user cancels, send a result back into IdentityServer as if they - // denied the consent (even if this client does not require consent). - // this will send back an access denied OIDC error response to the client. - - // FIXME await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied); - - // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - if (context.IsNativeClient()) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage("Redirect", model.ReturnUrl); - } - - return Redirect(model.ReturnUrl); - } - else - { - // since we don't have a valid context, then we just go back to the home page - return Redirect("~/"); - } + + // since we don't have a valid context, then we just go back to the home page + return Redirect("~/"); } if (ModelState.IsValid) @@ -119,8 +79,7 @@ namespace nuget_host.Controllers if (signResult.Succeeded) { - await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id, user.FullName, true, clientId: context?.ClientId)); - + // only set explicit expiration here if user chooses "remember me". // otherwise we rely upon expiration configured in cookie middleware. AuthenticationProperties props = null; @@ -132,29 +91,6 @@ namespace nuget_host.Controllers ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) }; }; - - // issue authentication cookie with subject ID and username - var isuser = new IdentityServerUser(user.Id) - { - DisplayName = user.UserName - }; - - await HttpContext.SignInAsync(isuser, props); - - if (context != null) - { - if (context.IsNativeClient()) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage("Redirect", model.ReturnUrl); - } - - // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - return Redirect(model.ReturnUrl); - } - - // request for a local page await _signInManager.SignInAsync(user, model.RememberLogin && AccountOptions.AllowRememberLogin); if (Url.IsLocalUrl(model.ReturnUrl)) @@ -172,7 +108,6 @@ namespace nuget_host.Controllers } } - await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials", clientId:context?.ClientId)); ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage); } @@ -215,9 +150,6 @@ namespace nuget_host.Controllers { // delete local authentication cookie await HttpContext.SignOutAsync(); - - // raise the logout event - await _events.RaiseAsync(new UserLogoutSuccessEvent(User.GetSubjectId(), User.GetDisplayName())); } // check if we need to trigger sign-out at an upstream identity provider @@ -231,7 +163,7 @@ namespace nuget_host.Controllers // this triggers a redirect to the external provider for sign-out return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme); } - + return View("LoggedOut", vm); } @@ -247,26 +179,7 @@ namespace nuget_host.Controllers /*****************************************/ private async Task BuildLoginViewModelAsync(string returnUrl) { - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - if (context?.IdP != null && await _schemeProvider.GetSchemeAsync(context.IdP) != null) - { - var local = context.IdP == IdentityServer4.IdentityServerConstants.LocalIdentityProvider; - - // this is meant to short circuit the UI and only trigger the one external IdP - var vm = new LoginViewModel - { - EnableLocalLogin = local, - ReturnUrl = returnUrl, - Username = context?.LoginHint, - }; - - if (!local) - { - vm.ExternalProviders = new[] { new ExternalProvider { AuthenticationScheme = context.IdP } }; - } - - return vm; - } + var schemes = await _schemeProvider.GetAllSchemesAsync(); @@ -279,26 +192,13 @@ namespace nuget_host.Controllers }).ToList(); var allowLocal = true; - if (context?.ClientId != null) - { - var client = await _clientStore.FindEnabledClientByIdAsync(context.ClientId); - if (client != null) - { - allowLocal = client.EnableLocalLogin; - - if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Any()) - { - providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme)).ToList(); - } - } - } + return new LoginViewModel { AllowRememberLogin = AccountOptions.AllowRememberLogin, EnableLocalLogin = allowLocal && AccountOptions.AllowLocalLogin, ReturnUrl = returnUrl, - Username = context?.LoginHint, ExternalProviders = providers.ToArray() }; } @@ -322,14 +222,6 @@ namespace nuget_host.Controllers return vm; } - var context = await _interaction.GetLogoutContextAsync(logoutId); - if (context?.ShowSignoutPrompt == false) - { - // it's safe to automatically sign-out - vm.ShowLogoutPrompt = false; - return vm; - } - // show the logout prompt. this prevents attacks where the user // is automatically signed out by another malicious web page. return vm; @@ -337,39 +229,13 @@ namespace nuget_host.Controllers private async Task BuildLoggedOutViewModelAsync(string logoutId) { - // get context information (client name, post logout redirect URI and iframe for federated signout) - var logout = await _interaction.GetLogoutContextAsync(logoutId); - + var vm = new LoggedOutViewModel { AutomaticRedirectAfterSignOut = AccountOptions.AutomaticRedirectAfterSignOut, - PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, - ClientName = string.IsNullOrEmpty(logout?.ClientName) ? logout?.ClientId : logout?.ClientName, - SignOutIframeUrl = logout?.SignOutIFrameUrl, LogoutId = logoutId }; - - if (User?.Identity.IsAuthenticated == true) - { - var idp = User.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; - if (idp != null && idp != IdentityServer4.IdentityServerConstants.LocalIdentityProvider) - { - var providerSupportsSignout = await HttpContext.GetSchemeSupportsSignOutAsync(idp); - if (providerSupportsSignout) - { - if (vm.LogoutId == null) - { - // if there's no current logout context, we need to create one - // this captures necessary info from the current logged in user - // before we signout and redirect away to the external IdP for signout - vm.LogoutId = await _interaction.CreateLogoutContextAsync(); - } - - vm.ExternalAuthenticationScheme = idp; - } - } - } - + return vm; } } diff --git a/Controllers/ConsentController.cs b/Controllers/ConsentController.cs deleted file mode 100644 index 8632638..0000000 --- a/Controllers/ConsentController.cs +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using IdentityServer4.Events; -using IdentityServer4.Models; -using IdentityServer4.Services; -using IdentityServer4.Extensions; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; -using System.Linq; -using System.Threading.Tasks; -using System.Collections.Generic; -using System; -using nuget_host.Models; - -namespace nuget_host.Controllers -{ - /// - /// This controller processes the consent UI - /// - [SecurityHeaders] - [Authorize] - public class ConsentController : Controller - { - private readonly IIdentityServerInteractionService _interaction; - private readonly IEventService _events; - private readonly ILogger _logger; - - public ConsentController( - IIdentityServerInteractionService interaction, - IEventService events, - ILogger logger) - { - _interaction = interaction; - _events = events; - _logger = logger; - } - - /// - /// Shows the consent screen - /// - /// - /// - [HttpGet] - public async Task Index(string returnUrl) - { - var vm = await BuildViewModelAsync(returnUrl); - if (vm != null) - { - return View("Index", vm); - } - - return View("Error"); - } - - /// - /// Handles the consent screen postback - /// - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Index(ConsentInputModel model) - { - var result = await ProcessConsent(model); - - if (result.IsRedirect) - { - var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - if (context?.IsNativeClient() == true) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage("Redirect", result.RedirectUri); - } - - return Redirect(result.RedirectUri); - } - - if (result.HasValidationError) - { - ModelState.AddModelError(string.Empty, result.ValidationError); - } - - if (result.ShowView) - { - return View("Index", result.ViewModel); - } - - return View("Error"); - } - - /*****************************************/ - /* helper APIs for the ConsentController */ - /*****************************************/ - private async Task ProcessConsent(ConsentInputModel model) - { - var result = new ProcessConsentResult(); - - // validate return url is still valid - var request = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); - if (request == null) return result; - - ConsentResponse grantedConsent = null; - - // user clicked 'no' - send back the standard 'access_denied' response - if (model?.Button == "no") - { - grantedConsent = ConsentResponse.Denied; - - // emit event - await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.ClientId, request.ScopesRequested)); - } - // user clicked 'yes' - validate the data - else if (model?.Button == "yes") - { - // if the user consented to some scope, build the response model - if (model.ScopesConsented != null && model.ScopesConsented.Any()) - { - var scopes = model.ScopesConsented; - if (ConsentOptions.EnableOfflineAccess == false) - { - scopes = scopes.Where(x => x != IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess); - } - - grantedConsent = new ConsentResponse - { - RememberConsent = model.RememberConsent, - ScopesConsented = scopes.ToArray() - }; - - // emit event - await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.ClientId, request.ScopesRequested, grantedConsent.ScopesConsented, grantedConsent.RememberConsent)); - } - else - { - result.ValidationError = ConsentOptions.MustChooseOneErrorMessage; - } - } - else - { - result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage; - } - - if (grantedConsent != null) - { - // communicate outcome of consent back to identityserver - await _interaction.GrantConsentAsync(request, grantedConsent); - - // indicate that's it ok to redirect back to authorization endpoint - result.RedirectUri = model.ReturnUrl; - result.Client = model.Client; - } - else - { - // we need to redisplay the consent UI - result.ViewModel = await BuildViewModelAsync(model.ReturnUrl, model); - } - - return result; - } - - private async Task BuildViewModelAsync(string returnUrl, ConsentInputModel model = null) - { - var request = await _interaction.GetAuthorizationContextAsync(returnUrl); - if (request != null) - { - return CreateConsentViewModel(model, returnUrl, request); - } - else - { - _logger.LogError("No consent request matching request: {0}", returnUrl); - } - - return null; - } - - private ConsentViewModel CreateConsentViewModel( - ConsentInputModel model, string returnUrl, - AuthorizationRequest request) - { - var vm = new ConsentViewModel - { - RememberConsent = model?.RememberConsent ?? true, - ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), - Description = model?.Description, - - ReturnUrl = returnUrl, - ClientName = model.ClientName, - ClientUrl = model.ClientUri, - ClientLogoUrl = model.LogoUri, - AllowRememberConsent = model.AllowRememberConsent - }; - - vm.IdentityScopes = model.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); - - var apiScopes = new List(); - foreach(var parsedScope in model.ValidatedResources.ParsedScopes.Scopes) - { - var apiScope = model.ValidatedResources.Resources.FindApiScope(parsedScope); - if (apiScope != null) - { - var scopeVm = CreateScopeViewModel(model.ValidatedResources.ParsedScopes, apiScope, vm.ScopesConsented.Contains(model.ValidatedResources.ParsedScopes.RawValue) || model == null); - apiScopes.Add(scopeVm); - } - } - if (ConsentOptions.EnableOfflineAccess && model.ValidatedResources.Resources.OfflineAccess) - { - apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); - } - vm.ApiScopes = apiScopes; - - return vm; - } - - private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) - { - return new ScopeViewModel - { - Value = identity.Name, - DisplayName = identity.DisplayName ?? identity.Name, - Description = identity.Description, - Emphasize = identity.Emphasize, - Required = identity.Required, - Checked = check || identity.Required - }; - } - - public ScopeViewModel CreateScopeViewModel(ParsedScopes parsedScope, Scope apiScope, bool check) - { - var displayName = apiScope.DisplayName; - if (!String.IsNullOrWhiteSpace(parsedScope.RawValue)) - { - displayName += ":" + parsedScope.RawValue; - } - - return new ScopeViewModel - { - Value = parsedScope.RawValue, - DisplayName = displayName, - Description = apiScope.Description, - Emphasize = apiScope.Emphasize, - Required = apiScope.Required, - Checked = check || apiScope.Required - }; - } - - private ScopeViewModel GetOfflineAccessScope(bool check) - { - return new ScopeViewModel - { - Value = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess, - DisplayName = ConsentOptions.OfflineAccessDisplayName, - Description = ConsentOptions.OfflineAccessDescription, - Emphasize = true, - Checked = check - }; - } - } -} \ No newline at end of file diff --git a/Controllers/DiagnosticsController.cs b/Controllers/DiagnosticsController.cs deleted file mode 100644 index 99abde5..0000000 --- a/Controllers/DiagnosticsController.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; - -namespace nuget_host.Models -{ - [SecurityHeaders] - [Authorize] - public class DiagnosticsController : Controller - { - public async Task Index() - { - var localAddresses = new string[] { "127.0.0.1", "::1", HttpContext.Connection.LocalIpAddress.ToString() }; - if (!localAddresses.Contains(HttpContext.Connection.RemoteIpAddress.ToString())) - { - return NotFound(); - } - - var model = new DiagnosticsViewModel(await HttpContext.AuthenticateAsync()); - return View(model); - } - } -} \ No newline at end of file diff --git a/Controllers/ExternalController.cs b/Controllers/ExternalController.cs deleted file mode 100644 index 408a6ec..0000000 --- a/Controllers/ExternalController.cs +++ /dev/null @@ -1,198 +0,0 @@ -using IdentityModel; -using IdentityServer4; -using IdentityServer4.Events; -using IdentityServer4.Services; -using IdentityServer4.Stores; -using IdentityServer4.Test; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; -using nuget_host.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace nuget_host.Controllers -{ - [SecurityHeaders] - [AllowAnonymous] - public class ExternalController : Controller - { - private readonly TestUserStore _users; - private readonly IIdentityServerInteractionService _interaction; - private readonly IClientStore _clientStore; - private readonly ILogger _logger; - private readonly IEventService _events; - - public ExternalController( - IIdentityServerInteractionService interaction, - IClientStore clientStore, - IEventService events, - ILogger logger, - TestUserStore users = null) - { - // if the TestUserStore is not in DI, then we'll just use the global users collection - // this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity) - _users = users ?? new TestUserStore(TestUsers.Users); - - _interaction = interaction; - _clientStore = clientStore; - _logger = logger; - _events = events; - } - - /// - /// initiate roundtrip to external authentication provider - /// - [HttpGet] - public IActionResult Challenge(string scheme, string returnUrl) - { - if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/"; - - // validate returnUrl - either it is a valid OIDC URL or back to a local page - if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false) - { - // user might have clicked on a malicious link - should be logged - throw new Exception("invalid return URL"); - } - - // start challenge and roundtrip the return URL and scheme - var props = new AuthenticationProperties - { - RedirectUri = Url.Action(nameof(Callback)), - Items = - { - { "returnUrl", returnUrl }, - { "scheme", scheme }, - } - }; - - return Challenge(props, scheme); - - } - - /// - /// Post processing of external authentication - /// - [HttpGet] - public async Task Callback() - { - // read external identity from the temporary cookie - var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); - if (result?.Succeeded != true) - { - throw new Exception("External authentication error"); - } - - if (_logger.IsEnabled(LogLevel.Debug)) - { - var externalClaims = result.Principal.Claims.Select(c => $"{c.Type}: {c.Value}"); - _logger.LogDebug("External claims: {@claims}", externalClaims); - } - - // lookup our user and external provider info - var (user, provider, providerUserId, claims) = FindUserFromExternalProvider(result); - if (user == null) - { - // this might be where you might initiate a custom workflow for user registration - // in this sample we don't show how that would be done, as our sample implementation - // simply auto-provisions new external user - user = AutoProvisionUser(provider, providerUserId, claims); - } - - // this allows us to collect any additional claims or properties - // for the specific protocols used and store them in the local auth cookie. - // this is typically used to store data needed for signout from those protocols. - var additionalLocalClaims = new List(); - var localSignInProps = new AuthenticationProperties(); - ProcessLoginCallback(result, additionalLocalClaims, localSignInProps); - - // issue authentication cookie for user - var isuser = new IdentityServerUser(user.SubjectId) - { - DisplayName = user.Username, - IdentityProvider = provider, - AdditionalClaims = additionalLocalClaims - }; - - await HttpContext.SignInAsync(isuser, localSignInProps); - - // delete temporary cookie used during external authentication - await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); - - // retrieve return URL - var returnUrl = result.Properties.Items["returnUrl"] ?? "~/"; - - // check if external login is in the context of an OIDC request - var context = await _interaction.GetAuthorizationContextAsync(returnUrl); - await _events.RaiseAsync(new UserLoginSuccessEvent(provider, providerUserId, user.SubjectId, user.Username, true, - context?.ClientId)); - - if (context != null) - { - if (context.IsNativeClient()) - { - // The client is native, so this change in how to - // return the response is for better UX for the end user. - return this.LoadingPage("Redirect", returnUrl); - } - } - - return Redirect(returnUrl); - } - - private (TestUser user, string provider, string providerUserId, IEnumerable claims) FindUserFromExternalProvider(AuthenticateResult result) - { - var externalUser = result.Principal; - - // try to determine the unique id of the external user (issued by the provider) - // the most common claim type for that are the sub claim and the NameIdentifier - // depending on the external provider, some other claim type might be used - var userIdClaim = externalUser.FindFirst(JwtClaimTypes.Subject) ?? - externalUser.FindFirst(ClaimTypes.NameIdentifier) ?? - throw new Exception("Unknown userid"); - - // remove the user id claim so we don't include it as an extra claim if/when we provision the user - var claims = externalUser.Claims.ToList(); - claims.Remove(userIdClaim); - - var provider = result.Properties.Items["scheme"]; - var providerUserId = userIdClaim.Value; - - // find external user - var user = _users.FindByExternalProvider(provider, providerUserId); - - return (user, provider, providerUserId, claims); - } - - private TestUser AutoProvisionUser(string provider, string providerUserId, IEnumerable claims) - { - var user = _users.AutoProvisionUser(provider, providerUserId, claims.ToList()); - return user; - } - - // if the external login is OIDC-based, there are certain things we need to preserve to make logout work - // this will be different for WS-Fed, SAML2p or other protocols - private void ProcessLoginCallback(AuthenticateResult externalResult, List localClaims, AuthenticationProperties localSignInProps) - { - // if the external system sent a session id claim, copy it over - // so we can use it for single sign-out - var sid = externalResult.Principal.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); - if (sid != null) - { - localClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); - } - - // if the external provider issued an id_token, we'll keep it for signout - var idToken = externalResult.Properties.GetTokenValue("id_token"); - if (idToken != null) - { - localSignInProps.StoreTokens(new[] { new AuthenticationToken { Name = "id_token", Value = idToken } }); - } - } - } -} \ No newline at end of file diff --git a/Controllers/GrantsController.cs b/Controllers/GrantsController.cs deleted file mode 100644 index 2386cf2..0000000 --- a/Controllers/GrantsController.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using IdentityServer4.Services; -using IdentityServer4.Stores; -using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authorization; -using IdentityServer4.Events; -using IdentityServer4.Extensions; - -namespace nuget_host.Models -{ - /// - /// This sample controller allows a user to revoke grants given to clients - /// - [SecurityHeaders] - [Authorize] - public class GrantsController : Controller - { - private readonly IIdentityServerInteractionService _interaction; - private readonly IClientStore _clients; - private readonly IResourceStore _resources; - private readonly IEventService _events; - - public GrantsController(IIdentityServerInteractionService interaction, - IClientStore clients, - IResourceStore resources, - IEventService events) - { - _interaction = interaction; - _clients = clients; - _resources = resources; - _events = events; - } - - /// - /// Show list of grants - /// - [HttpGet] - public async Task Index() - { - return View("Index", await BuildViewModelAsync()); - } - - /// - /// Handle postback to revoke a client - /// - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Revoke(string clientId) - { - await _interaction.RevokeUserConsentAsync(clientId); - await _events.RaiseAsync(new GrantsRevokedEvent(User.GetSubjectId(), clientId)); - - return RedirectToAction("Index"); - } - - private async Task BuildViewModelAsync() - { - var grants = await _interaction.GetAllUserConsentsAsync(); - - var list = new List(); - foreach(var grant in grants) - { - var client = await _clients.FindClientByIdAsync(grant.ClientId); - if (client != null) - { - var resources = await _resources.FindResourcesByScopeAsync(grant.Scopes); - - var item = new GrantViewModel() - { - ClientId = client.ClientId, - ClientName = client.ClientName ?? client.ClientId, - ClientLogoUrl = client.LogoUri, - ClientUrl = client.ClientUri, - Description = client.Description, - Created = grant.CreationTime, - Expires = grant.Expiration, - IdentityGrantNames = resources.IdentityResources.Select(x => x.DisplayName ?? x.Name).ToArray(), - ApiGrantNames = resources.ApiResources.Select(x => x.DisplayName ?? x.Name).ToArray() - }; - - list.Add(item); - } - } - - return new GrantsViewModel - { - Grants = list - }; - } - } -} \ No newline at end of file diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs index a6d8144..ccf697a 100644 --- a/Controllers/HomeController.cs +++ b/Controllers/HomeController.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using IdentityServer4.Services; +using System.Threading.Tasks; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; @@ -16,7 +11,6 @@ namespace nuget_host.Controllers { public class HomeController : Controller { - private readonly IIdentityServerInteractionService _interaction; private readonly ILogger _logger; readonly IHostingEnvironment _environment; public IDataProtector DataProtector { get; } @@ -24,10 +18,8 @@ namespace nuget_host.Controllers public HomeController( IOptions smtpSettings, - IDataProtectionProvider provider, - IIdentityServerInteractionService interaction, Microsoft.AspNetCore.Hosting.IHostingEnvironment environment, ILogger logger) + IDataProtectionProvider provider, Microsoft.AspNetCore.Hosting.IHostingEnvironment environment, ILogger logger) { - _interaction = interaction; _environment = environment; _logger = logger; Options = smtpSettings.Value; @@ -60,29 +52,5 @@ namespace nuget_host.Controllers return Ok(ViewData); } - - /// - /// Shows the error page - /// - public async Task Error(string errorId) - { - var vm = new ErrorViewModel(); - - // retrieve error details from identityserver - var message = await _interaction.GetErrorContextAsync(errorId); - if (message != null) - { - vm.Error = message; - - if (!_environment.IsDevelopment()) - { - // only show in development - message.ErrorDescription = null; - } - } - - return View("Error", vm); - } - } } diff --git a/Extensions/Extensions.cs b/Extensions/Extensions.cs index 88ad50d..4ea7aaa 100644 --- a/Extensions/Extensions.cs +++ b/Extensions/Extensions.cs @@ -1,20 +1,10 @@ using System; -using IdentityServer4.Models; using Microsoft.AspNetCore.Mvc; namespace nuget_host.Models { public static class Extensions { - /// - /// Checks if the redirect URI is for a native client. - /// - /// - public static bool IsNativeClient(this AuthorizationRequest context) - { - return !context.RedirectUri.StartsWith("https", StringComparison.Ordinal) - && !context.RedirectUri.StartsWith("http", StringComparison.Ordinal); - } public static IActionResult LoadingPage(this Controller controller, string viewName, string redirectUri) { diff --git a/Models/Consent/ConsentInputModel.cs b/Models/Consent/ConsentInputModel.cs deleted file mode 100644 index 461684b..0000000 --- a/Models/Consent/ConsentInputModel.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using System.Collections.Generic; -using IdentityServer4.Models; - -namespace nuget_host.Models -{ - public class ConsentInputModel - { - public string Button { get; set; } - public IEnumerable ScopesConsented { get; set; } - public bool RememberConsent { get; set; } - public string ReturnUrl { get; set; } - public string Description { get; set; } - public string ClientName { get; internal set; } - public string ClientUri { get; internal set; } - public string LogoUri { get; internal set; } - public bool AllowRememberConsent { get; internal set; } - public ValidatedResources ValidatedResources { get; internal set; } - public Client Client { get; internal set; } - } -} \ No newline at end of file diff --git a/Models/Consent/ConsentOptions.cs b/Models/Consent/ConsentOptions.cs deleted file mode 100644 index bd87a1a..0000000 --- a/Models/Consent/ConsentOptions.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace nuget_host.Models -{ - public class ConsentOptions - { - public static bool EnableOfflineAccess = true; - public static string OfflineAccessDisplayName = "Offline Access"; - public static string OfflineAccessDescription = "Access to your applications and resources, even when you are offline"; - - public static readonly string MustChooseOneErrorMessage = "You must pick at least one permission"; - public static readonly string InvalidSelectionErrorMessage = "Invalid selection"; - } -} diff --git a/Models/Consent/ConsentViewModel.cs b/Models/Consent/ConsentViewModel.cs deleted file mode 100644 index 3b4846a..0000000 --- a/Models/Consent/ConsentViewModel.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using System.Collections.Generic; - -namespace nuget_host.Models -{ - public class ConsentViewModel : ConsentInputModel - { - public string ClientLogoUrl { get; set; } - public string ClientUrl { get; set; } - - public IEnumerable ApiScopes { get; set; } - - public IEnumerable IdentityScopes { get; set; } - - - } -} diff --git a/Models/Consent/ParsedScopes.cs b/Models/Consent/ParsedScopes.cs deleted file mode 100644 index a768159..0000000 --- a/Models/Consent/ParsedScopes.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using System.Collections.Generic; -using IdentityServer4.Models; - -namespace nuget_host.Models -{ - public class ParsedScopes - { - public ParsedScopes(ParsedSecret secret) - { - RawValue = secret.Properties.ContainsKey(KEY_SCOPES) ? null : secret.Properties[KEY_SCOPES]; - Emphasize = secret.Properties.ContainsKey(KEY_OL); - if (secret.Properties.ContainsKey(KEY_SCOPES)) Scopes = secret.Properties[KEY_SCOPES].Split(','); - } - - public const string KEY_SCOPES = "scopes"; - public const string KEY_OL = "ol"; - public string RawValue { - get ; - } - - - public string[] Scopes { get ; protected set; } - public bool Emphasize { get; } - } -} \ No newline at end of file diff --git a/Models/Consent/ProcessConsentResult.cs b/Models/Consent/ProcessConsentResult.cs deleted file mode 100644 index 5c6cd90..0000000 --- a/Models/Consent/ProcessConsentResult.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using IdentityServer4.Models; - -namespace nuget_host.Models -{ - public class ProcessConsentResult - { - public bool IsRedirect => RedirectUri != null; - public string RedirectUri { get; set; } - public Client Client { get; set; } - - public bool ShowView => ViewModel != null; - public ConsentViewModel ViewModel { get; set; } - - public bool HasValidationError => ValidationError != null; - public string ValidationError { get; set; } - } -} diff --git a/Models/Consent/QSAuthorizationRequest.cs b/Models/Consent/QSAuthorizationRequest.cs deleted file mode 100644 index 6328f0d..0000000 --- a/Models/Consent/QSAuthorizationRequest.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using IdentityServer4.Models; -using IdentityServer4.Validation; -using NuGet.Packaging; - -namespace nuget_host.OAuth -{ - internal class NHAuthorizationRequest : AuthorizationRequest - { - internal NHAuthorizationRequest(ValidatedAuthorizeRequest request) : base() - { - ClientId = request.ClientId; - RedirectUri = request.RedirectUri; - DisplayMode = request.DisplayMode; - UiLocales = request.UiLocales; - IdP = request.GetIdP(); - Tenant = request.GetTenant(); - LoginHint = request.LoginHint; - PromptMode = request.PromptMode; - AcrValues = request.GetAcrValues(); - ScopesRequested = request.RequestedScopes; - Parameters.Add(request.Raw); - RequestObjectValues.AddRange(request.RequestObjectValues); - } - - } -} \ No newline at end of file diff --git a/Models/Consent/ScopeViewModel.cs b/Models/Consent/ScopeViewModel.cs deleted file mode 100644 index d7834cb..0000000 --- a/Models/Consent/ScopeViewModel.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace nuget_host.Models -{ - public class ScopeViewModel - { - public string Value { get; set; } - public string DisplayName { get; set; } - public string Description { get; set; } - public bool Emphasize { get; set; } - public bool Required { get; set; } - public bool Checked { get; set; } - } -} diff --git a/Models/Consent/ValidatedResource.cs b/Models/Consent/ValidatedResource.cs deleted file mode 100644 index bb2634c..0000000 --- a/Models/Consent/ValidatedResource.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using IdentityServer4.Models; -using System.Collections.Generic; - -namespace nuget_host.Models -{ - public class ValidatedResources - { - public Resources Resources { get; set; } - public ParsedScopes ParsedScopes { get; internal set; } - public bool OfflineAccess { get; internal set; } - - } -} \ No newline at end of file diff --git a/Models/Device/DeviceAuthorizationInputModel.cs b/Models/Device/DeviceAuthorizationInputModel.cs deleted file mode 100644 index 9c5a6be..0000000 --- a/Models/Device/DeviceAuthorizationInputModel.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace nuget_host.Models -{ - - public class DeviceAuthorizationInputModel : ConsentInputModel - { - public string UserCode { get; set; } - - } -} \ No newline at end of file diff --git a/Models/Device/DeviceAuthorizationViewModel.cs b/Models/Device/DeviceAuthorizationViewModel.cs deleted file mode 100644 index 5823e4a..0000000 --- a/Models/Device/DeviceAuthorizationViewModel.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -namespace nuget_host.Models -{ - public class DeviceAuthorizationViewModel : ConsentViewModel - { - public string UserCode { get; set; } - public bool ConfirmUserCode { get; set; } - } -} \ No newline at end of file diff --git a/Models/Device/DeviceController.cs b/Models/Device/DeviceController.cs deleted file mode 100644 index ed805d8..0000000 --- a/Models/Device/DeviceController.cs +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using IdentityModel.Client; -using IdentityServer4.Configuration; -using IdentityServer4.Events; -using IdentityServer4.Extensions; -using IdentityServer4.Models; -using IdentityServer4.Services; -using IdentityServer4.Validation; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using nuget_host.OAuth; - -namespace nuget_host.Models -{ - [Authorize] - [SecurityHeaders] - public class DeviceController : Controller - { - private readonly IDeviceFlowInteractionService _interaction; - private readonly IEventService _events; - private readonly IOptions _options; - private readonly ILogger _logger; - - public DeviceController( - IDeviceFlowInteractionService interaction, - IEventService eventService, - IOptions options, - ILogger logger) - { - _interaction = interaction; - _events = eventService; - _options = options; - _logger = logger; - } - - [HttpGet] - public async Task Index() - { - string userCodeParamName = _options.Value.UserInteraction.DeviceVerificationUserCodeParameter; - string userCode = Request.Query[userCodeParamName]; - if (string.IsNullOrWhiteSpace(userCode)) return View("UserCodeCapture"); - - var vm = await BuildViewModelAsync(userCode); - if (vm == null) return View("Error"); - - vm.ConfirmUserCode = true; - return View("UserCodeConfirmation", vm); - } - - [HttpPost] - [ValidateAntiForgeryToken] - public async Task UserCodeCapture(string userCode) - { - var vm = await BuildViewModelAsync(userCode); - if (vm == null) return View("Error"); - - return View("UserCodeConfirmation", vm); - } - - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Callback(DeviceAuthorizationInputModel model) - { - if (model == null) throw new ArgumentNullException(nameof(model)); - - var result = await ProcessConsent(model); - if (result.HasValidationError) return View("Error"); - - return View("Success"); - } - - private async Task ProcessConsent(DeviceAuthorizationInputModel model) - { - var result = new ProcessConsentResult(); - - var request = await _interaction.GetAuthorizationContextAsync(model.UserCode); - if (request == null) return result; - - ConsentResponse grantedConsent = null; - - // user clicked 'no' - send back the standard 'access_denied' response - if (model.Button == "no") - { - grantedConsent = ConsentResponse.Denied; - - // emit event - await _events.RaiseAsync(new ConsentDeniedEvent(User.GetSubjectId(), request.ClientId, request.ScopesRequested)); - } - // user clicked 'yes' - validate the data - else if (model.Button == "yes") - { - // if the user consented to some scope, build the response model - if (model.ScopesConsented != null && model.ScopesConsented.Any()) - { - var scopes = model.ScopesConsented; - if (ConsentOptions.EnableOfflineAccess == false) - { - scopes = scopes.Where(x => x != IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess); - } - - grantedConsent = new ConsentResponse - { - RememberConsent = model.RememberConsent, - ScopesConsented = scopes.ToArray() - }; - - // emit event - await _events.RaiseAsync(new ConsentGrantedEvent(User.GetSubjectId(), request.ClientId, request.ScopesRequested, grantedConsent.ScopesConsented, grantedConsent.RememberConsent)); - } - else - { - result.ValidationError = ConsentOptions.MustChooseOneErrorMessage; - } - } - else - { - result.ValidationError = ConsentOptions.InvalidSelectionErrorMessage; - } - - if (grantedConsent != null) - { - // communicate outcome of consent back to identityserver - await _interaction.HandleRequestAsync(model.UserCode, grantedConsent); - - // indicate that's it ok to redirect back to authorization endpoint - result.RedirectUri = model.ReturnUrl; - result.Client = model.Client; - } - else - { - // we need to redisplay the consent UI - result.ViewModel = await BuildViewModelAsync(model.UserCode, model); - } - - return result; - } - - private async Task BuildViewModelAsync(string userCode, DeviceAuthorizationInputModel model = null) - { - var request = await _interaction.GetAuthorizationContextAsync(userCode); - if (request != null) - { - return CreateConsentViewModel(userCode, model, request); - } - - return null; - } - - private DeviceAuthorizationViewModel CreateConsentViewModel( - string userCode, DeviceAuthorizationInputModel model, - DeviceFlowAuthorizationRequest request) - { - var vm = new DeviceAuthorizationViewModel - { - UserCode = userCode, - Description = model?.Description, - - RememberConsent = model?.RememberConsent ?? true, - ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty(), - - ClientName = model?.ClientName, - ClientUrl = model?.ClientUri, - ClientLogoUrl = model?.LogoUri, - AllowRememberConsent = model != null && model.AllowRememberConsent - }; - - vm.IdentityScopes = model.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); - - var apiScopes = new List(); - foreach (var parsedScope in model.ValidatedResources.ParsedScopes.Scopes) - { - var apiScope = model.ValidatedResources.Resources.FindApiScope(parsedScope); - if (apiScope != null) - { - var vreq = CreateValidatedRequest(request, apiScope); - - var scopeVm = CreateScopeViewModel(apiScope,vreq); - apiScopes.Add(scopeVm); - } - } - if (ConsentOptions.EnableOfflineAccess && model.ValidatedResources.Resources.OfflineAccess) - { - apiScopes.Add(GetOfflineAccessScope(vm.ScopesConsented.Contains(IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess) || model == null)); - } - vm.ApiScopes = apiScopes; - - return vm; - } - - private ValidatedAuthorizeRequest CreateValidatedRequest(DeviceFlowAuthorizationRequest request, Scope apiScope) - { - throw new NotImplementedException(); - } - - private ScopeViewModel CreateScopeViewModel(Scope scope, ValidatedAuthorizeRequest req) - { - return new ScopeViewModel - { - Value = scope.Name, - DisplayName = scope.DisplayName ?? scope.Name, - Description = scope.Description, - Emphasize = scope.Emphasize, - Required = scope.Required, - Checked = req.Client != null - }; - } - - private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check) - { - return new ScopeViewModel - { - Value = identity.Name, - DisplayName = identity.DisplayName ?? identity.Name, - Description = identity.Description, - Emphasize = identity.Emphasize, - Required = identity.Required, - Checked = check || identity.Required - }; - } - - public ScopeViewModel CreateScopeViewModel(ParsedScopes parsedScopeValue, Scope apiScope, bool check) - { - return new ScopeViewModel - { - Value = parsedScopeValue.RawValue, - // todo: use the parsed scope value in the display? - DisplayName = apiScope.DisplayName, - Description = apiScope.Description, - Emphasize = parsedScopeValue.Emphasize, - Required = apiScope.Required, - Checked = check || apiScope.Required - }; - } - private ScopeViewModel GetOfflineAccessScope(bool check) - { - return new ScopeViewModel - { - Value = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess, - DisplayName = ConsentOptions.OfflineAccessDisplayName, - Description = ConsentOptions.OfflineAccessDescription, - Emphasize = true, - Checked = check - }; - } - } -} \ No newline at end of file diff --git a/Models/Diagnostic/DiagnosticsViewModel.cs b/Models/Diagnostic/DiagnosticsViewModel.cs deleted file mode 100644 index 0561372..0000000 --- a/Models/Diagnostic/DiagnosticsViewModel.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using IdentityModel; -using Microsoft.AspNetCore.Authentication; -using Newtonsoft.Json; -using System.Collections.Generic; -using System.Text; - -namespace nuget_host.Models -{ - public class DiagnosticsViewModel - { - public DiagnosticsViewModel(AuthenticateResult result) - { - AuthenticateResult = result; - - if (result.Properties.Items.ContainsKey("client_list")) - { - var encoded = result.Properties.Items["client_list"]; - var bytes = Base64Url.Decode(encoded); - var value = Encoding.UTF8.GetString(bytes); - - Clients = JsonConvert.DeserializeObject(value); - } - } - - public AuthenticateResult AuthenticateResult { get; } - public IEnumerable Clients { get; } = new List(); - } -} \ No newline at end of file diff --git a/Models/ErrorViewModel.cs b/Models/ErrorViewModel.cs deleted file mode 100644 index fd46706..0000000 --- a/Models/ErrorViewModel.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using IdentityServer4.Models; - -namespace nuget_host.Models -{ - public class ErrorViewModel - { - public string RequestId { get; set; } - - public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - - - public ErrorViewModel() - { - } - - public ErrorViewModel(string error) - { - Error = new ErrorMessage { Error = error }; - } - - public ErrorMessage Error { get; set; } - - } -} \ No newline at end of file diff --git a/Models/RepositoryIdentityResource.cs b/Models/RepositoryIdentityResource.cs deleted file mode 100644 index 8be220c..0000000 --- a/Models/RepositoryIdentityResource.cs +++ /dev/null @@ -1,9 +0,0 @@ -using IdentityServer4.Models; - -namespace nuget_host.Models -{ - public class RepositoryIdentityResource : IdentityResource - { - - } -} \ No newline at end of file diff --git a/Models/TestUsers.cs b/Models/TestUsers.cs deleted file mode 100644 index 6a6dcdc..0000000 --- a/Models/TestUsers.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. -// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. - - -using IdentityModel; -using IdentityServer4.Test; -using System.Collections.Generic; -using System.Security.Claims; -using IdentityServer4; -using Newtonsoft.Json; - -namespace nuget_host.Models -{ - public class TestUsers - { - public static List Users - { - get - { - var address = new - { - street_address = "One Hacker Way", - locality = "Heidelberg", - postal_code = 69118, - country = "Germany" - }; - - return new List - { - new TestUser - { - SubjectId = "818727", - Username = "alice", - Password = "alice", - Claims = - { - new Claim(JwtClaimTypes.Name, "Alice Smith"), - new Claim(JwtClaimTypes.GivenName, "Alice"), - new Claim(JwtClaimTypes.FamilyName, "Smith"), - new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"), - new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), - new Claim(JwtClaimTypes.WebSite, "http://alice.com"), - new Claim(JwtClaimTypes.Address, JsonConvert.SerializeObject(address), IdentityServerConstants.ClaimValueTypes.Json) - } - }, - new TestUser - { - SubjectId = "88421113", - Username = "bob", - Password = "bob", - Claims = - { - new Claim(JwtClaimTypes.Name, "Bob Smith"), - new Claim(JwtClaimTypes.GivenName, "Bob"), - new Claim(JwtClaimTypes.FamilyName, "Smith"), - new Claim(JwtClaimTypes.Email, "BobSmith@email.com"), - new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), - new Claim(JwtClaimTypes.WebSite, "http://bob.com"), - new Claim(JwtClaimTypes.Address, JsonConvert.SerializeObject(address), IdentityServerConstants.ClaimValueTypes.Json) - } - } - }; - } - } - } -} \ No newline at end of file diff --git a/Startup.cs b/Startup.cs index 4efcf25..0c872b0 100644 --- a/Startup.cs +++ b/Startup.cs @@ -47,17 +47,6 @@ namespace nuget_host .AddDefaultUI() .AddDefaultTokenProviders(); - services.AddIdentityServer(options => - { - options.Discovery.CustomEntries.Add("local_api", "~/localapi"); - }) - .AddAspNetIdentity() - .AddInMemoryClients(Config.Clients) - .AddInMemoryIdentityResources(Config.IdentityResources) - .AddInMemoryApiResources(Config.ApiResources) - .AddDeveloperSigningCredential() - .AddTestUsers(Config.TestUsers); - services.AddMvc(); services.AddDataProtection(); diff --git a/Views/Consent/Index.cshtml b/Views/Consent/Index.cshtml deleted file mode 100644 index f8aa10d..0000000 --- a/Views/Consent/Index.cshtml +++ /dev/null @@ -1,104 +0,0 @@ -@model ConsentViewModel - - diff --git a/Views/Device/Success.cshtml b/Views/Device/Success.cshtml deleted file mode 100644 index 050dd91..0000000 --- a/Views/Device/Success.cshtml +++ /dev/null @@ -1,7 +0,0 @@ - -
-
-

Success

-

You have successfully authorized the device

-
-
diff --git a/Views/Device/UserCodeCapture.cshtml b/Views/Device/UserCodeCapture.cshtml deleted file mode 100644 index 6d41261..0000000 --- a/Views/Device/UserCodeCapture.cshtml +++ /dev/null @@ -1,23 +0,0 @@ -@model string - -
-
-

User Code

-

Please enter the code displayed on your device.

-
- - - -
-
-
-
- - -
- - -
-
-
-
diff --git a/Views/Device/UserCodeConfirmation.cshtml b/Views/Device/UserCodeConfirmation.cshtml deleted file mode 100644 index e1d3b19..0000000 --- a/Views/Device/UserCodeConfirmation.cshtml +++ /dev/null @@ -1,108 +0,0 @@ -@model DeviceAuthorizationViewModel - -
-
- @if (Model.ClientLogoUrl != null) - { - - } -

- @Model.ClientName - is requesting your permission -

- @if (Model.ConfirmUserCode) - { -

Please confirm that the authorization request quotes the code: @Model.UserCode.

- } -

Uncheck the permissions you do not wish to grant.

-
- -
-
- -
-
- -
- -
-
- @if (Model.IdentityScopes.Any()) - { -
-
-
- - Personal Information -
-
    - @foreach (var scope in Model.IdentityScopes) - { - - } -
-
-
- } - - @if (Model.ApiScopes.Any()) - { -
-
-
- - Application Access -
-
    - @foreach (var scope in Model.ApiScopes) - { - - } -
-
-
- } - -
-
-
- - Description -
-
- -
-
-
- - @if (Model.AllowRememberConsent) - { -
-
- - -
-
- } -
-
- -
-
- - -
-
- @if (Model.ClientUrl != null) - { - - - @Model.ClientName - - } -
-
-
-
diff --git a/Views/Diagnostics/Index.cshtml b/Views/Diagnostics/Index.cshtml deleted file mode 100644 index e939c0d..0000000 --- a/Views/Diagnostics/Index.cshtml +++ /dev/null @@ -1,64 +0,0 @@ -@model DiagnosticsViewModel - -
-
-

Authentication Cookie

-
- -
-
-
-
-

Claims

-
-
-
- @foreach (var claim in Model.AuthenticateResult.Principal.Claims) - { -
@claim.Type
-
@claim.Value
- } -
-
-
-
- -
-
-
-

Properties

-
-
-
- @foreach (var prop in Model.AuthenticateResult.Properties.Items) - { -
@prop.Key
-
@prop.Value
- } - @if (Model.Clients.Any()) - { -
Clients
-
- @{ - var clients = Model.Clients.ToArray(); - for(var i = 0; i < clients.Length; i++) - { - @clients[i] - if (i < clients.Length - 1) - { - , - } - } - } -
- } -
-
-
-
-
-
- - - - diff --git a/Views/Home/Index.cshtml b/Views/Home/Index.cshtml index fc68321..7ec6551 100644 --- a/Views/Home/Index.cshtml +++ b/Views/Home/Index.cshtml @@ -1,33 +1,11 @@ @{ - ViewData["Title"] = "Home Page"; - var version = FileVersionInfo.GetVersionInfo(typeof(IdentityServer4.Hosting.IdentityServerMiddleware).Assembly.Location).ProductVersion.Split('+').First(); -} + ViewData["Title"] = "Home Page";}

Welcome

Learn about building Web apps with ASP.NET Core.

- Welcome to IdentityServer4 - (version @version) + Welcome to Nuget host

- -
diff --git a/Views/Shared/Error.cshtml b/Views/Shared/Error.cshtml deleted file mode 100644 index 4c746e7..0000000 --- a/Views/Shared/Error.cshtml +++ /dev/null @@ -1,40 +0,0 @@ -@model ErrorViewModel - -@{ - var error = Model?.Error?.Error; - var errorDescription = Model?.Error?.ErrorDescription; - var request_id = Model?.Error?.RequestId; -} - -
-
-

Error

-
- -
-
-
- Sorry, there was an error - - @if (error != null) - { - - - : @error - - - - if (errorDescription != null) - { -
@errorDescription
- } - } -
- - @if (request_id != null) - { -
Request Id: @request_id
- } -
-
-
diff --git a/Views/Shared/_Nav.cshtml b/Views/Shared/_Nav.cshtml index 6ab6b70..83ed47e 100644 --- a/Views/Shared/_Nav.cshtml +++ b/Views/Shared/_Nav.cshtml @@ -1,10 +1,9 @@ -@using IdentityServer4.Extensions - + @{ string name = null; if (!true.Equals(ViewData["signed-out"])) { - name = Context.User?.GetDisplayName(); + name = User.Identity.Name; } } @@ -13,7 +12,7 @@ - IdentityServer4 + Nuget host @if (!string.IsNullOrWhiteSpace(name)) diff --git a/Views/Shared/_ScopeListItem.cshtml b/Views/Shared/_ScopeListItem.cshtml deleted file mode 100644 index 15eebcb..0000000 --- a/Views/Shared/_ScopeListItem.cshtml +++ /dev/null @@ -1,34 +0,0 @@ -@model ScopeViewModel - -
  • - - @if (Model.Required) - { - (required) - } - @if (Model.Description != null) - { - - } -
  • \ No newline at end of file diff --git a/nuget-host.csproj b/nuget-host.csproj index 279d8bc..0c6b851 100644 --- a/nuget-host.csproj +++ b/nuget-host.csproj @@ -16,9 +16,6 @@ - - -