我正在尝试实施ADFS4 - 用于身份验证的OAuth(OpenID连接)和用于webapi通信的webapp。
我已相应地配置了ADFS应用程序组,并在webapp中使用OpenIdconnectauth管道进行身份验证。为了调用webapi,如果我仅使用客户端凭证授权请求accessstoken,它可以正常工作,因为我收到了有效的访问令牌并且能够访问api。但是,访问令牌中没有任何用户详细信息,我需要从webapi端获取它。
所以,然后我尝试从bootstrapcontext.token创建UserAssertion对象。但是这一次,当我请求访问令牌时,我收到了标题中提到的错误。
以下是代码段:
AuthenticationContext authContext = null;
AuthenticationResult result = null;
authContext = new AuthenticationContext(Startup.authority, false);
ClientCredential credential = new ClientCredential(Startup.clientId, Startup.appKey);
string usercheck = User.Identity.Name; //For checking, returns username
var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;
string username = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
string userAccessToken = bootstrapContext.Token;
UserAssertion userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", username);
string accessToken = null;
HttpClient httpClient = new HttpClient();
try {
//result = authContext.AcquireTokenAsync(Startup.apiResourceId, credential).Result; // This works fine but no user details in the token
result = authContext.AcquireTokenAsync(Startup.apiResourceId, credential, userAssertion).Result;
}
以下是webapp和webapi中Startup.ConfigureAuth(IAppBuilder应用程序)的外观:
在webapp中:
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
AuthenticationType = OpenIdConnectAuthenticationDefaults.AuthenticationType,
MetadataAddress = metadataAddress,
PostLogoutRedirectUri = postLogoutRedirectUri,
RedirectUri = postLogoutRedirectUri,
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters()
{
SaveSigninToken = true
},
ResponseType = "code id_token",
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
context.Response.Redirect("/Error?message=" + context.Exception.Message);
return Task.FromResult(0);
}
}
});
}
在webapi中:
public void ConfigureAuth(IAppBuilder app)
{
JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
MetadataEndpoint = ConfigurationManager.AppSettings["ida:AdfsMetadataEndpoint"],
TokenValidationParameters = new TokenValidationParameters() {
SaveSigninToken = true,
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
}
});
}
我认为我传入userassertion的令牌不正确。但我该如何解决这个问题呢?有没有其他方法可以将用户详细信息输入访问令牌。如果有人能帮助我们解决这个问题,我真的很感激吗?
感谢。
答案 0 :(得分:1)
您必须使用授权代码流来使MVC应用程序与API通信。 Vittorio has a nice post on it here, although it talks about azure.
为了做到这一点,您需要通过Startup.ConfigureAuth(IAppBuilder应用程序)中的OpenIdConnectAuthenticationOptions上的通知来处理AuthorizationCodeReceived事件
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions {
...
Notifications = new OpenIdConnectAuthenticationNotifications {
AuthorizationCodeReceived = async code => {
ClientCredential credential = new ClientCredential(Startup.clientId, Startup.appKey);
AuthenticationContext authContext = new AuthenticationContext(Startup.authority, false);
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
code.Code,
new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
credential,
Startup.apiResourceId);
}
}
当您准备好拨打电话时,您将默默获取您的令牌。
var authContext = new AuthenticationContext(Startup.authority, false);
var credential = new ClientCredential(Startup.clientId, Startup.appKey);
var claim = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
var userId = new UserIdentifier(claim, UserIdentifierType.UniqueId);
result = await authContext.AcquireTokenSilentAsync(
Startup.apiResourceId,
credential,
userId);
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer",
result.AccessToken);