MSIS9649:收到无效的OAuth请求。 'assertion'参数值不是有效的访问令牌

时间:2017-05-09 10:31:56

标签: oauth openid adfs

我正在尝试实施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的令牌不正确。但我该如何解决这个问题呢?有没有其他方法可以将用户详细信息输入访问令牌。如果有人能帮助我们解决这个问题,我真的很感激吗?

感谢。

1 个答案:

答案 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);