Removes IdentityServer4 usage
This commit is contained in:
@ -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<string> 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; }
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -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<ScopeViewModel> ApiScopes { get; set; }
|
||||
|
||||
public IEnumerable<ScopeViewModel> IdentityScopes { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -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; }
|
||||
|
||||
}
|
||||
}
|
@ -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; }
|
||||
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
||||
}
|
@ -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<IdentityServerOptions> _options;
|
||||
private readonly ILogger<DeviceController> _logger;
|
||||
|
||||
public DeviceController(
|
||||
IDeviceFlowInteractionService interaction,
|
||||
IEventService eventService,
|
||||
IOptions<IdentityServerOptions> options,
|
||||
ILogger<DeviceController> logger)
|
||||
{
|
||||
_interaction = interaction;
|
||||
_events = eventService;
|
||||
_options = options;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> 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<IActionResult> UserCodeCapture(string userCode)
|
||||
{
|
||||
var vm = await BuildViewModelAsync(userCode);
|
||||
if (vm == null) return View("Error");
|
||||
|
||||
return View("UserCodeConfirmation", vm);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> 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<ProcessConsentResult> 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<DeviceAuthorizationViewModel> 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<string>(),
|
||||
|
||||
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<ScopeViewModel>();
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -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<string[]>(value);
|
||||
}
|
||||
}
|
||||
|
||||
public AuthenticateResult AuthenticateResult { get; }
|
||||
public IEnumerable<string> Clients { get; } = new List<string>();
|
||||
}
|
||||
}
|
@ -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; }
|
||||
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using IdentityServer4.Models;
|
||||
|
||||
namespace nuget_host.Models
|
||||
{
|
||||
public class RepositoryIdentityResource : IdentityResource
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -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<TestUser> Users
|
||||
{
|
||||
get
|
||||
{
|
||||
var address = new
|
||||
{
|
||||
street_address = "One Hacker Way",
|
||||
locality = "Heidelberg",
|
||||
postal_code = 69118,
|
||||
country = "Germany"
|
||||
};
|
||||
|
||||
return new List<TestUser>
|
||||
{
|
||||
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)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user