当使用AZURE AD进行身份验证时,我们会获得一个成功登录的令牌,我们会将其传递给资源服务器或api控制器。
在我的情况下,我的目录WebApp1,WebApp2,ApiApp1,ApiApp2& 2个用户 - user1&用户2
所有用户都被分配到所有应用程序。
但只有WebApp1才有权使用ApiApp1& ApiApp2,WebApp2仅拥有ApiApp2的许可。
我的问题是applcation的AAD提供商如何验证用户令牌和权限?
当我观察使用fiddler时,我没有看到对权限(AAD)进行任何调用以验证令牌和应用程序权限?
应用程序端的AAD提供程序如何确保它由有效的AAD颁发,并且用户是否拥有该应用程序的权限?
如果它是API应用程序,AAD提供商如何确保颁发令牌的应用程序具有Web应用程序的权限?
答案 0 :(得分:1)
所以这里有多个问题,所以我会尽力回答所有这些问题。
应用程序仅通过验证其数字签名来检查令牌是否使用正确的密钥签名。通常,当应用程序启动时,将有一个调用权限来获取签名公钥。如果你看不到它,或者是因为Fiddler无法看到它,或者因为有问题的库没有验证令牌(!)。对于我使用OWIN OpenId Connect中间件的应用程序,我可以看到对https://login.microsoftonline.com/tenant-id/.well-known/openid-configuration
的呼叫,然后是https://login.microsoftonline.com/common/discovery/keys
,这是签名公钥的位置。
用户对该应用的许可权在他们的声明中。向应用添加委派/应用权限时,始终定义value
。这些值在令牌中发送。应用权限位于名为roles
(IIRC)的声明中,并且委派的权限位于scp
。 Azure AD仅将声明放在那里,以获取给予每个应用/用户的权限。你的应用程序信任AAD做正确的事情(并通过签名验证它确实是AAD)。
实际上,这适用于Web和API应用程序。例如,如果您尝试通过授权代码授予流程登录前端应用程序,则用户将收到一条错误消息,指出他们不允许访问该应用程序。 AAD不会为此用户发回授权代码/ ID令牌。如果你有一个,他们就没事了。
您的WebApp1无法调用ApiApp2,因为AAD不会向其提供访问令牌。
答案 1 :(得分:0)
在我的情况下,我的目录WebApp1,WebApp2,ApiApp1,ApiApp2& 2个用户 - user1& USER2
所有用户都被分配到所有应用程序。
但只有WebApp1才有权使用ApiApp1& ApiApp2,WebApp2仅拥有ApiApp2的许可。
如果是您的情况,您可以按照以下步骤操作:
@juunas的一些补充说明:
我的问题是applcation的AAD提供商如何验证用户令牌和权限?
通常客户端应用程序会验证令牌的加密算法,令牌签名和令牌声明,例如:issuer - 令牌是否来自预期的IdP。观众 - 是我的标志吗? timestamps - 是其有效窗口内的标记。您可以使用JwtSecurityTokenHandler来验证令牌。在Azure AD V1.0端点中,颁发者将为“https://sts.windows.net/Yourtenant/”,而如@juunas所述,它将在验证令牌签名期间查询Azure广告公钥。您可以参考code sample here了解如何在c#中验证JWT令牌。
使用OWIN中间件可以帮助您更轻松地执行此类验证,您可以参考this code sample mvc app使用OpenID Connect登录Azure AD用户并使用OAuth 2.0访问令牌调用web api。在您的方案中,您希望应用程序调用另一个API APP,您可以添加以下代码来获取API的访问令牌:
string resource = "http://testbasic1.onmicrosoft.com/testrole"; //Your API APP
string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID));
ClientCredential credential = new ClientCredential(clientId, appKey);
var result = await authContext.AcquireTokenSilentAsync(resource, credential, new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));