C# 如何使用asp.net core 2.2授予外部验证且未在my WebApp中注册的用户访问权限?
摘要 这是我第一次尝试OAuth2和外部登录机制 我正在创建一个WebApp,它将通过一个用户友好的UI公开API特性 为了进行API调用,我需要从QBO接收一个访问令牌,该令牌授予对资源的访问权 所以,我的WebApp有一个外部登录选项,我用它来对QBO进行身份验证,然后授权我的应用 一切正常,直到 服务配置 基于GitHub身份验证教程,我提出了这个C# 如何使用asp.net core 2.2授予外部验证且未在my WebApp中注册的用户访问权限?,c#,asp.net-core,identity,claims-based-identity,asp.net-core-2.2,C#,Asp.net Core,Identity,Claims Based Identity,Asp.net Core 2.2,摘要 这是我第一次尝试OAuth2和外部登录机制 我正在创建一个WebApp,它将通过一个用户友好的UI公开API特性 为了进行API调用,我需要从QBO接收一个访问令牌,该令牌授予对资源的访问权 所以,我的WebApp有一个外部登录选项,我用它来对QBO进行身份验证,然后授权我的应用 一切正常,直到 服务配置 基于GitHub身份验证教程,我提出了这个 services.AddAuthentication(o => { o.DefaultAuth
services.AddAuthentication(o => {
o.DefaultAuthenticateScheme = IdentityConstants.ExternalScheme;
o.DefaultSignInScheme = IdentityConstants.ExternalScheme;
o.DefaultChallengeScheme = IdentityConstants.ExternalScheme;
})
.AddOAuth("qbo", "qbo", o => {
o.CallbackPath = new PathString("/signin-qbo");
o.ClientId = Configuration["ecm.qbo.client-id"];
o.ClientSecret = Configuration["ecm.qbo.client-secret"];
o.SaveTokens = true;
o.Scope.Add("openid");
o.Scope.Add("profile");
o.Scope.Add("email");
o.Scope.Add("com.intuit.quickbooks.accounting");
o.AuthorizationEndpoint = Configuration["ecm.qbo.authorization-endpoint"];
o.TokenEndpoint = Configuration["ecm.qbo.token-endpoint"];
o.UserInformationEndpoint = Configuration["ecm.qbo.user-info-endpoint"];
o.Events.OnCreatingTicket = async context => {
var companyId = context.Request.Query["realmid"].FirstOrDefault() ?? throw new ArgumentNullException("realmId");
var accessToken = context.AccessToken;
var refreshToken = context.RefreshToken;
Configuration["ecm.qbo.access-token"] = accessToken;
Configuration["ecm.qbo.refresh-token"] = refreshToken;
Configuration["ecm.qbo.realm-id"] = companyId;
context.Backchannel.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
context.Backchannel.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await context.Backchannel.GetStringAsync(context.Options.UserInformationEndpoint);
var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
var user = (ClaimsIdentity)context.Principal.Identity;
user.AddClaims(new Claim[] {
new Claim("access_token", accessToken),
new Claim("refresh_token", refreshToken),
new Claim(ClaimTypes.GivenName, result["givenName"]),
new Claim(ClaimTypes.Surname, result["familyName"]),
new Claim(ClaimTypes.Email, result["email"]),
new Claim(ClaimTypes.Name, result["givenName"]+" "+result["familyName"])
});
};
});
services.AddAuthentication(o=>{
o、 DefaultAuthenticateScheme=IdentityConstants.ExternalScheme;
o、 DefaultSignInScheme=IdentityConstants.ExternalScheme;
o、 DefaultChallengeScheme=IdentityConstants.ExternalScheme;
})
.AddOAuth(“qbo”,“qbo”,o=>{
o、 回调路径=新路径字符串(“/signin qbo”);
o、 ClientId=配置[“ecm.qbo.client id”];
o、 ClientSecret=Configuration[“ecm.qbo.client secret”];
o、 SaveTokens=true;
o、 范围。添加(“openid”);
o、 范围。添加(“简介”);
o、 范围。添加(“电子邮件”);
o、 Scope.Add(“com.intuit.quickbooks.accounting”);
o、 AuthorizationEndpoint=配置[“ecm.qbo.authorization endpoint”];
o、 TokenEndpoint=配置[“ecm.qbo.TokenEndpoint”];
o、 UserInformationEndpoint=配置[“ecm.qbo.user info endpoint”];
o、 Events.OnCreatingTicket=异步上下文=>{
var companyId=context.Request.Query[“realmid”].FirstOrDefault()??抛出新的ArgumentNullException(“realmid”);
var accessToken=context.accessToken;
var refreshttoken=context.refreshttoken;
配置[“ecm.qbo.access token”]=accessToken;
配置[“ecm.qbo.refreshToken”]=refreshToken;
配置[“ecm.qbo.realm id”]=公司id;
context.Backchannel.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“承载者”,context.AccessToken);
context.Backchannel.DefaultRequestHeaders.Accept.Add(新的MediaTypeWithQualityHeaderValue(“应用程序/json”);
var response=wait context.Backchannel.GetStringAsync(context.Options.UserInformationEndpoint);
var result=JsonConvert.DeserializeObject(响应);
var user=(ClaimsIdentity)context.Principal.Identity;
user.AddClaims(新索赔[]{
新声明(“访问令牌”,accessToken),
新索赔(“刷新令牌”,刷新令牌),
新索赔(ClaimTypes.GivenName,结果[“GivenName]”),
新索赔(索赔类型.姓氏,结果[“familyName”]),
新索赔(ClaimTypes.Email,结果[“Email”]),
新索赔(ClaimTypes.Name,结果[“givenName”]+“”+结果[“familyName”])
});
};
});
这很有效。我可以根据用户信息添加声明,context.Principal.Identity表示它已通过身份验证
出于某些原因,它似乎试图重定向到`/Identity/Account/Login?returnUrl=%2F。为什么呢
登录页面重定向
在这里,我不明白为什么我得到重定向,这让我很困惑。因此,我添加AccountController只是为了尝试关闭它
namespace ecm.backoffice.Controllers {
[Authorize]
[Route("[controller]/[action]")]
public class AccountController : Controller {
[AllowAnonymous]
[HttpGet]
public IActionResult Login(string returnUrl = "/") {
return Challenge(new AuthenticationProperties { RedirectUri = returnUrl });
}
[Authorize]
[HttpGet]
public async Task<IActionResult> Logout(string returnUrl = "/") {
await Request.HttpContext.SignOutAsync("qbo");
return Redirect(returnUrl);
}
}
}
名称空间ecm.backoffice.Controllers{
[授权]
[路由(“[控制器]/[操作]”)]
公共类AccountController:控制器{
[异名]
[HttpGet]
public IActionResult登录(字符串returnUrl=“/”){
返回质询(新的AuthenticationProperties{RedirectUri=returnUrl});
}
[授权]
[HttpGet]
公共异步任务注销(字符串returnUrl=“/”){
wait Request.HttpContext.SignOutAsync(“qbo”);
返回重定向(returnUrl);
}
}
}
事实上,这造成了比解决问题更多的困惑。我在这里迷路了
应用迁移
这个个人用户身份验证WebApp似乎使用了Identity,这似乎创建了很多幕后机制。我首先尝试注册到我的应用程序,并且不得不“应用迁移”,我完全理解了这一点,因为数据模型没有初始化
因此,我单击了应用迁移按钮。我以为我可以接受这个
实体框架核心
我知道该应用程序正在使用Entity Framework Core作为其持久性机制,因此需要注册过程等。要对其进行配置,我需要将这些行添加到服务配置中
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddDbContext
还有更多