다음을 통해 공유


Microsoft ID 플랫폼의 액세스 토큰

액세스 토큰은 인증된 사용자를 대신하여 특정 리소스에 대한 액세스 권한을 부여하는 권한 부여를 위해 설계된 보안 토큰의 유형입니다. 액세스 토큰의 정보는 사용자가 건물의 특정 문을 잠금 해제하는 키와 유사하게 특정 리소스에 액세스할 수 있는 권한이 있는지 여부를 결정합니다. 토큰을 구성하는 이러한 개별 정보를 클레임이라고 합니다. 따라서 이러한 자격 증명은 중요한 자격 증명이며 올바르게 처리되지 않으면 보안 위험을 초래합니다. 액세스 토큰은 인증 증명 역할을 하는 ID 토큰과 다릅니다.

액세스 토큰을 사용하면 보호되는 웹 API를 클라이언트가 안전하게 호출할 수 있습니다. 클라이언트 애플리케이션은 액세스 토큰을 수신하고 사용할 수 있지만 불투명 문자열로 처리해야 합니다. 클라이언트 애플리케이션은 액세스 토큰의 유효성을 검사하려고 시도해서는 안 됩니다. 리소스 서버는 권한 부여 증명으로 수락하기 전에 액세스 토큰의 유효성을 검사해야 합니다. 토큰의 내용은 API만을 위한 것입니다. 즉, 액세스 토큰은 불투명 문자열로 처리되어야 합니다. 개발자는 오직 유효성 검사 및 디버깅 목적으로만 jwt.ms와 같은 사이트를 사용하여 JWT를 디코딩할 수 있습니다. Microsoft API가 수신하는 토큰이 항상 디코딩할 수 있는 JWT인 것은 아닙니다.

클라이언트는 내부 항목에 대한 세부 정보를 위해 액세스 토큰과 함께 반환되는 토큰 응답 데이터를 사용해야 합니다. 클라이언트가 액세스 토큰을 요청하는 경우 Microsoft ID 플랫폼은 애플리케이션 사용을 위해 액세스 토큰에 대한 일부 메타데이터도 반환합니다. 이 정보에는 액세스 토큰의 만료 시간 및 유효 범위가 포함되어 있습니다. 이 데이터를 통해 애플리케이션은 액세스 토큰 자체를 구문 분석하지 않고도 액세스 토큰의 인텔리전트 캐싱을 수행할 수 있습니다. 이 문서에서는 형식, 소유권, 수명 및 API가 액세스 토큰 내에서 클레임의 유효성을 검사하고 사용하는 방법을 포함하여 액세스 토큰에 대한 필수 정보를 설명합니다.

참고 항목

이 페이지의 모든 문서는 명시된 경우를 제외하고 등록된 API에 대해 발행된 토큰에만 적용됩니다. Microsoft 소유의 API에 대해 발급된 토큰에는 적용되지 않으며, 이러한 토큰은 Microsoft ID 플랫폼이 등록된 API에 대한 토큰을 발급하는 방법의 유효성을 검사하는 데 사용될 수 없습니다.

토큰 형식

Microsoft ID 플랫폼에서 사용할 수 있는 액세스 토큰에는 v1.0 및 v2.0의 두 가지 버전이 있습니다. 이러한 버전은 토큰에 있는 클레임을 결정하고 웹 API가 토큰의 콘텐츠를 제어할 수 있는지 확인합니다.

등록하는 동안 웹 API에는 다음 버전 중 하나가 기본값으로 선택됩니다.

  • Microsoft Entra 전용 애플리케이션용 v1.0. 다음 예제에서는 v1.0 토큰을 보여 줍니다(키가 변경되고 개인 정보가 제거되어 토큰 유효성 검사를 방지함).

    eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSIsImtpZCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSJ9.eyJhdWQiOiJlZjFkYTlkNC1mZjc3LTRjM2UtYTAwNS04NDBjM2Y4MzA3NDUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mYTE1ZDY5Mi1lOWM3LTQ0NjAtYTc0My0yOWYyOTUyMjIyOS8iLCJpYXQiOjE1MzcyMzMxMDYsIm5iZiI6MTUzNzIzMzEwNiwiZXhwIjoxNTM3MjM3MDA2LCJhY3IiOiIxIiwiYWlvIjoiQVhRQWkvOElBQUFBRm0rRS9RVEcrZ0ZuVnhMaldkdzhLKzYxQUdyU091TU1GNmViYU1qN1hPM0libUQzZkdtck95RCtOdlp5R24yVmFUL2tES1h3NE1JaHJnR1ZxNkJuOHdMWG9UMUxrSVorRnpRVmtKUFBMUU9WNEtjWHFTbENWUERTL0RpQ0RnRTIyMlRJbU12V05hRU1hVU9Uc0lHdlRRPT0iLCJhbXIiOlsid2lhIl0sImFwcGlkIjoiNzVkYmU3N2YtMTBhMy00ZTU5LTg1ZmQtOGMxMjc1NDRmMTdjIiwiYXBwaWRhY3IiOiIwIiwiZW1haWwiOiJBYmVMaUBtaWNyb3NvZnQuY29tIiwiZmFtaWx5X25hbWUiOiJMaW5jb2xuIiwiZ2l2ZW5fbmFtZSI6IkFiZSAoTVNGVCkiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMjIyNDcvIiwiaXBhZGRyIjoiMjIyLjIyMi4yMjIuMjIiLCJuYW1lIjoiYWJlbGkiLCJvaWQiOiIwMjIyM2I2Yi1hYTFkLTQyZDQtOWVjMC0xYjJiYjkxOTQ0MzgiLCJyaCI6IkkiLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJzdWIiOiJsM19yb0lTUVUyMjJiVUxTOXlpMmswWHBxcE9pTXo1SDNaQUNvMUdlWEEiLCJ0aWQiOiJmYTE1ZDY5Mi1lOWM3LTQ0NjAtYTc0My0yOWYyOTU2ZmQ0MjkiLCJ1bmlxdWVfbmFtZSI6ImFiZWxpQG1pY3Jvc29mdC5jb20iLCJ1dGkiOiJGVnNHeFlYSTMwLVR1aWt1dVVvRkFBIiwidmVyIjoiMS4wIn0.D3H6pMUtQnoJAGq6AHd
    
  • 소비자 계정을 지원하는 애플리케이션의 경우 v2.0. 다음 예제에서는 v2.0 토큰을 보여 줍니다(키가 변경되고 개인 정보가 제거되어 토큰 유효성 검사를 방지함).

    eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSJ9.eyJhdWQiOiI2ZTc0MTcyYi1iZTU2LTQ4NDMtOWZmNC1lNjZhMzliYjEyZTMiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3YyLjAiLCJpYXQiOjE1MzcyMzEwNDgsIm5iZiI6MTUzNzIzMTA0OCwiZXhwIjoxNTM3MjM0OTQ4LCJhaW8iOiJBWFFBaS84SUFBQUF0QWFaTG8zQ2hNaWY2S09udHRSQjdlQnE0L0RjY1F6amNKR3hQWXkvQzNqRGFOR3hYZDZ3TklJVkdSZ2hOUm53SjFsT2NBbk5aY2p2a295ckZ4Q3R0djMzMTQwUmlvT0ZKNGJDQ0dWdW9DYWcxdU9UVDIyMjIyZ0h3TFBZUS91Zjc5UVgrMEtJaWpkcm1wNjlSY3R6bVE9PSIsImF6cCI6IjZlNzQxNzJiLWJlNTYtNDg0My05ZmY0LWU2NmEzOWJiMTJlMyIsImF6cGFjciI6IjAiLCJuYW1lIjoiQWJlIExpbmNvbG4iLCJvaWQiOiI2OTAyMjJiZS1mZjFhLTRkNTYtYWJkMS03ZTRmN2QzOGU0NzQiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhYmVsaUBtaWNyb3NvZnQuY29tIiwicmgiOiJJIiwic2NwIjoiYWNjZXNzX2FzX3VzZXIiLCJzdWIiOiJIS1pwZmFIeVdhZGVPb3VZbGl0anJJLUtmZlRtMjIyWDVyclYzeERxZktRIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZnFpQnFYTFBqMGVRYTgyUy1JWUZBQSIsInZlciI6IjIuMCJ9.pj4N-w_3Us9DrBLfpCt
    

앱 매니페스트accessTokenAcceptedVersion 설정에 적절한 값을 제공하여 애플리케이션에 대해 버전을 설정합니다. 값이 null1이면 v1.0 토큰이 되고 값이 2이면 v2.0 토큰이 됩니다.

토큰 소유권

액세스 토큰 요청에는 두 파티, 즉 토큰을 요청하는 클라이언트와 토큰을 수락하는 리소스(Web API)가 관여합니다. 토큰이 의도한 리소스(‘대상’)는 토큰의 aud 클레임에 정의됩니다. 클라이언트는 토큰을 사용하지만 이해하거나 구문 분석을 시도해서는 안 됩니다. 리소스는 토큰을 허용합니다.

Microsoft ID 플랫폼은 모든 버전 엔드포인트에서 모든 토큰 버전을 발급하는 것을 지원합니다. 예를 들어, accessTokenAcceptedVersion 값이 2이면 해당 리소스에 대한 토큰을 가져오기 위해 v1.0 엔드포인트를 호출하는 클라이언트가 v2.0 액세스 토큰을 받습니다.

리소스는 항상 aud 클레임을 사용하여 토큰을 소유하고 토큰 세부 정보를 변경할 수 있는 유일한 애플리케이션입니다.

토큰 수명

액세스 토큰의 기본 수명은 변할 수 있습니다. 발급되면 Microsoft ID 플랫폼은 액세스 토큰의 기본 수명으로 60~90분(평균 75분) 사이의 임의 값을 할당합니다. 이 변형은 시간에 따라 액세스 토큰 수요를 분산시켜 서비스 복원력을 개선시켜 Microsoft Entra ID에 대한 시간당 트래픽 급증을 방지합니다.

조건부 액세스를 사용하지 않는 테넌트의 기본 액세스 토큰 수명은 Microsoft Teams 및 Microsoft 365와 같은 클라이언트에 대해 2시간입니다.

액세스 토큰의 수명을 조정하여 클라이언트 애플리케이션이 애플리케이션 세션을 만료하는 빈도 및 사용자에게 다시 인증하도록(자동으로 또는 대화형으로) 요구하는 빈도를 제어합니다. 기본 액세스 토큰 수명 변형을 재정의하려면 CTL(구성 가능한 토큰 수명)을 사용합니다.

CAE(지속적인 액세스 권한 평가)가 사용하도록 설정된 조직에 기본 토큰 수명 변형을 적용합니다. 조직에서 CTL 정책을 사용하는 경우에도 기본 토큰 수명 변형을 적용합니다. 수명이 긴 토큰 수명의 기본 토큰 수명 범위는 20~28시간입니다. 액세스 토큰이 만료되면 클라이언트는 새로 고침 토큰을 사용하여 새 새로 고침 토큰과 액세스 토큰을 자동으로 획득해야 합니다.

SIF(조건부 액세스 로그인 빈도)를 사용하여 로그인 빈도를 적용하는 조직은 기본 액세스 토큰 수명 변형을 재정의할 수 없습니다. 조직에서 SIF를 사용하는 경우 클라이언트에 대한 자격 증명 프롬프트 사이의 시간은 60~90분 범위의 토큰 수명에 로그인 빈도 간격을 더한 값입니다.

다음은 기본 토큰 수명 변형에서 로그인 빈도를 사용하는 방법의 예입니다. 조직에서 로그인 빈도가 매시간 발생하도록 설정한다고 가정해 보겠습니다. 토큰 수명 변형으로 인해 토큰의 수명이 60~90분인 경우 실제 로그인 간격은 1시간에서 2.5시간 사이에 발생합니다.

1시간 수명의 토큰이 있는 사용자가 59분에 대화형 로그인을 수행하는 경우 로그인이 SIF 임계값 미만이므로 자격 증명 프롬프트가 표시되지 않습니다. 새 토큰의 수명이 90분이면 자격 증명 프롬프트가 또 다른 1시간 30분 동안 사용자에게 표시되지 않습니다. 자동 갱신을 시도하는 동안 총 세션 길이가 로그인 빈도 설정인 1시간을 초과했기 때문에 Microsoft Entra ID에 자격 증명 프롬프트가 필요합니다. 이 예에서 SIF 간격 및 토큰 수명 변형으로 인한 자격 증명 프롬프트 간의 시간 차이는 2.5시간입니다.

토큰 유효성 검사

모든 애플리케이션에서 토큰의 유효성을 검사해야 하는 것은 아닙니다. 특정 시나리오에서만 애플리케이션에서 토큰의 유효성을 검사해야 합니다.

  • 웹 API는 클라이언트에 의해 전송된 액세스 토큰의 유효성을 검사해야 합니다. AppId URI 중 하나가 포함된 토큰만 aud 클레임으로 수락해야 합니다.
  • 웹앱은 사용자 데이터에 대한 액세스를 허용하거나 세션을 설정하기 전에 하이브리드 흐름에서 사용자의 브라우저를 통해 전송된 ID 토큰의 유효성을 검사해야 합니다.

이전에 설명한 시나리오가 적용되지 않는 경우 토큰의 유효성을 검사할 필요가 없습니다. 네이티브 또는 단일 페이지 애플리케이션과 같은 퍼블릭 클라이언트는 토큰 유효성 검사의 이점을 얻지 못합니다. 애플리케이션이 IDP와 직접 통신하며 이 경우 SSL 보호를 통해 토큰이 유효한지 확인하기 때문입니다. 클라이언트가 아닌 웹 API의 유효성을 검사하기 위해 액세스 토큰의 유효성을 검사해서는 안 됩니다.

API 및 웹 애플리케이션은 애플리케이션과 일치하는 aud 클레임이 있는 토큰만 유효성을 검사해야 합니다. 다른 리소스에는 사용자 지정 토큰 유효성 검사 규칙이 있을 수 있습니다. 예를 들어 Microsoft Graph 토큰은 독점 형식을 가지므로 이러한 규칙에 따라 유효성을 검사할 수 없습니다. 다른 리소스에 대한 토큰의 유효성을 검사하고 허용하는 것은 혼동된 대리인 문제의 예입니다.

애플리케이션이 ID 토큰 또는 액세스 토큰의 유효성을 검사해야 하는 경우 먼저 OpenID 검색 문서의 값에 대해 토큰의 서명과 발급자의 유효성을 검사해야 합니다.

Microsoft Entra 미들웨어에는 액세스 토큰의 유효성을 검사하는 기능이 기본 제공되어 있습니다. 적절한 언어로 된 토큰을 찾으려면 샘플을 참조하세요. JWT 유효성 검사에 사용할 수 있는 여러 타사 오픈 소스 라이브러리도 있습니다. 인증 라이브러리 및 코드 샘플에 대한 자세한 내용은 인증 라이브러리를 참조하세요. 웹앱 또는 웹 API가 ASP.NET 또는 ASP.NET Core인 경우 유효성 검사를 처리하는 Microsoft.Identity.Web을 사용합니다.

v1.0 및 v2.0 토큰

  • 웹앱/API가 v1.0 토큰(ver 클레임 =”1.0")의 유효성을 검사하는 경우 웹 API에 대해 구성된 기관이 v2.0 기관인 경우에도 v1.0 엔드포인트(https://login.microsoftonline.com/{example-tenant-id}/.well-known/openid-configuration)에서 OpenID Connect 메타데이터 문서를 읽어야 합니다.
  • 웹앱/API가 v2.0 토큰(ver 클레임 =”2.0")의 유효성을 검사하는 경우 웹 API에 대해 구성된 기관이 v1.0 기관인 경우에도 v2.0 엔드포인트(https://login.microsoftonline.com/{example-tenant-id}/v2.0/.well-known/openid-configuration)에서 OpenID Connect 메타데이터 문서를 읽어야 합니다.

다음 예제에서는 애플리케이션이 v2.0 액세스 토큰의 유효성을 검사하고 있다고 가정합니다(따라서 OIDC 메타데이터 문서 및 키의 v2.0 버전을 참조). v1.0 토큰의 유효성을 검사하는 경우 URL에서 “/v2.0”을 제거합니다.

발급자 유효성 검사

OpenID Connect Core에 “발급자 식별자 [...]는 iss(발급자) 클레임의 값과 정확히 일치해야 합니다.”라고 표시됩니다. 테넌트별 메타데이터 엔드포인트(예 https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/.well-known/openid-configuration 또는 https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0/.well-known/openid-configuration)를 사용하는 애플리케이션의 경우 이 모든 것이 필요합니다.

Microsoft Entra ID에는 https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration에서 사용할 수 있는 테넌트 독립적 버전의 문서가 있습니다. 이 엔드포인트는 발급자 값 https://login.microsoftonline.com/{tenantid}/v2.0를 반환합니다. 애플리케이션은 이 테넌트 독립적 엔드포인트를 사용하여 다음과 같은 수정을 통해 모든 테넌트에서 토큰의 유효성을 검사할 수 있습니다.

  1. 토큰의 발급자 클레임이 메타데이터의 발급자 값과 정확히 일치할 것으로 예상하는 대신 애플리케이션은 발급자 메타데이터의 {tenantid} 값을 현재 요청의 대상인 tenantid로 바꾼 다음 정확한 일치를 검사합니다.

  2. 애플리케이션은 키 엔드포인트에서 반환된 issuer 속성을 사용하여 키의 범위를 제한해야 합니다.

    • https://login.microsoftonline.com/{tenantid}/v2.0와 같은 발급자 값이 있는 키는 일치하는 토큰 발급자에서 사용할 수 있습니다.
    • https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0와 같은 발급자 값이 있는 키는 정확한 일치 항목으로만 사용해야 합니다.

    Microsoft Entra의 테넌트 독립적 키 엔드포인트(https://login.microsoftonline.com/common/discovery/v2.0/keys)는 다음과 같은 문서를 반환합니다.

    {
      "keys":[
        {"kty":"RSA","use":"sig","kid":"A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u","x5t":"A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u","n":"spv...","e":"AQAB","x5c":["MIID..."],"issuer":"https://login.microsoftonline.com/{tenantid}/v2.0"},
        {"kty":"RSA","use":"sig","kid":"C2dE3fH4iJ5kL6mN7oP8qR9sT0uV1w","x5t":"C2dE3fH4iJ5kL6mN7oP8qR9sT0uV1w","n":"wEM...","e":"AQAB","x5c":["MIID..."],"issuer":"https://login.microsoftonline.com/{tenantid}/v2.0"},
        {"kty":"RSA","use":"sig","kid":"E3fH4iJ5kL6mN7oP8qR9sT0uV1wX2y","x5t":"E3fH4iJ5kL6mN7oP8qR9sT0uV1wX2y","n":"rv0...","e":"AQAB","x5c":["MIID..."],"issuer":"https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0"}
      ]
    }
    
  3. 표준 발급자 클레임 대신 Microsoft Entra 테넌트 ID(tid) 클레임을 신뢰 경계로 사용하는 애플리케이션은 테넌트 ID 클레임이 GUID이고 발급자와 테넌트 ID가 일치하는지 확인해야 합니다.

테넌트 독립적 메타데이터를 사용하면 많은 테넌트에서 토큰을 수락하는 애플리케이션에 더 효율적입니다.

참고 항목

Microsoft Entra 테넌트 독립적 메타데이터를 사용하면 표준 OpenID Connect에서 클레임이 발급자 내에서 해석되는 것처럼 테넌트 내에서 클레임이 해석되어야 합니다. 즉, {"sub":"ABC123","iss":"https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0","tid":"aaaabbbb-0000-cccc-1111-dddd2222eeee"}{"sub":"ABC123","iss":"https://login.microsoftonline.com/bbbbcccc-1111-dddd-2222-eeee3333ffff/v2.0","tid":"bbbbcccc-1111-dddd-2222-eeee3333ffff"}sub와 같은 클레임이 발급자/테넌트 컨텍스트 내에서 해석되기 때문에 sub가 동일하더라도 다른 사용자를 설명합니다.

서명의 유효성을 검사

JWT에는 . 문자로 구분된 세 개의 세그먼트가 포함되어 있습니다. 첫 번째 세그먼트는 헤더, 두 번째 세그먼트는 본문, 세 번째 세그먼트는 서명입니다. 서명 세그먼트를 사용하여 토큰의 신뢰성을 평가합니다.

Microsoft Entra ID는 RS256과 같은 업계 표준 비대칭형 암호화 알고리즘을 사용하여 서명된 토큰을 발급합니다. JWT의 헤더에는 토큰 서명에 사용된 키 및 암호화 방법에 대한 정보가 들어 있습니다.

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "H4iJ5kL6mN7oP8qR9sT0uV1wX2yZ3a",
  "kid": "H4iJ5kL6mN7oP8qR9sT0uV1wX2yZ3a"
}

alg 클레임은 토큰 서명에 사용된 알고리즘을 나타내고 kid 클레임은 토큰 유효성 검사에 사용된 특정 공개 키를 나타냅니다.

특정 시점에 Microsoft Entra ID는 특정 공용-프라이빗 키 쌍 집합 중 하나를 사용하여 ID 토큰에 서명할 수 있습니다. Microsoft Entra ID는 주기적으로 가능한 키 집합을 회전하므로 해당 키 변경 내용을 자동으로 처리하도록 애플리케이션을 작성합니다. Microsoft Entra ID에서 사용하는 공개 키에 대한 업데이트를 확인하는 합리적인 빈도는 24시간마다입니다.

다음 위치에 있는 OpenID Connect 메타데이터 문서를 사용하여 서명 유효성 검사에 필요한 서명 키 데이터를 얻을 수 있습니다.

https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration

브라우저에서 다음을 시도합니다. URL

다음 정보는 메타데이터 문서에 대해 설명합니다.

  • OpenID Connect 인증을 수행하는 데 필요한 다양한 엔드포인트의 위치 등 여러 유용한 정보를 포함하는 JSON 개체입니다.
  • 토큰 서명에 사용된 프라이빗 키에 해당하는 퍼블릭 키 세트의 위치를 제공하는 jwks_uri를 포함합니다. jwks_uri에 있는 JWK(JSON 웹 키)는 해당 특정 시점에 사용 중인 공개 키 정보를 모두 포함합니다. RFC 7517은 JWK 형식을 설명합니다. 애플리케이션은 JWT 헤더에 kid 클레임을 사용하여 특정 토큰 서명에 사용된 프라이빗 키에 해당하는 공개 키를 이 문서에서 선택할 수 있습니다. 그런 다음, 올바른 공개 키와 표시된 알고리즘을 사용하여 서명 유효성 검사를 수행할 수 있습니다.

참고 항목

kid 클레임을 사용하여 토큰의 유효성을 검사합니다. v1.0 토큰에는 x5tkid 클레임이 있지만 v2.0 토큰에는 kid 클레임만 포함됩니다.

서명 유효성 검사를 수행하는 것은 이 문서의 범위를 벗어납니다. 필요한 경우 서명 유효성 검사를 도와주는 데 사용할 수 있는 오픈 소스 라이브러리가 많이 있습니다. 그러나 Microsoft ID 플랫폼에는 사용자 지정 서명 키인 표준에 대한 하나의 토큰 서명 확장이 있습니다.

claims-mapping 기능을 사용한 결과 애플리케이션에 사용자 지정 서명 키가 적용된 경우, 애플리케이션 ID를 포함하는 appid 쿼리 매개 변수를 추가합니다. 유효성 검사를 위해 애플리케이션의 서명 키 정보를 가리키는 jwks_uri를 사용합니다. 예를 들어 https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration?appid=00001111-aaaa-2222-bbbb-3333cccc4444https://login.microsoftonline.com/{tenant}/discovery/keys?appid=00001111-aaaa-2222-bbbb-3333cccc4444jwks_uri를 포함합니다.

발급자 유효성 검사

ID 토큰의 유효성을 검사하는 웹앱 및 액세스 토큰의 유효성을 검사하는 웹 API는 토큰(iss 클레임)의 발급자의 유효성을 검사해야 합니다.

  1. 애플리케이션 구성(기관)과 연결된 OpenID 연결 메타데이터 문서에서 사용할 수 있는 발급자입니다. 확인할 메타데이터 문서는 다음에 따라 다릅니다.
    • 토큰의 버전
    • 애플리케이션에서 지원하는 계정입니다.
  2. 토큰의 테넌트 ID(tid 클레임)
  3. 서명 키의 발급자입니다.

단일 테넌트 애플리케이션

OpenID Connect Core에 “발급자 식별자 [...]는 iss(발급자) 클레임의 값과 정확히 일치해야 합니다.”라고 표시됩니다. 테넌트별 메타데이터 엔드포인트(예: https://login.microsoftonline.com/{example-tenant-id}/v2.0/.well-known/openid-configuration 또는 https://login.microsoftonline.com/contoso.onmicrosoft.com/v2.0/.well-known/openid-configuration)를 사용하는 애플리케이션의 경우입니다.

단일 테넌트 애플리케이션은 다음을 지원하는 애플리케이션입니다.

  • 하나의 조직 디렉터리에 있는 계정(example-tenant-id 에만 해당): https://login.microsoftonline.com/{example-tenant-id}
  • 개인 Microsoft 계정만 해당: https://login.microsoftonline.com/consumers(소비자는 테넌트 9188040d-6c67-4c5b-b112-36a304b66dad에 대한 애칭임)

다중 테넌트 애플리케이션

Microsoft Entra ID는 다중 테넌트 애플리케이션도 지원합니다. 이런 애플리케이션은 다음을 지원합니다.

  • 모든 조직 디렉터리(모든 Microsoft Entra 디렉터리)의 계정: https://login.microsoftonline.com/organizations
  • 모든 조직 디렉터리(모든 Microsoft Entra 디렉터리) 및 개인 Microsoft 계정(예: Skype, XBox)의 계정: https://login.microsoftonline.com/common

이러한 애플리케이션의 경우 Microsoft Entra ID는 각각 https://login.microsoftonline.com/common/v2.0/.well-known/openid-configurationhttps://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration에서 OIDC 테넌트 독립적 버전의 문서를 노출합니다. 이런 엔드포인트는 tenantid에서 매개 변수화된 템플릿인 발급자 값을 반환합니다. https://login.microsoftonline.com/{tenantid}/v2.0 애플리케이션은 다음 규정으로 모든 테넌트에서 토큰의 유효성을 검사하기 위해 이런 테넌트 독립적 엔드포인트를 사용할 수 있습니다.

  • 서명 키 발급자 유효성 검사
  • 토큰의 발급자 클레임이 메타데이터의 발급자 값과 정확히 일치할 것으로 예상하는 대신 애플리케이션은 발급자 메타데이터의 {tenantid} 값을 현재 요청의 대상인 tenantid로 바꾼 다음 정확한 일치(토큰의 tid 클레임)를 검사합니다.
  • tid 클레임이 GUID이고 iss 클레임이 https://login.microsoftonline.com/{tid}/v2.0 형식이며 {tid}가 정확한 tid 클레임인지 확인합니다. 이 유효성 검사에서는 테넌트가 발급자와 다시 연결되고 신뢰 체인을 만드는 서명 키의 범위로 다시 연결됩니다.
  • 클레임의 주체와 연결된 데이터를 찾을 때 tid 클레임을 사용합니다. 즉, tid 클레임은 사용자의 데이터에 액세스하는 데 사용되는 키의 일부여야 합니다.

서명 키 발급자 유효성 검사

v2.0 테넌트 독립적 메타데이터를 사용하는 애플리케이션은 서명 키 발급자의 유효성을 검사해야 합니다.

키 문서 및 서명 키 발급자

설명한 대로 OpenID Connect 문서에서 애플리케이션은 토큰에 서명하는 데 사용되는 키에 액세스합니다. OpenIdConnect 문서의 jwks_uri 속성에 노출된 URL에 액세스하여 해당 키 문서를 가져옵니다.

 "jwks_uri": "https://login.microsoftonline.com/{example-tenant-id}/discovery/v2.0/keys",

{example-tenant-id} 값은 GUID, 도메인 이름 또는 일반적인, 조직소비자로 대체할 수 있습니다.

Azure AD v2.0에서 노출하는 keys 문서에는 각 키에 대해 이 서명 키를 사용하는 발급자를 포함합니다. 예를 들어 테넌트 독립적 “공통” 키 엔드포인트 https://login.microsoftonline.com/common/discovery/v2.0/keys는 다음과 같은 문서를 반환합니다.

{
  "keys":[
    {"kty":"RSA","use":"sig","kid":"A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u","x5t":"A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u","n":"spv...","e":"AQAB","x5c":["MIID..."],"issuer":"https://login.microsoftonline.com/{tenantid}/v2.0"},
    {"kty":"RSA","use":"sig","kid":"C2dE3fH4iJ5kL6mN7oP8qR9sT0uV1w","x5t":"C2dE3fH4iJ5kL6mN7oP8qR9sT0uV1w","n":"wEM...","e":"AQAB","x5c":["MIID..."],"issuer":"https://login.microsoftonline.com/{tenantid}/v2.0"},
    {"kty":"RSA","use":"sig","kid":"E3fH4iJ5kL6mN7oP8qR9sT0uV1wX2y","x5t":"E3fH4iJ5kL6mN7oP8qR9sT0uV1wX2y","n":"rv0...","e":"AQAB","x5c":["MIID..."],"issuer":"https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0"}
  ]
}

서명 키 발급자의 유효성 검사

애플리케이션은 키의 범위를 제한하기 위해 토큰에 서명하는 데 사용되는 키와 연결된 키 문서의 issuer 속성을 사용해야 합니다.

  • GUID와 같은 https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0 발급자 값이 있는 키는 토큰의 iss 클레임이 값과 정확히 일치하는 경우에만 사용해야 합니다.
  • https://login.microsoftonline.com/{tenantid}/v2.0와 같은 템플릿 발급자 값이 있는 키는 토큰의 iss 클레임이 {tenantid} 자리 표시자에 대한 토큰의 tid 클레임을 대체한 후 이 값과 일치하는 경우에만 사용해야 합니다.

테넌트 독립적 메타데이터를 사용하면 많은 테넌트에서 토큰을 수락하는 애플리케이션에 더 효율적입니다.

참고 항목

Microsoft Entra 테넌트 독립적 메타데이터를 사용하면 표준 OpenID Connect에서 클레임이 발급자 내에서 해석되는 것처럼 테넌트 내에서 클레임이 해석되어야 합니다. 즉, {"sub":"ABC123","iss":"https://login.microsoftonline.com/{example-tenant-id}/v2.0","tid":"{example-tenant-id}"}{"sub":"ABC123","iss":"https://login.microsoftonline.com/{another-tenand-id}/v2.0","tid":"{another-tenant-id}"}sub와 같은 클레임이 발급자/테넌트 컨텍스트 내에서 해석되기 때문에 sub가 동일하더라도 다른 사용자를 설명합니다.

요약

다음은 발급자 및 서명 키 발급자의 유효성을 검사하는 방법을 재현하는 몇 가지 의사 코드입니다.

  1. 구성된 메타데이터 URL에서 키 가져오기
  2. 게시된 키 중 하나로 서명된 경우 토큰을 확인합니다. 그러지 않으면 실패합니다.
  3. kid 헤더를 기반으로 메타데이터의 키를 식별합니다. 메타데이터 문서의 키에 연결된 “발급자” 속성을 확인합니다.
    var issuer = metadata["kid"].issuer;
    if (issuer.contains("{tenantId}", CaseInvariant)) issuer = issuer.Replace("{tenantid}", token["tid"], CaseInvariant);
    if (issuer != token["iss"]) throw validationException;
    if (configuration.allowedIssuer != "*" && configuration.allowedIssuer != issuer) throw validationException;
    var issUri = new Uri(token["iss"]);
    if (issUri.Segments.Count < 1) throw validationException;
    if (issUri.Segments[1] != token["tid"]) throw validationException;