如何在 C# 中使用 ClientAssertionCertificate 从 ADFS(Windows 服务器 2012R2)获取 JWT
How to obtain a JWT from ADFS (Windows server 2012R2) using a ClientAssertionCertificate in C#
我在使用 ClientAssertionCertificate 从 ADFS(Windows 服务器 2012R2)获取 JWT 时遇到问题。
当我让用户使用他的用户名和密码直接进入 adfs 进行身份验证时一切正常 - 登录 window,但我不希望我的应用程序显示 ADFS - 登录 window,因为我的应用程序的用户不会知道凭据。我的应用程序实际上是用户(api)所以我想使用证书进行身份验证。当我尝试这样做时,我收到消息“授权服务器不支持请求的 grant_type
。授权服务器仅支持 authorization_code
或 refresh_token
作为授权类型。
有谁知道使用证书从 ADFS 获取 JWT 的任何解决方法或其他方法?非常感谢!
我的应用程序是 .Net 4.6.1 控制台应用程序。
现在这是我的代码:
var certPath = Path.Combine(GetCurrentDirectoryFromExecutingAssembly(), "mycertificate.pfx");
var certfile = File.OpenRead(certPath);
var certificateBytes = new byte[certfile.Length];
certfile.Read(certificateBytes, 0, (int)certfile.Length);
var cert = new X509Certificate2(
certificateBytes,
"mypassword",
X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
var certificate = new ClientAssertionCertificate("myclientid", cert);
AuthenticationContext context = new AuthenticationContext("https://sts.example.com/adfs",false);
AuthenticationResult authenticationResult = await context.AcquireTokenAsync("http://example.com/api", certificate);
var token = authenticationResult.AccessToken;
您是否尝试过将 WSTrustChannelFactory 与 CertificateWSTrustBinding 一起使用?
在 RequestSecurityToken 中,您可以在 TokenType 中指定您想要 JWT。您收到的 JWT 将是您需要解码的 base64 字符串。
public static async Task<string> GetAccessToken(string authority, string resource, string clientId)
{
var certPath = Path.Combine(GetCurrentDirectoryFromExecutingAssembly(), "mycertificate.pfx");
var certfile = File.OpenRead(certPath);
var certificateBytes = new byte[certfile.Length];
certfile.Read(certificateBytes, 0, (int)certfile.Length);
var cert = new X509Certificate2(
certificateBytes,
"PASSWORD",
X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
var factory = new WSTrustChannelFactory(
new CertificateWSTrustBinding(
SecurityMode.TransportWithMessageCredential),
"https://example.com/adfs/services/trust/13/certificatemixed") {TrustVersion = TrustVersion.WSTrust13};
if (factory.Credentials != null)
factory.Credentials.ClientCertificate.Certificate = cert;
// create token request
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
AppliesTo = new EndpointReference("http://example.com/api"),
KeySizeInBits = 0,
TokenType = "urn:ietf:params:oauth:token-type:jwt"
};
// request token and return
var genericXmlSecurityToken = factory.CreateChannel().Issue(rst) as GenericXmlSecurityToken;
return genericXmlSecurityToken != null
? Encoding.UTF8.GetString(Convert.FromBase64String(genericXmlSecurityToken.TokenXml.InnerXml))
: string.Empty;
}
我在使用 ClientAssertionCertificate 从 ADFS(Windows 服务器 2012R2)获取 JWT 时遇到问题。
当我让用户使用他的用户名和密码直接进入 adfs 进行身份验证时一切正常 - 登录 window,但我不希望我的应用程序显示 ADFS - 登录 window,因为我的应用程序的用户不会知道凭据。我的应用程序实际上是用户(api)所以我想使用证书进行身份验证。当我尝试这样做时,我收到消息“授权服务器不支持请求的 grant_type
。授权服务器仅支持 authorization_code
或 refresh_token
作为授权类型。
有谁知道使用证书从 ADFS 获取 JWT 的任何解决方法或其他方法?非常感谢!
我的应用程序是 .Net 4.6.1 控制台应用程序。
现在这是我的代码:
var certPath = Path.Combine(GetCurrentDirectoryFromExecutingAssembly(), "mycertificate.pfx");
var certfile = File.OpenRead(certPath);
var certificateBytes = new byte[certfile.Length];
certfile.Read(certificateBytes, 0, (int)certfile.Length);
var cert = new X509Certificate2(
certificateBytes,
"mypassword",
X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
var certificate = new ClientAssertionCertificate("myclientid", cert);
AuthenticationContext context = new AuthenticationContext("https://sts.example.com/adfs",false);
AuthenticationResult authenticationResult = await context.AcquireTokenAsync("http://example.com/api", certificate);
var token = authenticationResult.AccessToken;
您是否尝试过将 WSTrustChannelFactory 与 CertificateWSTrustBinding 一起使用? 在 RequestSecurityToken 中,您可以在 TokenType 中指定您想要 JWT。您收到的 JWT 将是您需要解码的 base64 字符串。
public static async Task<string> GetAccessToken(string authority, string resource, string clientId)
{
var certPath = Path.Combine(GetCurrentDirectoryFromExecutingAssembly(), "mycertificate.pfx");
var certfile = File.OpenRead(certPath);
var certificateBytes = new byte[certfile.Length];
certfile.Read(certificateBytes, 0, (int)certfile.Length);
var cert = new X509Certificate2(
certificateBytes,
"PASSWORD",
X509KeyStorageFlags.Exportable |
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet);
var factory = new WSTrustChannelFactory(
new CertificateWSTrustBinding(
SecurityMode.TransportWithMessageCredential),
"https://example.com/adfs/services/trust/13/certificatemixed") {TrustVersion = TrustVersion.WSTrust13};
if (factory.Credentials != null)
factory.Credentials.ClientCertificate.Certificate = cert;
// create token request
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
AppliesTo = new EndpointReference("http://example.com/api"),
KeySizeInBits = 0,
TokenType = "urn:ietf:params:oauth:token-type:jwt"
};
// request token and return
var genericXmlSecurityToken = factory.CreateChannel().Issue(rst) as GenericXmlSecurityToken;
return genericXmlSecurityToken != null
? Encoding.UTF8.GetString(Convert.FromBase64String(genericXmlSecurityToken.TokenXml.InnerXml))
: string.Empty;
}