Thinktecture Identity Server v3 如何防止来自外部提供商的声明?
Thinktecture Identity Server v3 How to keep Claims from external providers?
我正在尝试遵循简单指南 mvcGettingStarted。
现在,我已经实现了 GoogleAuthentication
和 FacebookAuthentication
提供程序,并且一切都按预期工作,我实际上可以登录,如果我使用我的身份服务器登录,我也得到了 Role claims per用户。
我想知道,如果我想保留外部提供者提供的所有声明怎么办?
简单的例子。
这是我的 Facebook 提供商设置的样子:
var facebookOptions = new FacebookAuthenticationOptions() {
AuthenticationType = "Facebook",
Caption = "Sign in with Facebook",
AppId = "*****",
AppSecret = "****",
SignInAsAuthenticationType = signInAsType,
Provider = new FacebookAuthenticationProvider() {
OnAuthenticated = (context) => {
foreach (var x in context.User) {
context.Identity.AddClaim(new Claim(x.Key, x.Value.ToString()));
}
return Task.FromResult(context);
}
},
};
facebookOptions.Scope.Add("email");
facebookOptions.Scope.Add("public_profile");
facebookOptions.Scope.Add("user_friends");
app.UseFacebookAuthentication(facebookOptions);
在 for each 循环中,我试图将所有 Facebook 声明存储在身份中,但是当我返回 SecurityTokenValidated
回调时,我的身份没有它们。
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions() {
Authority = "https://localhost:44302/identity/",
ClientId = "my_client",
Scope = "openid profile roles email",
RedirectUri = "https://localhost:44302/",
ResponseType = "id_token token",
SignInAsAuthenticationType = "Cookies",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications() {
SecurityTokenValidated = async context => {
//let's clean up this identity
//context.AuthenticationTicket.Identity doesn't have the claims added in the facebook callback
var nid = new ClaimsIdentity(
context.AuthenticationTicket.Identity.AuthenticationType,
Constants.ClaimTypes.GivenName,
Constants.ClaimTypes.Role);
........
是因为我在操纵两个不同的身份吗?
有没有正确的方法来实现我想要做的事情?
谢谢你。
您可以在自定义用户服务实施中执行此操作。默认值使来自外部提供者的声明可用。关于自定义用户服务的文档:https://identityserver.github.io/Documentation/docsv2/advanced/userService.html
正如@brock-allen 所说,用户服务是正确的方向。
所以我继续实现了一个简单的 UserService
public class UserService {
private static InMemoryUserService _service = null;
public static InMemoryUserService Get() {
if(_service == null)
_service = new InMemoryUserService(Users.Get());
return _service;
}
}
像这样在我的工厂注册了我的用户服务
public void Configuration(IAppBuilder app) {
AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
var factory = InMemoryFactory.Create(
users: Users.Get(),
clients: Clients.Get(),
scopes: Scopes.Get());
factory.UserService = new Registration<IUserService>(resolver => UserService.Get());
.....
(当然是我Startup里的Configuration方法class)
所以现在我可以在外部提供者(在本例中是 facebook)的身份验证回调中对外部用户进行身份验证,指定我需要的所有声明:
var facebookOptions = new FacebookAuthenticationOptions() {
AuthenticationType = "Facebook",
Caption = "Sign in with Facebook",
AppId = "******",
AppSecret = "*******",
SignInAsAuthenticationType = signInAsType,
Provider = new FacebookAuthenticationProvider() {
OnAuthenticated = (context) => {
foreach (var x in context.User) {
context.Identity.AddClaim(new Claim(x.Key, x.Value.ToString()));
}
ExternalIdentity identity = new ExternalIdentity() {
Claims = context.Identity.Claims,
Provider = "Facebook",
ProviderId = "Facebook"
};
SignInMessage signInMessage = new SignInMessage();
UserService.Get().AuthenticateExternalAsync(identity, signInMessage);
return Task.FromResult(context);
}
},
}
现在,我可以做到
List<Claim> claims = await UserService.Get().GetProfileDataAsync(User as ClaimsPrincipal) as List<Claim>;
并看到我的用户拥有在身份验证期间提供的所有 Facebook 声明。
当然这段代码只是为了测试,还可以改进很多。
我正在尝试遵循简单指南 mvcGettingStarted。
现在,我已经实现了 GoogleAuthentication
和 FacebookAuthentication
提供程序,并且一切都按预期工作,我实际上可以登录,如果我使用我的身份服务器登录,我也得到了 Role claims per用户。
我想知道,如果我想保留外部提供者提供的所有声明怎么办?
简单的例子。
这是我的 Facebook 提供商设置的样子:
var facebookOptions = new FacebookAuthenticationOptions() {
AuthenticationType = "Facebook",
Caption = "Sign in with Facebook",
AppId = "*****",
AppSecret = "****",
SignInAsAuthenticationType = signInAsType,
Provider = new FacebookAuthenticationProvider() {
OnAuthenticated = (context) => {
foreach (var x in context.User) {
context.Identity.AddClaim(new Claim(x.Key, x.Value.ToString()));
}
return Task.FromResult(context);
}
},
};
facebookOptions.Scope.Add("email");
facebookOptions.Scope.Add("public_profile");
facebookOptions.Scope.Add("user_friends");
app.UseFacebookAuthentication(facebookOptions);
在 for each 循环中,我试图将所有 Facebook 声明存储在身份中,但是当我返回 SecurityTokenValidated
回调时,我的身份没有它们。
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions() {
Authority = "https://localhost:44302/identity/",
ClientId = "my_client",
Scope = "openid profile roles email",
RedirectUri = "https://localhost:44302/",
ResponseType = "id_token token",
SignInAsAuthenticationType = "Cookies",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications() {
SecurityTokenValidated = async context => {
//let's clean up this identity
//context.AuthenticationTicket.Identity doesn't have the claims added in the facebook callback
var nid = new ClaimsIdentity(
context.AuthenticationTicket.Identity.AuthenticationType,
Constants.ClaimTypes.GivenName,
Constants.ClaimTypes.Role);
........
是因为我在操纵两个不同的身份吗? 有没有正确的方法来实现我想要做的事情? 谢谢你。
您可以在自定义用户服务实施中执行此操作。默认值使来自外部提供者的声明可用。关于自定义用户服务的文档:https://identityserver.github.io/Documentation/docsv2/advanced/userService.html
正如@brock-allen 所说,用户服务是正确的方向。 所以我继续实现了一个简单的 UserService
public class UserService {
private static InMemoryUserService _service = null;
public static InMemoryUserService Get() {
if(_service == null)
_service = new InMemoryUserService(Users.Get());
return _service;
}
}
像这样在我的工厂注册了我的用户服务
public void Configuration(IAppBuilder app) {
AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
var factory = InMemoryFactory.Create(
users: Users.Get(),
clients: Clients.Get(),
scopes: Scopes.Get());
factory.UserService = new Registration<IUserService>(resolver => UserService.Get());
.....
(当然是我Startup里的Configuration方法class)
所以现在我可以在外部提供者(在本例中是 facebook)的身份验证回调中对外部用户进行身份验证,指定我需要的所有声明:
var facebookOptions = new FacebookAuthenticationOptions() {
AuthenticationType = "Facebook",
Caption = "Sign in with Facebook",
AppId = "******",
AppSecret = "*******",
SignInAsAuthenticationType = signInAsType,
Provider = new FacebookAuthenticationProvider() {
OnAuthenticated = (context) => {
foreach (var x in context.User) {
context.Identity.AddClaim(new Claim(x.Key, x.Value.ToString()));
}
ExternalIdentity identity = new ExternalIdentity() {
Claims = context.Identity.Claims,
Provider = "Facebook",
ProviderId = "Facebook"
};
SignInMessage signInMessage = new SignInMessage();
UserService.Get().AuthenticateExternalAsync(identity, signInMessage);
return Task.FromResult(context);
}
},
}
现在,我可以做到
List<Claim> claims = await UserService.Get().GetProfileDataAsync(User as ClaimsPrincipal) as List<Claim>;
并看到我的用户拥有在身份验证期间提供的所有 Facebook 声明。 当然这段代码只是为了测试,还可以改进很多。