Browse Source

Working on identity server integration.

pull/217/head
Halil İbrahim Kalkan 9 years ago
parent
commit
c84c5b76c1
  1. 7
      src/MicroserviceDemo/MicroserviceDemo.AuthServer/MicroservicesAuthServerModule.cs
  2. 46
      src/MicroserviceDemo/MicroserviceDemo.Web/MicroservicesDemoWebModule.cs
  3. 13
      src/MicroserviceDemo/MicroserviceDemo.Web/Pages/Index.cshtml
  4. 4
      src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/Login.cshtml.cs
  5. 36
      src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/_ScopeListItem.cshtml
  6. 65
      src/Volo.Abp.Account.Web.IdentityServer/Pages/Consent.cshtml
  7. 114
      src/Volo.Abp.Account.Web.IdentityServer/Pages/Consent.cshtml.cs
  8. 3
      src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs
  9. 3
      src/Volo.Abp.Identity.Domain/Microsoft/Extensions/DependencyInjection/AbpIdentityServiceCollectionExtensions.cs
  10. 2
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs
  11. 15
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs
  12. 23
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs
  13. 5
      src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientAutoMapperProfile.cs

7
src/MicroserviceDemo/MicroserviceDemo.AuthServer/MicroservicesAuthServerModule.cs

@ -13,7 +13,6 @@ using Volo.Abp.Autofac;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Identity.EntityFrameworkCore; using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.IdentityServer;
using Volo.Abp.IdentityServer.EntityFrameworkCore; using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.VirtualFileSystem;
@ -48,6 +47,12 @@ namespace MicroserviceDemo.AuthServer
}); });
}); });
services.Configure<IISOptions>(iis =>
{
iis.AuthenticationDisplayName = "Windows";
iis.AutomaticAuthentication = false;
});
if (hostingEnvironment.IsDevelopment()) if (hostingEnvironment.IsDevelopment())
{ {
services.Configure<VirtualFileSystemOptions>(options => services.Configure<VirtualFileSystemOptions>(options =>

46
src/MicroserviceDemo/MicroserviceDemo.Web/MicroservicesDemoWebModule.cs

@ -1,9 +1,16 @@
using System; using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.Swagger;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Account.Web; using Volo.Abp.Account.Web;
@ -21,6 +28,7 @@ using Volo.Abp.MultiTenancy;
using Volo.Abp.MultiTenancy.Web; using Volo.Abp.MultiTenancy.Web;
using Volo.Abp.Permissions; using Volo.Abp.Permissions;
using Volo.Abp.Permissions.EntityFrameworkCore; using Volo.Abp.Permissions.EntityFrameworkCore;
using Volo.Abp.Security.Claims;
namespace MicroserviceDemo.Web namespace MicroserviceDemo.Web
{ {
@ -75,28 +83,41 @@ namespace MicroserviceDemo.Web
}); });
}); });
var xxx = JwtSecurityTokenHandler.DefaultInboundClaimTypeMap;
//JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); //TODO: Try to understand if this is really needed?
services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
options.DefaultScheme = "Cookies"; //options.DefaultScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = "oidc"; //options.DefaultChallengeScheme = "oidc";
}) })
.AddCookie("Cookies") //.AddCookie(IdentityConstants.ApplicationScheme)
.AddOpenIdConnect("oidc", options => .AddOpenIdConnect("oidc", options =>
{ {
options.SignInScheme = "Cookies"; //options.SignInScheme = IdentityConstants.ApplicationScheme;
options.Authority = "http://localhost:54307"; options.Authority = "http://localhost:54307";
options.RequireHttpsMetadata = false; options.RequireHttpsMetadata = false;
options.ClientId = "mvc"; options.ClientId = "client";
options.ClientSecret = "secret"; options.ClientSecret = "secret";
options.ResponseType = "code id_token"; options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
options.SaveTokens = true; options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true; options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("api1"); options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("phone");
options.Scope.Add("multi-tenancy-api");
options.Scope.Add("offline_access"); options.Scope.Add("offline_access");
options.ClaimActions.MapUniqueJsonKey(AbpClaimTypes.UserName, "name");
options.ClaimActions.MapUniqueJsonKey(AbpClaimTypes.Email, "email");
options.SecurityTokenValidator = new MyJwtSecurityTokenHandler();
}); });
services.Configure<RemoteServiceOptions>(configuration); services.Configure<RemoteServiceOptions>(configuration);
@ -153,4 +174,15 @@ namespace MicroserviceDemo.Web
return builder.Build(); return builder.Build();
} }
} }
public class MyJwtSecurityTokenHandler : JwtSecurityTokenHandler
{
protected override ClaimsIdentity CreateClaimsIdentity(JwtSecurityToken jwt, string issuer,
TokenValidationParameters validationParameters)
{
var xxx = base.CreateClaimsIdentity(jwt, issuer, validationParameters);
return xxx;
}
}
} }

13
src/MicroserviceDemo/MicroserviceDemo.Web/Pages/Index.cshtml

@ -1,11 +1,14 @@
@page @page
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Http
@model MicroserviceDemo.Web.Pages.IndexModel @model MicroserviceDemo.Web.Pages.IndexModel
@inject IHttpContextAccessor HttpContextAccessor
<p> <p>
<abp-card> <abp-card>
<abp-card-header></abp-card-header> <abp-card-header></abp-card-header>
<abp-card-body> <abp-card-body>
<a href="~/Account/Login">Login</a> <a href="~/Account/Login">Login</a>
@if (User.Identity.IsAuthenticated) @if (User.Identity.IsAuthenticated)
{ {
foreach (var claim in User.Claims) foreach (var claim in User.Claims)
@ -14,6 +17,14 @@
} }
} }
<hr />
@{
var accessToken = await HttpContextAccessor.HttpContext.GetTokenAsync("access_token");
}
@accessToken <br />
</abp-card-body> </abp-card-body>
</abp-card> </abp-card>
</p> </p>

4
src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/Login.cshtml.cs

@ -133,7 +133,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
} }
await _interaction.GrantConsentAsync(context, ConsentResponse.Denied); await _interaction.GrantConsentAsync(context, ConsentResponse.Denied);
return RedirectSafely(ReturnUrl); return Redirect(ReturnUrl);
} }
ValidateModel(); ValidateModel();
@ -163,7 +163,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
return Redirect("~/"); return Redirect("~/");
} }
return RedirectSafely(ReturnUrl, ReturnUrlHash); return Redirect(ReturnUrl); //ReturnUrlHash?
} }
[UnitOfWork] [UnitOfWork]

36
src/Volo.Abp.Account.Web.IdentityServer/Pages/Account/_ScopeListItem.cshtml

@ -1,30 +1,20 @@
@using Volo.Abp.Account.Web.Pages @using Volo.Abp.Account.Web.Pages
@using Volo.Abp.Account.Web.Pages.Account @using Volo.Abp.Account.Web.Pages.Account
@model Volo.Abp.Account.Web.Pages.ConsentModel.ScopeViewModel @model ConsentModel.ScopeViewModel
@* TODO: Should re-format this, just made copy/paste *@ @* TODO: Should re-format this, just made copy/paste *@
<li class="list-group-item"> <li class="list-group-item">
<label> <div class="form-check">
<input class="consent-scopecheck" <label asp-for="Checked" class="form-check-label">
type="checkbox" <input asp-for="Checked" class="form-check-input" disabled="@Model.Required" />
name="ScopesConsented" @Html.DisplayNameFor(m => m.Checked)
id="scopes_@Model.Name" <input asp-for="Name" type="hidden" />
value="@Model.Name" <strong>@Model.DisplayName</strong>
checked="@Model.Checked" @if (Model.Emphasize)
disabled="@Model.Required" /> {
@if (Model.Required) <span class="glyphicon glyphicon-exclamation-sign"></span>
{ }
<input type="hidden" </label>
name="ScopesConsented" </div>
value="@Model.Name" />
}
<strong>@Model.DisplayName</strong>
@if (Model.Emphasize)
{
<span class="glyphicon glyphicon-exclamation-sign"></span>
}
</label>
@if (Model.Required) @if (Model.Required)
{ {
<span><em>(required)</em></span> <span><em>(required)</em></span>

65
src/Volo.Abp.Account.Web.IdentityServer/Pages/Consent.cshtml

@ -7,48 +7,85 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<h2> <h2>
@if (Model.ClientLogoUrl != null) @if (Model.ClientInfo.ClientLogoUrl != null)
{ {
<img src="@Model.ClientLogoUrl"> <img src="@Model.ClientInfo.ClientLogoUrl">
} }
@Model.ClientName
@Model.ClientInfo.ClientName
<small>is requesting your permission</small> <small>is requesting your permission</small>
</h2> </h2>
</div> </div>
</div> </div>
</abp-card-header> </abp-card-header>
<abp-card-body> <abp-card-body>
<form method="post" asp-page="/Account/Consent"> <form method="post" asp-page="/Consent">
<input type="hidden" asp-for="ReturnUrl" /> <input type="hidden" asp-for="ReturnUrl" />
<input type="hidden" asp-for="ReturnUrlHash" /> <input type="hidden" asp-for="ReturnUrlHash" />
<div>Uncheck the permissions you do not wish to grant.</div> <div>Uncheck the permissions you do not wish to grant.</div>
@if (Model.IdentityScopes.Any()) @if (Model.ConsentInput.IdentityScopes.Any())
{ {
<h3>Personal Information</h3> <h3>Personal Information</h3>
<ul class="list-group"> <ul class="list-group">
@foreach (var scope in Model.IdentityScopes) @for (var i = 0; i < Model.ConsentInput.IdentityScopes.Count; i++)
{ {
@Html.Partial("Account/_ScopeListItem", scope) <li class="list-group-item">
<div class="form-check">
<label asp-for="@Model.ConsentInput.IdentityScopes[i].Checked" class="form-check-label">
<input asp-for="@Model.ConsentInput.IdentityScopes[i].Checked" class="form-check-input" />
@Model.ConsentInput.IdentityScopes[i].DisplayName
@if (Model.ConsentInput.IdentityScopes[i].Required)
{
<span><em>(required)</em></span>
}
</label>
</div>
<input asp-for="@Model.ConsentInput.IdentityScopes[i].Name" type="hidden" /> @* TODO: Use attributes on the view model instead of using hidden here *@
@if (Model.ConsentInput.IdentityScopes[i].Description != null)
{
<div class="consent-description">
@Model.ConsentInput.IdentityScopes[i].Description
</div>
}
</li>
} }
</ul> </ul>
} }
@if (Model.ResourceScopes.Any()) @if (Model.ConsentInput.ApiScopes.Any())
{ {
<h3>Application Access</h3> <h3>Application Access</h3>
<ul class="list-group"> <ul class="list-group">
@foreach (var scope in Model.ResourceScopes) @for (var i = 0; i < Model.ConsentInput.ApiScopes.Count; i++)
{ {
@Html.Partial("Account/_ScopeListItem", scope) <li class="list-group-item">
<div class="form-check">
<label asp-for="@Model.ConsentInput.ApiScopes[i].Checked" class="form-check-label">
<input asp-for="@Model.ConsentInput.ApiScopes[i].Checked" class="form-check-input" disabled="@Model.ConsentInput.ApiScopes[i].Required" />
@Model.ConsentInput.ApiScopes[i].DisplayName
@if (Model.ConsentInput.ApiScopes[i].Required)
{
<span><em>(required)</em></span>
}
</label>
</div>
<input asp-for="@Model.ConsentInput.ApiScopes[i].Name" type="hidden" /> @* TODO: Use attributes on the view model instead of using hidden here *@
@if (Model.ConsentInput.ApiScopes[i].Description != null)
{
<div class="consent-description">
@Model.ConsentInput.ApiScopes[i].Description
</div>
}
</li>
} }
</ul> </ul>
} }
@if (Model.AllowRememberConsent) @if (Model.ClientInfo.AllowRememberConsent)
{ {
<div class="form-check"> <div class="form-check">
<label asp-for="@Model.ConsentInput.RememberConsent" class="form-check-label"> <label asp-for="@Model.ConsentInput.RememberConsent" class="form-check-label">
@ -61,10 +98,10 @@
<div> <div>
<button name="UserDecision" value="yes" class="btn btn-primary" autofocus>Yes, Allow</button> <button name="UserDecision" value="yes" class="btn btn-primary" autofocus>Yes, Allow</button>
<button name="UserDecision" value="no" class="btn">No, Do Not Allow</button> <button name="UserDecision" value="no" class="btn">No, Do Not Allow</button>
@if (Model.ClientUrl != null) @if (Model.ClientInfo.ClientUrl != null)
{ {
<a class="pull-right btn btn-secondary" target="_blank" href="@Model.ClientUrl"> <a class="pull-right btn btn-secondary" target="_blank" href="@Model.ClientInfo.ClientUrl">
<strong>@Model.ClientName</strong> <strong>@Model.ClientInfo.ClientName</strong>
</a> </a>
} }
</div> </div>

114
src/Volo.Abp.Account.Web.IdentityServer/Pages/Consent.cshtml.cs

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using IdentityServer4.Models; using IdentityServer4.Models;
@ -7,6 +8,7 @@ using IdentityServer4.Services;
using IdentityServer4.Stores; using IdentityServer4.Stores;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.RazorPages; using Volo.Abp.AspNetCore.Mvc.RazorPages;
using Volo.Abp.Ui;
namespace Volo.Abp.Account.Web.Pages namespace Volo.Abp.Account.Web.Pages
{ {
@ -22,24 +24,17 @@ namespace Volo.Abp.Account.Web.Pages
public string ReturnUrlHash { get; set; } public string ReturnUrlHash { get; set; }
[BindProperty] [BindProperty]
public ConsentInputModel ConsentInput { get; set; } public ConsentModel.ConsentInputModel ConsentInput { get; set; }
public string ClientName { get; set; } public ClientInfoModel ClientInfo { get; set; }
public string ClientUrl { get; set; }
public string ClientLogoUrl { get; set; }
public bool AllowRememberConsent { get; set; }
public List<ScopeViewModel> IdentityScopes { get; set; }
public List<ScopeViewModel> ResourceScopes { get; set; }
private readonly IIdentityServerInteractionService _interaction; private readonly IIdentityServerInteractionService _interaction;
private readonly IClientStore _clientStore; private readonly IClientStore _clientStore;
private readonly IResourceStore _resourceStore; private readonly IResourceStore _resourceStore;
public ConsentModel( public ConsentModel(
IIdentityServerInteractionService interaction, IIdentityServerInteractionService interaction,
IClientStore clientStore, IClientStore clientStore,
IResourceStore resourceStore) IResourceStore resourceStore)
{ {
_interaction = interaction; _interaction = interaction;
@ -47,7 +42,7 @@ namespace Volo.Abp.Account.Web.Pages
_resourceStore = resourceStore; _resourceStore = resourceStore;
} }
public async Task OnGet() public virtual async Task OnGet()
{ {
var request = await _interaction.GetAuthorizationContextAsync(ReturnUrl); var request = await _interaction.GetAuthorizationContextAsync(ReturnUrl);
if (request == null) if (request == null)
@ -67,27 +62,21 @@ namespace Volo.Abp.Account.Web.Pages
throw new ApplicationException($"No scopes matching: {request.ScopesRequested.Aggregate((x, y) => x + ", " + y)}"); throw new ApplicationException($"No scopes matching: {request.ScopesRequested.Aggregate((x, y) => x + ", " + y)}");
} }
ClientInfo = new ClientInfoModel(client);
ConsentInput = new ConsentInputModel ConsentInput = new ConsentInputModel
{ {
RememberConsent = true, RememberConsent = true,
ScopesConsented = new List<string>() IdentityScopes = resources.IdentityResources.Select(x => CreateScopeViewModel(x, true)).ToList(),
ApiScopes = resources.ApiResources.SelectMany(x => x.Scopes).Select(x => CreateScopeViewModel(x, true)).ToList()
}; };
ClientName = client.ClientId; //TODO: Consider to create a ClientInfoModel
ClientUrl = client.ClientUri;
ClientLogoUrl = client.LogoUri;
AllowRememberConsent = client.AllowRememberConsent;
IdentityScopes = resources.IdentityResources.Select(x => CreateScopeViewModel(x, true)).ToList();
ResourceScopes = resources.ApiResources.SelectMany(x => x.Scopes).Select(x => CreateScopeViewModel(x, true)).ToList();
if (resources.OfflineAccess) if (resources.OfflineAccess)
{ {
ResourceScopes = ResourceScopes.Union(new[] {GetOfflineAccessScope(true)}).ToList(); ConsentInput.ApiScopes.Add(GetOfflineAccessScope(true));
} }
} }
public async Task<IActionResult> OnPost(string userDecision) public virtual async Task<IActionResult> OnPost(string userDecision)
{ {
var result = await ProcessConsentAsync(); var result = await ProcessConsentAsync();
@ -98,17 +87,18 @@ namespace Volo.Abp.Account.Web.Pages
if (result.HasValidationError) if (result.HasValidationError)
{ {
ModelState.AddModelError("", result.ValidationError); //ModelState.AddModelError("", result.ValidationError);
throw new ApplicationException("Error: " + result.ValidationError);
} }
throw new ApplicationException("Error: "); throw new ApplicationException("Unknown Error!");
} }
private async Task<ProcessConsentResult> ProcessConsentAsync() protected virtual async Task<ConsentModel.ProcessConsentResult> ProcessConsentAsync()
{ {
var result = new ProcessConsentResult(); var result = new ConsentModel.ProcessConsentResult();
ConsentResponse grantedConsent = null; ConsentResponse grantedConsent;
if (ConsentInput.UserDecision == "no") if (ConsentInput.UserDecision == "no")
{ {
@ -116,42 +106,39 @@ namespace Volo.Abp.Account.Web.Pages
} }
else else
{ {
if (ConsentInput.ScopesConsented != null && ConsentInput.ScopesConsented.Any()) if (ConsentInput.IdentityScopes.Any() || ConsentInput.ApiScopes.Any())
{ {
var scopes = ConsentInput.ScopesConsented;
grantedConsent = new ConsentResponse grantedConsent = new ConsentResponse
{ {
RememberConsent = ConsentInput.RememberConsent, RememberConsent = ConsentInput.RememberConsent,
ScopesConsented = scopes.ToArray() ScopesConsented = ConsentInput.GetAllowedScopeNames()
}; };
} }
else else
{ {
result.ValidationError = "You must pick at least one permission"; throw new UserFriendlyException("You must pick at least one permission"); //TODO: How to handle this
} }
} }
if (grantedConsent != null) if (grantedConsent != null)
{ {
// validate return url is still valid
var request = await _interaction.GetAuthorizationContextAsync(ReturnUrl); var request = await _interaction.GetAuthorizationContextAsync(ReturnUrl);
if (request == null) return result; if (request == null)
{
return result;
}
// communicate outcome of consent back to identityserver
await _interaction.GrantConsentAsync(request, grantedConsent); await _interaction.GrantConsentAsync(request, grantedConsent);
// indicate that's it ok to redirect back to authorization endpoint
result.RedirectUri = ReturnUrl; //TODO: ReturnUrlHash? result.RedirectUri = ReturnUrl; //TODO: ReturnUrlHash?
} }
return result; return result;
} }
protected virtual ConsentModel.ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check)
private ScopeViewModel CreateScopeViewModel(IdentityResource identity, bool check)
{ {
return new ScopeViewModel return new ConsentModel.ScopeViewModel
{ {
Name = identity.Name, Name = identity.Name,
DisplayName = identity.DisplayName, DisplayName = identity.DisplayName,
@ -162,9 +149,9 @@ namespace Volo.Abp.Account.Web.Pages
}; };
} }
public ScopeViewModel CreateScopeViewModel(Scope scope, bool check) protected virtual ConsentModel.ScopeViewModel CreateScopeViewModel(Scope scope, bool check)
{ {
return new ScopeViewModel return new ConsentModel.ScopeViewModel
{ {
Name = scope.Name, Name = scope.Name,
DisplayName = scope.DisplayName, DisplayName = scope.DisplayName,
@ -175,9 +162,9 @@ namespace Volo.Abp.Account.Web.Pages
}; };
} }
private ScopeViewModel GetOfflineAccessScope(bool check) protected virtual ConsentModel.ScopeViewModel GetOfflineAccessScope(bool check)
{ {
return new ScopeViewModel return new ConsentModel.ScopeViewModel
{ {
Name = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess, Name = IdentityServer4.IdentityServerConstants.StandardScopes.OfflineAccess,
DisplayName = "Offline Access", //TODO: Localize DisplayName = "Offline Access", //TODO: Localize
@ -189,21 +176,36 @@ namespace Volo.Abp.Account.Web.Pages
public class ConsentInputModel public class ConsentInputModel
{ {
public string UserDecision { get; set; } public List<ConsentModel.ScopeViewModel> IdentityScopes { get; set; }
public List<string> ScopesConsented { get; set; } public List<ConsentModel.ScopeViewModel> ApiScopes { get; set; }
[Required]
public string UserDecision { get; set; }
public bool RememberConsent { get; set; } public bool RememberConsent { get; set; }
public List<string> GetAllowedScopeNames()
{
return IdentityScopes.Union(ApiScopes).Where(s => s.Checked).Select(s => s.Name).ToList();
}
} }
public class ScopeViewModel public class ScopeViewModel
{ {
[Required]
[HiddenInput]
public string Name { get; set; } public string Name { get; set; }
public bool Checked { get; set; }
public string DisplayName { get; set; } public string DisplayName { get; set; }
public string Description { get; set; } public string Description { get; set; }
public bool Emphasize { get; set; } public bool Emphasize { get; set; }
public bool Required { get; set; } public bool Required { get; set; }
public bool Checked { get; set; }
} }
public class ProcessConsentResult public class ProcessConsentResult
@ -214,5 +216,25 @@ namespace Volo.Abp.Account.Web.Pages
public bool HasValidationError => ValidationError != null; public bool HasValidationError => ValidationError != null;
public string ValidationError { get; set; } public string ValidationError { get; set; }
} }
public class ClientInfoModel
{
public string ClientName { get; set; }
public string ClientUrl { get; set; }
public string ClientLogoUrl { get; set; }
public bool AllowRememberConsent { get; set; }
public ClientInfoModel(Client client)
{
//TODO: Automap
ClientName = client.ClientId;
ClientUrl = client.ClientUri;
ClientLogoUrl = client.LogoUri;
AllowRememberConsent = client.AllowRememberConsent;
}
}
} }
} }

3
src/Volo.Abp.Account.Web/Pages/Account/Login.cshtml.cs

@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.Security.Claims;
using Volo.Abp.Ui; using Volo.Abp.Ui;
using Volo.Abp.Uow; using Volo.Abp.Uow;
@ -122,7 +123,7 @@ namespace Volo.Abp.Account.Web.Pages.Account
private async Task<IdentityUser> CreateExternalUserAsync(ExternalLoginInfo info) private async Task<IdentityUser> CreateExternalUserAsync(ExternalLoginInfo info)
{ {
var emailAddress = info.Principal.FindFirstValue(ClaimTypes.Email); var emailAddress = info.Principal.FindFirstValue(AbpClaimTypes.Email);
var user = new IdentityUser(GuidGenerator.Create(), emailAddress, CurrentTenant.Id); var user = new IdentityUser(GuidGenerator.Create(), emailAddress, CurrentTenant.Id);

3
src/Volo.Abp.Identity.Domain/Microsoft/Extensions/DependencyInjection/AbpIdentityServiceCollectionExtensions.cs

@ -37,7 +37,8 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddScoped<IdentityRoleStore>(); services.TryAddScoped<IdentityRoleStore>();
services.TryAddScoped(typeof(IRoleStore<IdentityRole>), provider => provider.GetService(typeof(IdentityRoleStore))); services.TryAddScoped(typeof(IRoleStore<IdentityRole>), provider => provider.GetService(typeof(IdentityRoleStore)));
return services.AddIdentity<IdentityUser, IdentityRole>(setupAction); return services.AddIdentity<IdentityUser, IdentityRole>(setupAction)
.AddDefaultTokenProviders();
//return services.AddIdentityCore<IdentityUser>(setupAction); //return services.AddIdentityCore<IdentityUser>(setupAction);
} }
} }

2
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpZeroIdentityServerBuilderExtensions.cs → src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerBuilderExtensions.cs

@ -10,7 +10,7 @@ using Volo.Abp.Security.Claims;
namespace Volo.Abp.IdentityServer namespace Volo.Abp.IdentityServer
{ {
public static class AbpZeroIdentityServerBuilderExtensions public static class AbpIdentityServerBuilderExtensions
{ {
public static IIdentityServerBuilder AddAbpIdentityServer( public static IIdentityServerBuilder AddAbpIdentityServer(
this IIdentityServerBuilder builder, this IIdentityServerBuilder builder,

15
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerDomainModule.cs

@ -2,7 +2,6 @@
using Volo.Abp.AutoMapper; using Volo.Abp.AutoMapper;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Clients; using Volo.Abp.IdentityServer.Clients;
using Volo.Abp.IdentityServer.Temp;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.Security; using Volo.Abp.Security;
@ -22,17 +21,23 @@ namespace Volo.Abp.IdentityServer
options.AddProfile<ClientAutoMapperProfile>(validate: true); options.AddProfile<ClientAutoMapperProfile>(validate: true);
}); });
services.AddAssemblyOf<AbpIdentityServerDomainModule>();
AddIdentityServer(services); AddIdentityServer(services);
services.AddAssemblyOf<AbpIdentityServerDomainModule>();
} }
private static void AddIdentityServer(IServiceCollection services) private static void AddIdentityServer(IServiceCollection services)
{ {
var identityServerBuilder = services.AddIdentityServer(); var identityServerBuilder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
});
identityServerBuilder identityServerBuilder
.AddDeveloperSigningCredential() .AddDeveloperSigningCredential() //TODO: Should be able to change this!
.AddAbpIdentityServer(); .AddAbpIdentityServer();
services.ExecutePreConfiguredActions(identityServerBuilder); services.ExecutePreConfiguredActions(identityServerBuilder);

23
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpProfileService.cs

@ -9,26 +9,37 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity
{ {
//TODO: Implement multi-tenancy as like in old ABP //TODO: Implement multi-tenancy as like in old ABP
public class AbpProfileService : ProfileService<IdentityUser> public class AbpProfileService : ProfileService<IdentityUser>
{ {
private readonly IUnitOfWorkManager _unitOfWorkManager;
public AbpProfileService( public AbpProfileService(
IdentityUserManager userManager, IdentityUserManager userManager,
IUserClaimsPrincipalFactory<IdentityUser> claimsFactory IUserClaimsPrincipalFactory<IdentityUser> claimsFactory,
) : base(userManager, claimsFactory) IUnitOfWorkManager unitOfWorkManager)
: base(userManager, claimsFactory)
{ {
_unitOfWorkManager = unitOfWorkManager;
} }
[UnitOfWork] [UnitOfWork]
public override async Task GetProfileDataAsync(ProfileDataRequestContext context) public override async Task GetProfileDataAsync(ProfileDataRequestContext context)
{ {
await base.GetProfileDataAsync(context); using (var uow = _unitOfWorkManager.Begin())
{
await base.GetProfileDataAsync(context);
await uow.CompleteAsync();
}
} }
[UnitOfWork] [UnitOfWork]
public override async Task IsActiveAsync(IsActiveContext context) public override async Task IsActiveAsync(IsActiveContext context)
{ {
await base.IsActiveAsync(context); using (var uow = _unitOfWorkManager.Begin())
{
await base.IsActiveAsync(context);
await uow.CompleteAsync();
}
} }
} }
} }

5
src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/Clients/ClientAutoMapperProfile.cs

@ -28,6 +28,11 @@ namespace Volo.Abp.IdentityServer.Clients
CreateMap<IdentityResource, IdentityServer4.Models.IdentityResource>(); CreateMap<IdentityResource, IdentityServer4.Models.IdentityResource>();
CreateMap<UserClaim, string>()
.ConstructUsing(src => src.Type)
.ReverseMap()
.ForMember(dest => dest.Type, opt => opt.MapFrom(src => src));
CreateMap<ApiSecret, IdentityServer4.Models.Secret>(); CreateMap<ApiSecret, IdentityServer4.Models.Secret>();
CreateMap<ApiScope, IdentityServer4.Models.Scope>(); CreateMap<ApiScope, IdentityServer4.Models.Scope>();

Loading…
Cancel
Save