在每个请求上验证OpenId IdToken

时间:2017-12-05 16:12:50

标签: c# azure azure-active-directory openid openid-connect

我正在尝试验证每次请求时从Azure AD获取的IdToken,但我一直收到错误消息,表示令牌上没有签名。当我验证访问令牌它工作,但我宁愿使用Id令牌,因为它包含用户声明。反正有没有让Azure发回带有签名的Id令牌?

public JwtSecurityToken ValidateJwtToken(string jwtToken)
    {
        string stsDiscoveryEndpoint = $"{_authority}/.well-known/openid-configuration";

       ConfigurationManager<OpenIdConnectConfiguration> configManager =
            new ConfigurationManager<OpenIdConnectConfiguration>(stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());

       OpenIdConnectConfiguration config = configManager.GetConfigurationAsync().Result;

       TokenValidationParameters validationParameters = new TokenValidationParameters
        {
            ValidateAudience = false,
            ValidateIssuer = false,
            ValidateLifetime = false,
            IssuerSigningKeys = config.SigningKeys
        };

       JwtSecurityTokenHandler tokendHandler = new JwtSecurityTokenHandler();

       try
        {
            SecurityToken token;
            tokendHandler.ValidateToken(jwtToken, validationParameters, out token);

           return token as JwtSecurityToken;
        }
        catch (Exception ex)
        {
            loggingService.LogError("Could not validate azure ad token", nameof(AzureSecurityService), ex);
            return null;
        }
    }

   public async Task<string> GenerateToken(string code)
    {
        AuthenticationContext authenticationContext = new AuthenticationContext(_authority);

       try
        {
            string baseUrl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
            AuthenticationResult result =
                await authenticationContext.AcquireTokenByAuthorizationCodeAsync(code, new Uri(baseUrl), new ClientCredential(_clientId, _clientSecret));

           return result.IdToken;
        }
        catch (AdalException adalex)
        {
            loggingService.LogError("Could not get authorization request url", nameof(AzureSecurityService), adalex);
            return null;
        }
        catch (Exception ex)
        {
            loggingService.LogError("Could not get authorization request url", nameof(AzureSecurityService), ex);
            return null;
        }
    }

   public async Task<string> GetAuthUrl()
    {
        AuthenticationContext authenticationContext = new AuthenticationContext(_authority);

       // Config for OAuth client credentials  
       try
        {
            string baseUrl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
            var authUri =
                await authenticationContext.GetAuthorizationRequestUrlAsync("00000000-0000-0000-0000-000000000000", _clientId, new Uri(baseUrl), UserIdentifier.AnyUser, null);

           return authUri.ToString();
        }
        catch (AdalException adalex)
        {
            loggingService.LogError("Could not get authorization request url", nameof(AzureSecurityService), adalex);
            return null;
        }
        catch (Exception ex)
        {
            loggingService.LogError("Could not get authorization request url", nameof(AzureSecurityService), ex);
            return null;
        }
    }

更新

所以无论出于什么原因,即使没有提供范围,我也会收到索赔。我现在所做的只是将查询参数添加到范围的auth url并请求openid和profile:

var authUri =
                await authenticationContext.GetAuthorizationRequestUrlAsync("00000000-0000-0000-0000-000000000000", _clientId, new Uri(GetBaseUrl()), UserIdentifier.AnyUser, "scope=openid profile");

我的问题是,为什么默认范围不会返回带签名的id_token?

1 个答案:

答案 0 :(得分:1)

您应该忘记在授权请求中输入所需的范围值,

来自OpenID Connect specification

  

<强>范围

     

必需的。 OpenID Connect请求必须包含openid范围值。   如果openid范围值不存在,则完全是行为   不确定的。可能存在其他范围值。使用的范围值   不被实现理解应该被忽略。看到   第5.4和11节,了解由此定义的其他范围值   说明书

因此,您必须在授权请求中指定 openid

Azure确实为OAuth 2.0令牌响应返回了一个id令牌(当openid作用域不存在时)。

来自Azure AD OAuth2.0 documentation

  

id_token

     

未签名的JSON Web令牌(JWT)。该应用程序可以base64Url解码   此令牌的片段用于请求有关用户的信息   登录。该应用程序可以缓存值并显示它们,但它   不应该依赖它们来获得任何授权或安全边界。

正如文档所说,它只是显示最终用户。不得使用此id标记进行身份验证/授权。

另一方面,对于正确的OpenID Connect令牌响应,Auzre会向您发送签名的ID令牌,

来自documentation

  

<强> id_token

     

应用请求的id_token。你可以使用id_token来   验证用户的身份并开始与用户进行会话。

验证相同文档的id_token部分解释了如何验证令牌

希望这能解决你的问题。