如果基于客户端凭据

时间:2016-10-10 15:52:08

标签: asp.net asp.net-mvc azure asp.net-web-api azure-active-directory

在通过Web应用程序和API获得Azure AD之前 -

用户在应用表单上输入ID和密码 - >用户登录(Asp.net身份) - >使用相同的凭证,在WebAPI获取令牌(grant_type =密码) - >将此标记存储为cookie,以便稍后使用。

现在使用Azure AD -

我有一个场景,我必须使用Azure AD对用户进行身份验证。 Azure上的webapi传递包含登录用户信息的JWT。根据这些信息,我提取用户电子邮件并强制我的Web应用程序登录用户(Asp.net身份)。

Web App调用WebAPI获取令牌,因为我无法传递密码,因此我的令牌调用更改为(grant_type = client_credentials)。但是,我忘记了登录Web API的个人用户的信息。如果我检查context.user它指向唯一的客户端ID而不是任何用户。

我知道它很混乱,但要求是使用相同的应用程序进行Azure AD身份验证以及内部部署表单身份验证。请建议是否有更简单的方法来实现这一目标。

修改:我正在使用Owin oAuth

我使用相同的应用程序进行表单身份验证和Azure AD。但是最近不得不在web api级别添加日志记录机制,该机制适用于使用用户ID /密码记录的本地应用程序。但是,如果webapi使用客户端凭据发出令牌,它就不起作用。我试图在验证客户端ID(在ValidateClientAuthentication中)并登录用户时将username作为参数传递。但是webapi无法保留此用户信息。

2 个答案:

答案 0 :(得分:0)

客户端凭据流用于守护程序应用程序或服务,以委派应用程序来操作资源。在这种情况下,没有用户上下文信息。

根据我的理解,当我们使用Azure AD作为身份提供者时,我们使用OpenId连接协议来获取Azure AD的id_token表单。 OpenId connect还支持混合流程,以在同一请求中获取授权代码 id_token

如果使用带有OWIN组件的MVC进行开发,则默认情况下此流程。我们只需要使用Azure AD返回的授权代码(OAuth 2.0代码授予流)获取访问令牌,以调用Web API,这不需要用户再次登录。要获得具有授权码的令牌,我们可以添加下面的代码通知:

public void ConfigureAuth(IAppBuilder app)
{
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = Authority,
                PostLogoutRedirectUri = redirectUri,
                RedirectUri = redirectUri,
                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    //
                    // If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
                    //
                    AuthorizationCodeReceived = OnAuthorizationCodeReceived,
                    AuthenticationFailed = OnAuthenticationFailed
                }

            });
}

private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
        var code = context.Code;

        ClientCredential credential = new ClientCredential(clientId, appKey);
        string userObjectID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
        AuthenticationContext authContext = new AuthenticationContext(Authority, new NaiveSessionCache(userObjectID));

        // If you create the redirectUri this way, it will contain a trailing slash.  
        // Make sure you've registered the same exact Uri in the Azure Portal (including the slash).
        Uri uri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));

        AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(code, uri, credential, graphResourceId);
}

要从网络应用调用网络API的完整代码示例,您可以参考here

答案 1 :(得分:0)

这是我为修复问题所做的工作 - 而不是为客户端分配claimIdentity我生成了用户身份。 (_username是局部变量,它在" ValidateClientAuthentication"中从参数中获得赋值。我知道这可能不是理想的方法,但现在我的应用程序现在可以使用表单身份验证以及使用JWT令牌的Azure AD) / p>

 public override async Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
        {
            var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();

            ApplicationUser user = await userManager.FindByNameAsync(_userName);

            ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, CookieAuthenticationDefaults.AuthenticationType);

            var ticket = new AuthenticationTicket(oAuthIdentity, null);

            context.Validated(ticket);
        }