OAuth 2.0, Azure Active Directory B2C 및 Azure API Management를 사용 하 여 SPA 백 엔드 보호Protect SPA backend with OAuth 2.0, Azure Active Directory B2C and Azure API Management

이 시나리오에서는 API를 보호 하도록 Azure API Management 인스턴스를 구성 하는 방법을 보여 줍니다.This scenario shows you how to configure your Azure API Management instance to protect an API. EasyAuth를 사용 하 여 Azure Functions 백 엔드를 보호 하는 API Management와 함께 Azure AD B2C SPA (Auth Code + PKCE) flow를 사용 하 여 토큰을 가져옵니다.We'll use the Azure AD B2C SPA (Auth Code + PKCE) flow to acquire a token, alongside API Management to secure an Azure Functions backend using EasyAuth.

목표Aims

Azure Functions 및 Azure AD B2C를 사용 하 여 간소화 된 시나리오에서 API Management를 사용 하는 방법을 살펴보겠습니다.We're going to see how API Management can be used in a simplified scenario with Azure Functions and Azure AD B2C. Azure AD B2C를 사용 하 여 사용자에 게 로그인 하는 API를 호출 하는 JavaScript (JS) 앱을 만듭니다.You'll create a JavaScript (JS) app calling an API, that signs in users with Azure AD B2C. 그런 다음 키 정책 기능을 통해 API Management의 jwt, CORS 및 요율 제한을 사용 하 여 백 엔드 API를 보호 합니다.Then you'll use API Management's validate-jwt, CORS, and Rate Limit By Key policy features to protect the Backend API.

심층 방어를 위해 EasyAuth를 사용 하 여 백 엔드 API 내에서 토큰의 유효성을 다시 검사 하 고 API management가 Azure Functions 백 엔드를 호출할 수 있는 유일한 서비스 인지 확인 합니다.For defense in depth, we then use EasyAuth to validate the token again inside the back-end API and ensure that API management is the only service that can call the Azure Functions backend.

학습할 내용What will you learn

  • Azure Active Directory B2C의 단일 페이지 앱 및 백 엔드 API 설정Setup of a Single Page App and backend API in Azure Active Directory B2C
  • Azure Functions 백 엔드 API 만들기Creation of an Azure Functions Backend API
  • Azure API Management에 Azure Functions API 가져오기Import of an Azure Functions API into Azure API Management
  • Azure API Management에서 API 보호Securing the API in Azure API Management
  • MSAL.js (Microsoft Id 플랫폼 라이브러리)를 통해 Azure Active Directory B2C 권한 부여 끝점 호출Calling the Azure Active Directory B2C Authorization Endpoints via the Microsoft Identity Platform Libraries (MSAL.js)
  • HTML/바닐라 JS 단일 페이지 응용 프로그램을 저장 하 고 Azure Blob Storage 끝점에서 서비스 제공Storing a HTML / Vanilla JS Single Page Application and serving it from an Azure Blob Storage Endpoint

필수 구성 요소Prerequisites

이 문서의 단계를 따르려면 다음이 있어야 합니다.To follow the steps in this article, you must have:

  • 프런트 엔드 JS 단일 페이지 앱을 호스트 하는 Azure (StorageV2) 범용 V2 저장소 계정.An Azure (StorageV2) General Purpose V2 Storage Account to host the frontend JS Single Page App.
  • Azure API Management 인스턴스 (' 소비 '를 비롯 한 모든 계층은 작동 하지만, 전체 시나리오에 적용 되는 특정 기능을이 계층에서 사용할 수 없는 경우 (요금 제한-키 단위 및 전용 가상 IP) 이러한 제한은 해당 하는 문서에서 아래에 설명 되어 있습니다.An Azure API Management instance (Any tier will work, including 'Consumption', however certain features applicable to the full scenario are not available in this tier (rate-limit-by-key and dedicated Virtual IP), these restrictions are called out below in the article where appropriate).
  • 호출 된 API를 호스트 하는 빈 Azure 함수 앱 (소비 계획에서 V 3.1 .NET Core 런타임 실행)An empty Azure Function app (running the V3.1 .NET Core runtime, on a Consumption Plan) to host the called API
  • 구독에 연결 된 Azure AD B2C 테 넌 트입니다.An Azure AD B2C tenant, linked to a subscription.

실제로 프로덕션 워크 로드에서 동일한 지역의 리소스를 사용 하는 경우에도이 방법 문서에서는 배포 지역이 중요 하지 않습니다.Although in practice you would use resources in the same region in production workloads, for this how-to article the region of deployment isn't important.

개요Overview

다음은 사용 중인 구성 요소와이 프로세스가 완료 된 후 이러한 구성 요소 간의 흐름을 보여 주는 그림입니다.Here's an illustration of the components in use and the flow between them once this process is complete. 사용 중인 구성 요소 및 흐름Components in use and flow

단계에 대 한 간략 한 개요는 다음과 같습니다.Here's a quick overview of the steps:

  1. 범위를 포함 하는 Azure AD B2C (프런트 엔드, API Management) 및 API 응용 프로그램을 만들고 API 액세스를 부여 합니다.Create the Azure AD B2C Calling (Frontend, API Management) and API Applications with scopes and grant API Access

  2. 사용자가 Azure AD B2C를 사용 하 여 로그인 할 수 있도록 등록 및 로그인 정책 만들기Create the sign up and sign in policies to allow users to sign in with Azure AD B2C

  3. 개발자 콘솔에서 OAuth2 사용자 권한 부여를 사용 하도록 새 Azure AD B2C 클라이언트 Id 및 키를 사용 하 여 API Management 구성Configure API Management with the new Azure AD B2C Client IDs and keys to Enable OAuth2 user authorization in the Developer Console

  4. 함수 API 빌드Build the Function API

  5. 새 Azure AD B2C 클라이언트 ID 및 키로 EasyAuth를 사용 하도록 설정 하 고 APIM VIP로 잠금을 해제 하도록 함수 API를 구성 합니다.Configure the Function API to enable EasyAuth with the new Azure AD B2C Client ID’s and Keys and lock down to APIM VIP

  6. API Management에서 API 정의를 빌드합니다.Build the API Definition in API Management

  7. API Management API 구성에 대해 Oauth2 설정Set up Oauth2 for the API Management API configuration

  8. CORS 정책을 설정 하 고 jwt 유효성 검사 정책을 추가 하 여 들어오는 모든 요청에 대 한 OAuth 토큰의 유효성을 검사 합니다.Set up the CORS policy and add the validate-jwt policy to validate the OAuth token for every incoming request

  9. API를 사용 하는 호출 응용 프로그램 빌드Build the calling application to consume the API

  10. JS SPA 샘플 업로드Upload the JS SPA Sample

  11. 새 Azure AD B2C 클라이언트 ID 및 키를 사용 하 여 샘플 JS 클라이언트 앱 구성Configure the Sample JS Client App with the new Azure AD B2C Client ID’s and keys

  12. 클라이언트 응용 프로그램 테스트Test the Client Application

    이 문서를 살펴볼 때 많은 정보 및 키를 캡처할 예정입니다. 다음 구성 항목을 일시적으로 저장 하기 위해 텍스트 편집기를 여는 것이 편리할 수 있습니다.We're going to capture quite a few pieces of information and keys etc as we walk this document, you might find it handy to have a text editor open to store the following items of configuration temporarily.

    B2C 백 엔드 클라이언트 ID:B2C BACKEND CLIENT ID:
    B2C 백엔드 클라이언트 비밀 키:B2C BACKEND CLIENT SECRET KEY:
    B2C 백엔드 API 범위 URI:B2C BACKEND API SCOPE URI:
    B2C 프런트 엔드 클라이언트 ID:B2C FRONTEND CLIENT ID:
    B2C 사용자 흐름 끝점 URI:B2C USER FLOW ENDPOINT URI:
    B2C 잘 알려진 OPENID CONNECT 끝점:B2C WELL-KNOWN OPENID ENDPOINT:
    B2C 정책 이름: Frontendapp_signupandsignin 함수 URL:B2C POLICY NAME: Frontendapp_signupandsignin FUNCTION URL:
    APIM API 기준 URL: 저장소 기본 끝점 URL:APIM API BASE URL: STORAGE PRIMARY ENDPOINT URL:

백 엔드 응용 프로그램 구성Configure the backend application

포털에서 Azure AD B2C 블레이드를 열고 다음 단계를 수행 합니다.Open the Azure AD B2C blade in the portal and do the following steps.

  1. 앱 등록 탭을 선택 합니다.Select the App Registrations tab

  2. ' 새 등록 ' 단추를 클릭 합니다.Click the 'New Registration' button.

  3. 리디렉션 URI 선택 상자에서 ' 웹 '을 선택 합니다.Choose 'Web' from the Redirect URI selection box.

  4. 이제 표시 이름을 설정 하 고, 생성 되는 서비스와 관련 된 고유한 항목을 선택 합니다.Now set the Display Name, choose something unique and relevant to the service being created. 이 예제에서는 "백 엔드 응용 프로그램" 이름을 사용 합니다.In this example, we will use the name "Backend Application".

  5. 회신 url에 대 한 자리 표시자를 사용 하 여 ' https://jwt.ms ' (Microsoft 소유의 토큰 디코딩 사이트) 나중에 해당 url을 업데이트 합니다.Use placeholders for the reply urls, like 'https://jwt.ms' (A Microsoft owned token decoding site), we’ll update those urls later.

  6. "모든 id 공급자 또는 조직 디렉터리의 계정 (사용자 흐름을 사용 하 여 사용자 인증)" 옵션을 선택 했는지 확인 합니다.Ensure you have selected the "Accounts in any identity provider or organizational directory (for authenticating users with user flows)" option

  7. 이 샘플의 경우 현재 offline_access 권한이 필요 하지 않으므로 "관리자 동의 부여" 확인란의 선택을 취소 합니다.For this sample, uncheck the "Grant admin consent" box, as we won't require offline_access permissions today.

  8. '등록'을 클릭합니다.Click 'Register'.

  9. 나중에 사용 하기 위해 백 엔드 응용 프로그램 클라이언트 ID를 기록 합니다 (' 응용 프로그램 (클라이언트) ID ' 아래에 표시 됨).Record the Backend Application Client ID for later use (shown under 'Application (client) ID').

  10. 인증서 및 비밀 탭 (관리 아래)을 선택 하 고 ' 새 클라이언트 암호 '를 클릭 하 여 인증 키를 생성 합니다 (기본 설정을 적용 하 고 ' 추가 ' 클릭).Select the Certificates and Secrets tab (under Manage) then click 'New Client Secret' to generate an auth key (Accept the default settings and click 'Add').

  11. ' 추가 '를 클릭 하 고 나중에 ' 백 엔드 클라이언트 암호 '로 사용 하기 위해 안전 하 게 ' 값 ' 아래의 키를 복사 합니다 .이 대화 상자는이 키를 복사 해야 하는 유일한 기회입니다.Upon clicking 'Add', copy the key (under 'value') somewhere safe for later use as the 'Backend client secret' - note that this dialog is the ONLY chance you'll have to copy this key.

  12. 이제 API 탭 표시 (관리 아래)를 선택 합니다.Now select the Expose an API Tab (Under Manage).

  13. AppID URI를 설정 하 라는 메시지가 표시 되 면 기본값을 선택 하 고 기록 합니다.You will be prompted to set the AppID URI, select and record the default value.

  14. 함수 API에 대 한 "Hello" 범위 만들기 및 이름 지정할 수 있는 모든 옵션에 대해 ' Hello ' 구문을 사용 하 여 채워진 전체 범위 값 URI를 기록한 다음 ' 범위 추가 '를 클릭할 수 있습니다.Create and name the scope "Hello" for your Function API, you can use the phrase 'Hello' for all of the enterable options, recording the populated Full Scope Value URI, then click 'Add Scope'.

  15. 포털의 왼쪽 위에 있는 ' Azure AD B2C ' 이동 경로를 선택 하 여 Azure AD B2C 블레이드의 루트로 돌아갑니다.Return to the root of the Azure AD B2C blade by selecting the 'Azure AD B2C' breadcrumb at the top left of the portal.

    참고

    Azure AD B2C 범위는 응용 프로그램에서 API 액세스 블레이드를 통해 다른 응용 프로그램에 대 한 액세스를 요청할 수 있는 API 내에서 효과적으로 사용 되는 권한으로, 호출 된 API에 대 한 응용 프로그램 권한을 효과적으로 만들었습니다.Azure AD B2C scopes are effectively permissions within your API that other applications can request access to via the API access blade from their applications, effectively you just created application permissions for your called API.

프런트 엔드 응용 프로그램 구성Configure the frontend application

  1. 앱 등록 탭을 선택 합니다.Select the App Registrations tab
  2. ' 새 등록 ' 단추를 클릭 합니다.Click the 'New Registration' button.
  3. 리디렉션 URI 선택 상자에서 ' SPA (단일 페이지 응용 프로그램) '를 선택 합니다.Choose 'Single Page Application (SPA)' from the Redirect URI selection box.
  4. 이제 표시 이름 및 AppID URI를 설정 하 고,이 AAD B2C 앱 등록을 사용 하는 프런트 엔드 응용 프로그램과 관련 된 고유한 항목을 선택 합니다.Now set the Display Name and AppID URI, choose something unique and relevant to the Frontend application that will use this AAD B2C app registration. 이 예제에서는 "프런트 엔드 응용 프로그램"을 사용할 수 있습니다.In this example, you can use "Frontend Application"
  5. 첫 번째 앱 등록에 따라 지원 되는 계정 유형 선택 항목을 기본값으로 둡니다. 사용자 흐름을 사용 하 여 사용자를 인증 합니다.As per the first app registration, leave the supported account types selection to default (authenticating users with user flows)
  6. 회신 url에 대 한 자리 표시자를 사용 하 여 ' https://jwt.ms ' (Microsoft 소유의 토큰 디코딩 사이트) 나중에 해당 url을 업데이트 합니다.Use placeholders for the reply urls, like 'https://jwt.ms' (A Microsoft owned token decoding site), we’ll update those urls later.
  7. 관리자 동의 허용 상자를 그대로 선택.Leave the grant admin consent box ticked
  8. '등록'을 클릭합니다.Click 'Register'.
  9. 나중에 사용할 프런트 엔드 응용 프로그램 클라이언트 ID를 기록 합니다 (' 응용 프로그램 (클라이언트) ID ' 아래에 표시 됨).Record the Frontend Application Client ID for later use (shown under 'Application (client) ID').
  10. API 사용 권한 탭으로 전환 합니다.Switch to the API Permissions tab.
  11. ' 권한 추가 ', ' 내 Api ', ' 백 엔드 응용 프로그램 ', ' 사용 권한 '을 차례로 선택 하 고, 이전 섹션에서 만든 범위를 선택 하 고, ' 권한 추가 '를 클릭 하 여 백 엔드 응용 프로그램에 대 한 액세스 권한을 부여 합니다.Grant access to the backend application by clicking 'Add a permission', then 'My APIs', select the 'Backend Application', select 'Permissions', select the scope you created in the previous section, and click 'Add permissions'
  12. ' {Tenant}에 대해 관리자 동의 부여를 클릭 하 고 팝업 대화 상자에서 ' 예 '를 클릭 합니다.Click 'Grant admin consent for {tenant} and click 'Yes' from the popup dialog. 이 팝업은 앞에서 만든 "백 엔드 응용 프로그램"에 정의 된 사용 권한 "hello"를 사용 하는 "프런트 엔드 응용 프로그램"을 동의 합니다.This popup consents the "Frontend Application" to use the permission "hello" defined in the "Backend Application" created earlier.
  13. 이제 모든 권한이 상태 열에서 녹색 틱으로 앱에 대해 표시 됩니다.All Permissions should now show for the app as a green tick under the status column

"등록 및 로그인" 사용자 흐름 만들기Create a "Sign up and Sign in" user flow

  1. Azure AD B2C 이동 경로를 선택 하 여 B2C 블레이드의 루트로 돌아갑니다.Return to the root of the B2C blade by selecting the Azure AD B2C breadcrumb.

  2. [정책] 탭에서 ' 사용자 흐름 '로 전환 합니다.Switch to the 'User Flows' (Under Policies) tab.

  3. "새 사용자 흐름"을 클릭 합니다.Click "New user flow"

  4. ' 등록 및 로그인 ' 사용자 흐름 유형을 선택 하 고 ' 권장 ', ' 만들기 '를 차례로 선택 합니다.Choose the 'Sign up and sign in' user flow type, and select 'Recommended' and then 'Create'

  5. 정책에 이름을 지정 하 고 나중에 기록 합니다.Give the policy a name and record it for later. 이 예에서는 "Frontendapp_signupandsignin"을 사용할 수 있습니다. "B2C_1_Frontendapp_signupandsignin"를 만들기 위해 "B2C_1_" 접두사가 접두사로 추가 됩니다.For this example, you can use "Frontendapp_signupandsignin", note that this will be prefixed with "B2C_1_" to make "B2C_1_Frontendapp_signupandsignin"

  6. ' Id 공급자 ' 및 "로컬 계정"에서 ' 전자 메일 등록 ' (또는 B2C 테 넌 트의 구성에 따라 ' 사용자 ID 등록 ')을 선택 하 고 확인을 클릭 합니다.Under 'Identity providers' and "Local accounts", check 'Email sign up' (or 'User ID sign up' depending on the config of your B2C tenant) and click OK. 이 구성은 사용자의 기존 소셜 미디어 계정을 사용 하기 위해 다른 id 공급자 (예: 소셜 id 공급자)로 지연 되지 않고 로컬 B2C 계정을 등록할 수 있기 때문입니다.This configuration is because we'll be registering local B2C accounts, not deferring to another identity provider (like a social identity provider) to use an user's existing social media account.

  7. MFA 및 조건부 액세스 설정은 기본값으로 둡니다.Leave the MFA and conditional access settings at their defaults.

  8. ' 사용자 특성 및 클레임 '에서 ' 자세히 표시 ... '를 클릭 합니다. 그런 다음 사용자가 입력 하 고 토큰에서 반환 하려는 클레임 옵션을 선택 합니다.Under 'User Attributes and claims', click 'Show More...' then choose the claim options that you want your users to enter and have returned in the token. 반환할 ' 표시 이름 ' 및 ' 전자 메일 주소 '를 선택 하 고, ' 표시 이름 ' 및 ' 전자 메일 주소 '를 사용 하 여 (emailaddress, 단수형을 수집 하 고 전자 메일 주소를 반환 하도록 요청 하는 사실에 주의 해야 합니다.) ' 확인 '을 클릭 한 다음 ' 만들기 '를 클릭 합니다.Check at least 'Display Name' and 'Email Address' to collect, with 'Display Name' and 'Email Addresses' to return (pay careful attention to the fact that you are collecting emailaddress, singular, and asking to return email addresses, multiple), and click 'OK', then click 'Create'.

  9. 목록에서 만든 사용자 흐름을 클릭 한 다음 ' 사용자 흐름 실행 ' 단추를 클릭 합니다.Click on the user flow that you created in the list, then click the 'Run user flow' button.

  10. 이 작업은 사용자 흐름 실행 블레이드를 열고, 프런트 엔드 응용 프로그램을 선택 하 고, 사용자 흐름 끝점을 복사 하 여 나중에 저장 합니다.This action will open the run user flow blade, select the frontend application, copy the user flow endpoint and save it for later.

  11. 나중에 사용 하기 위해 ' 잘 알려진 openid connect 구성 끝점 '으로 기록 하 여 맨 위에 있는 링크를 복사 하 고 저장 합니다.Copy and store the link at the top, recording as the 'well-known openid configuration endpoint' for later use.

    참고

    B2C 정책을 사용 하면 다양 한 방식으로 다양 한 데이터 구성 요소 및 로그인 사용자를 캡처할 수 있도록 Azure AD B2C 로그인 끝점을 노출할 수 있습니다.B2C Policies allow you to expose the Azure AD B2C login endpoints to be able to capture different data components and sign in users in different ways.

    이 경우 등록 또는 로그인 흐름 (정책)을 구성 했습니다.In this case we configured a sign up or sign in flow (policy). 이는 잘 알려진 구성 끝점도 노출 합니다. 두 경우 모두 생성 된 정책은 URL에서 "p =" 쿼리 문자열 매개 변수로 식별 되었습니다.This also exposed a well-known configuration endpoint, in both cases our created policy was identified in the URL by the "p=" query string parameter.

    이 작업이 완료 되 면 이제 여러 응용 프로그램에 사용자를 로그인 하는 기능을 갖춘 소비자 id 플랫폼을 사용할 수 있습니다.Once this is done, you now have a functional Business to Consumer identity platform that will sign users into multiple applications.

함수 API 빌드Build the function API

  1. 구독에서 항목을 다시 구성할 수 있도록 Azure Portal에서 표준 Azure AD 테 넌 트로 다시 전환 합니다.Switch back to your standard Azure AD tenant in the Azure portal so we can configure items in your subscription again.

  2. Azure Portal의 함수 앱 블레이드로 이동 하 여 빈 함수 앱을 연 다음 ' 함수 '를 클릭 하 고 ' 추가 '를 클릭 합니다.Go to the Function Apps blade of the Azure portal, open your empty function app, then click 'Functions', click 'Add'.

  3. 표시 되는 플라이 아웃에서 ' 포털에서 개발 '을 선택한 다음 ' 템플릿 선택 ' 아래에서 ' HTTP 트리거 '를 선택 하 고 템플릿 세부 정보 아래에서 권한 부여 수준 ' Function '이 포함 된 ' hello '로 이름을 지정한 다음 추가를 선택 합니다.In the flyout that appears, choose 'Develop in portal', under 'select a template' then choose 'HTTP trigger', under Template details name it 'hello' with authorization level 'Function', then select Add.

  4. 코드 + 테스트 블레이드로 전환 하 고 아래에 있는 샘플 코드를 복사 하 여 아래에 표시 되는 기존 코드 위에 붙여넣습니다.Switch to the Code + Test blade and copy-paste the sample code from below over the existing code that appears.

  5. [저장]을 선택합니다.Select Save.

    
    using System.Net;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Primitives;
    
    public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
    {
       log.LogInformation("C# HTTP trigger function processed a request.");
    
       return (ActionResult)new OkObjectResult($"Hello World, time and date are {DateTime.Now.ToString()}");
    }
    
    

    방금 붙여 넣은 c # 스크립트 함수 코드는 단순히 함수 로그에 줄을 기록 하 고 일부 동적 데이터 (날짜 및 시간)를 사용 하 여 "헬로 월드" 텍스트를 반환 합니다.The c# script function code you just pasted simply logs a line to the functions logs, and returns the text "Hello World" with some dynamic data (the date and time).

  6. 왼쪽 블레이드에서 "통합"을 선택 하 고 ' 트리거 ' 상자 내에서 http (요청) 링크를 클릭 합니다.Select “Integration” from the left-hand blade, then click the http (req) link inside the 'Trigger' box.

  7. ' 선택한 HTTP 메서드 ' 드롭다운에서 http POST 메서드를 선택 취소 하 고, 선택 항목만 남기고 나 서, 저장을 클릭 합니다.From the 'Selected HTTP methods' dropdown, uncheck the http POST method, leaving only GET selected, then click Save.

  8. 코드 + 테스트 탭으로 다시 전환 하 고 ' 함수 URL 가져오기 '를 클릭 한 다음 표시 되는 URL을 복사 하 여 나중에 저장 합니다.Switch back to the Code + Test tab, click 'Get Function URL', then copy the URL that appears and save it for later.

    참고

    방금 만든 바인딩은 방금 복사한 URL ()에 대 한 익명 http GET 요청에 응답 하도록 함수에 지시 https://yourfunctionappname.azurewebsites.net/api/hello?code=secretkey 합니다.The bindings you just created simply tell Functions to respond on anonymous http GET requests to the URL you just copied (https://yourfunctionappname.azurewebsites.net/api/hello?code=secretkey). 이제 매우 간단한 페이로드를 반환할 수 있는 확장 되지 않은 서버를 사용 하는 https API가 있습니다.Now we have a scalable serverless https API, that is capable of returning a very simple payload.

    이제 방금 복사 하 고 저장 한 위의 URL 버전을 사용 하 여 웹 브라우저에서이 API 호출을 테스트할 수 있습니다.You can now test calling this API from a web browser using your version of the URL above that you just copied and saved. URL의 쿼리 문자열 매개 변수 "? code = secretkey" 부분을 제거 하 고 다시 테스트 하 여 Azure Functions에서 401 오류를 반환 하는지 증명할 수도 있습니다.You can also remove the query string parameters "?code=secretkey" portion of the URL , and test again, to prove that Azure Functions will return a 401 error.

함수 API 구성 및 보안Configure and secure the function API

  1. 함수 앱의 두 추가 영역을 구성 해야 합니다 (권한 부여 및 네트워크 제한).Two extra areas in the function app need to be configured (Authorization and Network Restrictions).

  2. 먼저 인증/권한 부여를 구성 했으므로 이동 경로를 통해 함수 앱의 루트 블레이드로 다시 이동 합니다.Firstly Let's configure Authentication / Authorization, so navigate back to the root blade of the function app via the breadcrumb.

  3. 그런 다음 ' 설정 ' 아래에서 ' 인증/권한 부여 '를 선택 합니다.Next select 'Authentication / Authorization' (under 'Settings').

  4. App Service 인증 기능을 설정 합니다.Turn on the App Service Authentication feature.

  5. 요청이 인증 되지 않은 경우에 수행할 동작을 "Azure Active Directory 사용 하 여 로그인"으로 설정 합니다.Set the Action to take when request is not authenticated dropdown to "Log in with Azure Active Directory".

  6. ' 인증 공급자 '에서 ' Azure Active Directory '를 선택 합니다.Under 'Authentication Providers', choose ‘Azure Active Directory’.

  7. 관리 모드 스위치에서 ' 고급 '을 선택 합니다.Choose ‘Advanced’ from the Management Mode switch.

  8. 백 엔드 응용 프로그램의 [Application] 클라이언트 ID (Azure AD B2C에서)를 ' 클라이언트 ID ' 상자에 붙여넣습니다.Paste the Backend application's [Application] Client ID (from Azure AD B2C) into the ‘Client ID’ box

  9. 등록 및 로그인 정책에서 잘 알려진 오픈 id 구성 끝점을 발급자 URL 상자에 붙여넣습니다 (이전에이 구성을 기록 함).Paste the Well-known open-id configuration endpoint from the sign up and sign in policy into the Issuer URL box (we recorded this configuration earlier).

  10. ' 암호 표시 '를 클릭 하 고 백 엔드 응용 프로그램의 클라이언트 암호를 해당 상자에 붙여넣습니다.Click 'Show Secret' and paste the Backend application's client secret into the appropriate box.

  11. 확인을 선택 하 여 id 공급자 선택 블레이드/화면으로 돌아갑니다.Select OK, which takes you back to the identity provider selection blade/screen.

  12. 고급 설정에서 토큰 저장소 를 사용 하도록 설정 된 상태로 둡니다 (기본값).Leave Token Store enabled under advanced settings (default).

  13. 블레이드의 왼쪽 위에서 ' 저장 '을 클릭 합니다.Click 'Save' (at the top left of the blade).

    중요

    이제 함수 API가 배포 되 고 올바른 JWT가 권한 부여: 전달자 헤더로 제공 되지 않는 경우 401 응답을 throw 하 고 유효한 요청이 표시 될 때 데이터를 반환 해야 합니다.Now your Function API is deployed and should throw 401 responses if the correct JWT is not supplied as an Authorization: Bearer header, and should return data when a valid request is presented.
    인증 되지 않은 요청을 처리 하기 위해 ' Azure AD를 사용 하 여 로그인 ' 옵션을 구성 하 여 EasyAuth에서 심층 방어 보안을 추가 했습니다.You added additional defense-in-depth security in EasyAuth by configuring the 'Login With Azure AD' option to handle unauthenticated requests. EasyAuth는 백 엔드 함수 앱와 프런트 엔드 SPA 간에 인증 되지 않은 요청 동작을 변경 합니다 .이는 401 권한이 부여 되지 않은 응답 대신 AAD에 302 리디렉션을 실행 하므로 나중에 API Management를 사용 하 여 해결할 수 있습니다.Be aware that this will change the unauthorized request behavior between the Backend Function App and Frontend SPA as EasyAuth will issue a 302 redirect to AAD instead of a 401 Not Authorized response, we will correct this by using API Management later.

    여전히 IP 보안이 적용 되지 않습니다. 유효한 키 및 OAuth2 토큰이 있는 경우 누구나이를 호출할 수 있습니다. 모든 요청을 API Management를 통해 적용 하는 것이 좋습니다.We still have no IP security applied, if you have a valid key and OAuth2 token, anyone can call this from anywhere - ideally we want to force all requests to come via API Management.

    APIM 소비 계층을 사용 하는 경우, 함수 액세스 제한에 대 한 전용 Azure API Management 가상 IP가 허용 목록에 없습니다.If you're using APIM Consumption tier then there isn't a dedicated Azure API Management Virtual IP to allow-list with the functions access-restrictions. Azure API Management Standard SKU 이상에서 VIP는 단일 테 넌 트이 고 리소스의 수명 동안입니다.In the Azure API Management Standard SKU and above the VIP is single tenant and for the lifetime of the resource. Azure API Management 소비 계층의 경우 위에서 복사한 URI의 부분에 있는 공유 비밀 기능 키를 통해 API 호출을 잠글 수 있습니다.For the Azure API Management Consumption tier, you can lock down your API calls via the shared secret function key in the portion of the URI you copied above. 또한 소비 계층-아래 12-17 단계는 적용 되지 않습니다.Also, for the Consumption tier - steps 12-17 below do not apply.

  14. ' 인증/권한 부여 ' 블레이드를 닫습니다.Close the 'Authentication / Authorization' blade

  15. 포털의 API Management 블레이드 를 연 후 인스턴스 를 엽니다.Open the API Management blade of the portal, then open your instance.

  16. 개요 탭에 표시 된 개인 VIP를 기록 합니다.Record the Private VIP shown on the overview tab.

  17. 포털의 Azure Functions 블레이드 로 돌아간 후 인스턴스 를 다시 엽니다.Return to the Azure Functions blade of the portal then open your instance again.

  18. ' 네트워킹 '을 선택한 후 ' 액세스 제한 구성 '을 선택 합니다.Select 'Networking' and then select 'Configure access restrictions'

  19. ' 규칙 추가 '를 클릭 하 고 위의 3 단계에서 복사한 VIP를 xx. xx. xx/32 형식으로 입력 합니다.Click 'Add Rule', and enter the VIP copied in step 3 above in the format xx.xx.xx.xx/32.

  20. 계속 해 서 함수 포털과 상호 작용 하 고 아래에서 선택적 단계를 수행 하려는 경우 사용자 고유의 공용 IP 주소 또는 CIDR 범위만 추가 해야 합니다.If you want to continue to interact with the functions portal, and to carry out the optional steps below, you should add your own public IP address or CIDR range here too.

  21. 목록에 허용 항목이 있으면 Azure는 다른 모든 주소를 차단 하는 암시적인 거부 규칙을 추가 합니다.Once there’s an allow entry in the list, Azure adds an implicit deny rule to block all other addresses.

IP 제한 패널에 CIDR 형식 주소 블록을 추가 해야 합니다.You'll need to add CIDR formatted blocks of addresses to the IP restrictions panel. API Management VIP와 같은 단일 주소를 추가 해야 하는 경우에는 xx. xx. xx/32 형식으로 추가 해야 합니다.When you need to add a single address such as the API Management VIP, you need to add it in the format xx.xx.xx.xx/32.

참고

이제 API management 나 사용자의 주소를 제외한 모든 위치에서 함수 API를 호출할 수 없습니다.Now your Function API should not be callable from anywhere other than via API management, or your address.

  1. API Management 블레이드 를 연 후 인스턴스 를 엽니다.Open the API Management blade, then open your instance.

  2. Api 블레이드 아래에서 Api 블레이드를 선택 합니다.Select the APIs Blade (under APIs).

  3. ' 새 API 추가 ' 창에서 ' 함수 앱 '를 선택한 다음 팝업 위쪽에서 ' 전체 '를 선택 합니다.From the 'Add a New API' pane, choose 'Function App', then select 'Full' from the top of the popup.

  4. 찾아보기를 클릭 하 고 내에서 API를 호스트 하는 함수 앱을 선택한 다음 선택을 클릭 합니다.Click Browse, choose the function app you're hosting the API inside, and click select. 다음으로, 선택을 다시 클릭 합니다.Next, click select again.

  5. API Management의 내부 사용에 대 한 이름 및 설명을 API에 제공 하 고 ' 제한 없음 ' 제품에 추가 합니다.Give the API a name and description for API Management's internal use and add it to the ‘unlimited’ Product.

  6. API의 ' 기본 URL '을 복사 하 고 기록 하 고 ' 만들기 '를 클릭 합니다.Copy and record the API's 'base URL' and click 'create'.

  7. 이 경우 Oauth JWT 토큰을 사용 하는 경우 ' 설정 ' 탭을 클릭 한 다음 구독-' 구독 필요 ' 확인란을 선택 취소 합니다.Click the 'settings' tab, then under subscription - switch off the 'Subscription Required' checkbox as we will use the Oauth JWT token in this case to rate limit. 소비 계층을 사용 하는 경우 프로덕션 환경에서 여전히 필요 합니다.Note that if you are using the consumption tier, this would still be required in a production environment.

    APIM의 소비 계층을 사용 하는 경우 무제한 제품을 기본 제공으로 사용할 수 없습니다.If using the consumption tier of APIM the unlimited product won't be available as an out of the box. 대신 "Api"의 "제품"으로 이동 하 고 "추가"를 누릅니다.Instead, navigate to "Products" under "APIs" and hit "Add".
    제품 이름 및 설명으로 "제한 없음"을 입력 하 고 화면 왼쪽 아래에 있는 "+" Api 설명선에서 방금 추가한 API를 선택 합니다.Type "Unlimited" as the product name and description and select the API you just added from the "+" APIs callout at the bottom left of the screen. "게시 됨" 확인란을 선택 합니다.Select the "published" checkbox. 나머지는 기본값으로 둡니다.Leave the rest as default. 마지막으로 "만들기" 단추를 누릅니다.Finally, hit the "create" button. 이렇게 하면 "제한 없음" 제품이 생성 되어 API에 할당 됩니다.This created the "unlimited" product and assigned it to your API. 나중에 새 제품을 사용자 지정할 수 있습니다.You can customize your new product later.

올바른 저장소 끝점 설정 구성 및 캡처Configure and capture the correct storage endpoint settings

  1. Azure Portal에서 storage 계정 블레이드를 엽니다.Open the storage accounts blade in the Azure portal

  2. 만든 계정을 선택 하 고 설정 섹션에서 ' 정적 웹 사이트 ' 블레이드를 선택 합니다. ' 정적 웹 사이트 ' 옵션이 표시 되지 않으면 V2 계정을 만들었는지 확인 합니다.Select the account you created and select the 'Static Website' blade from the Settings section (if you don't see a 'Static Website' option, check you created a V2 account).

  3. 정적 웹 호스팅 기능을 ' 사용 '으로 설정 하 고 인덱스 문서 이름을 ' index.html '로 설정한 후 ' 저장 '을 클릭 합니다.Set the static web hosting feature to 'enabled', and set the index document name to 'index.html', then click 'save'.

  4. 이 위치는 프런트 엔드 사이트가 호스팅될 위치 이므로 나중에 대해 ' 기본 끝점 '의 내용을 적어둡니다.Note down the contents of the 'Primary Endpoint' for later, as this location is where the frontend site will be hosted.

    Azure Blob Storage + CDN 재작성 또는 Azure App Service를 사용 하 여 SPA를 호스트할 수 있지만 Blob Storage의 정적 웹 사이트 호스팅 기능을 사용 하면 Azure Storage에서 정적 웹 콘텐츠/h t t p/s u p t/css를 제공 하는 기본 컨테이너를 제공 하 고, 0 작업에 대해 기본 페이지를 유추할 수 있습니다.You could use either Azure Blob Storage + CDN rewrite, or Azure App Service to host the SPA - but Blob Storage's Static Website hosting feature gives us a default container to serve static web content / html / js / css from Azure Storage and will infer a default page for us for zero work.

CORS 설정 및 jwt 정책 유효성 검사Set up the CORS and validate-jwt policies

사용 중인 APIM 계층에 관계 없이 다음 섹션을 따라야 합니다.The following sections should be followed regardless of the APIM tier being used. 저장소 계정 URL은이 문서의 맨 위에 있는 전제 조건에서 사용할 수 있도록 저장소 계정에서 제공 됩니다.The storage account URL is from the storage account you will have made available from the prerequisites at the top of this article.

  1. 포털의 API management 블레이드로 전환 하 고 인스턴스를 엽니다.Switch to the API management blade of the portal and open your instance.

  2. Api를 선택한 다음 "모든 Api"를 선택 합니다.Select APIs, then select “All APIs”.

  3. "인바운드 처리"에서 코드 보기 단추 "</>"를 클릭 하 여 정책 편집기를 표시 합니다.Under "Inbound processing", click the code view button "</>" to show the policy editor.

  4. 인바운드 섹션을 편집 하 고 다음과 같이 읽도록 xml을 붙여넣습니다.Edit the inbound section and paste the below xml so it reads like the following.

  5. 정책에서 다음 매개 변수를 바꿉니다.Replace the following parameters in the Policy

  6. {PrimaryStorageEndpoint} (이전 섹션에서 복사한 ' 기본 저장소 끝점 '), {b2cpolicy-openid connect} (이전에 복사한 ' 잘 알려진 openid connect 구성 끝점 ') 및 {} ( 백 엔드 api 에 대 한 B2C 응용 프로그램/클라이언트 id)를 사용 하 여 이전에 저장 한 올바른 값이 있습니다.{PrimaryStorageEndpoint} (The 'Primary Storage Endpoint' you copied in the previous section), {b2cpolicy-well-known-openid} (The 'well-known openid configuration endpoint' you copied earlier) and {backend-api-application-client-id} (The B2C Application / Client ID for the backend API) with the correct values saved earlier.

  7. API Management의 소비 계층을 사용 하는 경우 Azure API Management의 소비 계층을 사용 하는 경우이 정책을 사용할 수 없으므로 rate limit key 정책을 모두 제거 해야 합니다.If you're using the Consumption tier of API Management, then you should remove both rate-limit-by-key policy as this policy is not available when using the Consumption tier of Azure API Management.

    <inbound>
       <cors allow-credentials="true">
             <allowed-origins>
                 <origin>{PrimaryStorageEndpoint}</origin>
             </allowed-origins>
             <allowed-methods preflight-result-max-age="120">
                 <method>GET</method>
             </allowed-methods>
             <allowed-headers>
                 <header>*</header>
             </allowed-headers>
             <expose-headers>
                 <header>*</header>
             </expose-headers>
         </cors>
       <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid." require-expiration-time="true" require-signed-tokens="true" clock-skew="300">
          <openid-config url="{b2cpolicy-well-known-openid}" />
          <required-claims>
             <claim name="aud">
                <value>{backend-api-application-client-id}</value>
             </claim>
          </required-claims>
       </validate-jwt>
       <rate-limit-by-key calls="300" renewal-period="120" counter-key="@(context.Request.IpAddress)" />
       <rate-limit-by-key calls="15" renewal-period="60" counter-key="@(context.Request.Headers.GetValueOrDefault("Authorization","").AsJwt()?.Subject)" />
    </inbound>
    

    참고

    이제 Azure API management는 JavaScript SPA 앱의 원본 간 요청에 응답할 수 있으며, 요청을 함수 API로 전달 하기 전에 전달 되는 JWT 인증 토큰의 제한, 요율 제한 및 사전 유효성 검사를 수행 합니다.Now Azure API management is able respond to cross origin requests from your JavaScript SPA apps, and it will perform throttling, rate-limiting and pre-validation of the JWT auth token being passed BEFORE forwarding the request on to the Function API.

    축 하 합니다. 이제 Azure AD B2C API Management 하 고 함께 작업 하 여 API를 게시, 보호 및 사용할 Azure Functions 있습니다.Congratulations, you now have Azure AD B2C, API Management and Azure Functions working together to publish, secure AND consume an API!

    API Management 소비 계층을 사용 하는 경우 JWT 주체 또는 들어오는 IP 주소 (현재 "소비" 계층에 대 한 키 정책에의 한 호출 율 제한)에의 한 요금 제한 대신 통화 요금 할당량으로 제한할 수 있습니다. 여기를 참조 하십시오.If you're using the API Management consumption tier then instead of rate limiting by the JWT subject or incoming IP Address (Limit call rate by key policy is not supported today for the "Consumption" tier), you can Limit by call rate quota see here.
    이 예제에서는 JavaScript 단일 페이지 응용 프로그램 이기 때문에 API Management 키를 사용 하 여 요금 제한 및 청구 호출에만 사용 합니다.As this example is a JavaScript Single Page Application, we use the API Management Key only for rate-limiting and billing calls. 실제 권한 부여 및 인증은 Azure AD B2C에 의해 처리 되 고 JWT에 캡슐화 되며, API Management에 의해 한 번, 그 다음에 백 엔드 Azure 함수에서 유효성을 두 번 확인 합니다.The actual Authorization and Authentication is handled by Azure AD B2C, and is encapsulated in the JWT, which gets validated twice, once by API Management, and then by the backend Azure Function.

정적 저장소에 JavaScript SPA 샘플 업로드Upload the JavaScript SPA sample to static storage

  1. 저장소 계정 블레이드의 Blob Service 섹션에서 ' 컨테이너 ' 블레이드를 선택 하 고 오른쪽 창에 표시 되는 $web 컨테이너를 클릭 합니다.Still in the storage account blade, select the 'Containers' blade from the Blob Service section and click on the $web container that appears in the right-hand pane.

  2. 아래 코드를 컴퓨터에서 로컬로 파일에 index.html로 저장 한 다음, index.html 파일을 $web 컨테이너에 업로드 합니다.Save the code below to a file locally on your machine as index.html and then upload the file index.html to the $web container.

     <!doctype html>
     <html lang="en">
     <head>
          <meta charset="utf-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1">
          <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
          <script type="text/javascript" src="https://alcdn.msauth.net/browser/2.11.1/js/msal-browser.min.js"></script>
     </head>
     <body>
          <div class="container-fluid">
              <div class="row">
                  <div class="col-md-12">
                     <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
                         <div class="container-fluid">
                             <a class="navbar-brand" href="#">Azure Active Directory B2C with Azure API Management</a>
                             <div class="navbar-nav">
                                 <button class="btn btn-success" id="signinbtn"  onClick="login()">Sign In</a>
                             </div>
                         </div>
                     </nav>
                  </div>
              </div>
              <div class="row">
                  <div class="col-md-12">
                      <div class="card" >
                         <div id="cardheader" class="card-header">
                             <div class="card-text"id="message">Please sign in to continue</div>
                         </div>
                         <div class="card-body">
                             <button class="btn btn-warning" id="callapibtn" onClick="getAPIData()">Call API</a>
                             <div id="progress" class="spinner-border" role="status">
                                 <span class="visually-hidden">Loading...</span>
                             </div>
                         </div>
                      </div>
                  </div>
              </div>
          </div>
          <script lang="javascript">
                 // Just change the values in this config object ONLY.
                 var config = {
                     msal: {
                         auth: {
                             clientId: "{CLIENTID}", // This is the client ID of your FRONTEND application that you registered with the SPA type in AAD B2C
                             authority:  "{YOURAUTHORITYB2C}", // Formatted as https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantguid or full tenant name including onmicrosoft.com}/{signuporinpolicyname}
                             redirectUri: "{StoragePrimaryEndpoint}", // The storage hosting address of the SPA, a web-enabled v2 storage account - recorded earlier as the Primary Endpoint.
                             knownAuthorities: ["{B2CTENANTDOMAIN}"] // {b2ctenantname}.b2clogin.com
                         },
                         cache: {
                             cacheLocation: "sessionStorage",
                             storeAuthStateInCookie: false 
                         }
                     },
                     api: {
                         scopes: ["{BACKENDAPISCOPE}"], // The scope that we request for the API from B2C, this should be the backend API scope, with the full URI.
                         backend: "{APIBASEURL}/hello" // The location that we will call for the backend api, this should be hosted in API Management, suffixed with the name of the API operation (in the sample this is '/hello').
                     }
                 }
                 document.getElementById("callapibtn").hidden = true;
                 document.getElementById("progress").hidden = true;
                 const myMSALObj = new msal.PublicClientApplication(config.msal);
                 myMSALObj.handleRedirectPromise().then((tokenResponse) => {
                     if(tokenResponse !== null){
                         console.log(tokenResponse.account);
                         document.getElementById("message").innerHTML = "Welcome, " + tokenResponse.account.name;
                         document.getElementById("signinbtn").hidden = true;
                         document.getElementById("callapibtn").hidden = false;
                     }}).catch((error) => {console.log("Error Signing in:" + error);
                 });
                 function login() {
                     try {
                         myMSALObj.loginRedirect({scopes: config.api.scopes});
                     } catch (err) {console.log(err);}
                 }
                 function getAPIData() {
                     document.getElementById("progress").hidden = false; 
                     document.getElementById("message").innerHTML = "Calling backend ... "
                     document.getElementById("cardheader").classList.remove('bg-success','bg-warning','bg-danger');
                     myMSALObj.acquireTokenSilent({scopes: config.api.scopes, account: getAccount()}).then(tokenResponse => {
                         const headers = new Headers();
                         headers.append("Authorization", `Bearer ${tokenResponse.accessToken}`);
                         fetch(config.api.backend, {method: "GET", headers: headers})
                             .then(async (response)  => {
                                 if (!response.ok)
                                 {
                                     document.getElementById("message").innerHTML = "Error: " + response.status + " " + JSON.parse(await response.text()).message;
                                     document.getElementById("cardheader").classList.add('bg-warning');
                                 }
                                 else
                                 {
                                     document.getElementById("cardheader").classList.add('bg-success');
                                     document.getElementById("message").innerHTML = await response.text();
                                 }
                                 }).catch(async (error) => {
                                     document.getElementById("cardheader").classList.add('bg-danger');
                                     document.getElementById("message").innerHTML = "Error: " + error;
                                 });
                     }).catch(error => {console.log("Error Acquiring Token Silently: " + error);
                         return myMSALObj.acquireTokenRedirect({scopes: config.api.scopes, forceRefresh: false})
                     });
                     document.getElementById("progress").hidden = true;
              }
             function getAccount() {
                 var accounts = myMSALObj.getAllAccounts();
                 if (!accounts || accounts.length === 0) {
                     return null;
                 } else {
                     return accounts[0];
                 }
             }
         </script>
      </body>
     </html>
    
  3. 마지막 섹션에서 이전에 저장 한 정적 웹 사이트 기본 끝점으로 이동 합니다.Browse to the Static Website Primary Endpoint you stored earlier in the last section.

    참고

    축 하 합니다. 정적 콘텐츠 호스팅을 Azure Storage 하는 JavaScript 단일 페이지 앱을 배포 했습니다.Congratulations, you just deployed a JavaScript Single Page App to Azure Storage Static content hosting.
    Azure AD B2C 세부 정보를 사용 하 여 JS 앱을 아직 구성 하지 않았기 때문에 페이지를 열 때 페이지가 아직 작동 하지 않습니다.Since we haven’t configured the JS app with your Azure AD B2C details yet – the page won't work yet if you open it.

Azure AD B2C에 대 한 JavaScript SPA 구성Configure the JavaScript SPA for Azure AD B2C

  1. 이제 모든 것이 무엇 인지 알 수 있습니다. 적절 한 API Management API 주소 및 올바른 Azure AD B2C 응용 프로그램/클라이언트 Id로 SPA를 구성할 수 있습니다.Now we know where everything is: we can configure the SPA with the appropriate API Management API address and the correct Azure AD B2C application / client IDs.
  2. Azure Portal 저장소 블레이드로 돌아가기Go back to the Azure portal storage blade
  3. ' 설정 ' 아래에서 ' 컨테이너 '를 선택 합니다.Select 'Containers' (under 'Settings')
  4. 목록에서 ' $web ' 컨테이너를 선택 합니다.Select the '$web' container from the list
  5. 목록에서 index.html blob을 선택 합니다.Select index.html blob from the list
  6. ' 편집 '을 클릭 합니다.Click 'Edit'
  7. 이전에 B2C에 등록 한 프런트 엔드 응용 프로그램과 일치 하도록 msal 구성 섹션의 인증 값을 업데이트 합니다.Update the auth values in the msal config section to match your front-end application you registered in B2C earlier. 구성 값을 확인 하는 방법에 대 한 힌트는 코드 주석을 사용 합니다.Use the code comments for hints on how the config values should look. 권한 값은 다음 형식 이어야 합니다.-https://{b2ctenantname}. b2clogin/tfp/{b2ctenantname}. onmicrosoft}/{signupandsigninpolicyname}. 샘플 이름을 사용 하 고 테 넌 트가 ' contoso ' 라고 하면 권한이 ' '이 됩니다. https://contoso.b2clogin.com/tfp/contoso.onmicrosoft.com}/Frontendapp_signupandsigninThe authority value needs to be in the format:- https://{b2ctenantname}.b2clogin.com/tfp/{b2ctenantname}.onmicrosoft.com}/{signupandsigninpolicyname}, if you have used our sample names and your b2c tenant is called 'contoso' then you would expect the authority to be 'https://contoso.b2clogin.com/tfp/contoso.onmicrosoft.com}/Frontendapp_signupandsignin'.
  8. 백 엔드 주소와 일치 하도록 api 값을 설정 합니다 (앞에서 기록한 API 기본 Url 및 백 엔드 응용 프로그램 에 대해 ' b2cScopes ' 값이 이전에 기록 됨).Set the api values to match your backend address (The API Base Url you recorded earlier, and the 'b2cScopes' values were recorded earlier for the backend application).
  9. 저장을 클릭합니다.Click Save

Azure AD B2C 프런트 엔드 앱에 대 한 리디렉션 Uri 설정Set the redirect URIs for the Azure AD B2C frontend app

  1. Azure AD B2C 블레이드를 열고 JavaScript 프런트 엔드 응용 프로그램에 대 한 응용 프로그램 등록으로 이동 합니다.Open the Azure AD B2C blade and navigate to the application registration for the JavaScript Frontend Application.

  2. ' 리디렉션 Uri '를 클릭 하 고 앞에서 입력 한 자리 표시자 ' '를 삭제 https://jwt.ms 합니다.Click 'Redirect URIs' and delete the placeholder 'https://jwt.ms' we entered earlier.

  3. 기본 (저장소) 끝점에 대 한 새 URI를 추가 합니다 (후행 슬래시 제외).Add a new URI for the primary (storage) endpoint (minus the trailing forward slash).

    참고

    이 구성을 사용 하면 프런트 엔드 응용 프로그램 클라이언트가 Azure AD B2C의 적절 한 클레임으로 액세스 토큰을 받습니다.This configuration will result in a client of the frontend application receiving an access token with appropriate claims from Azure AD B2C.
    SPA는 백엔드 API 호출에서이를 https 헤더에 전달자 토큰으로 추가할 수 있습니다.The SPA will be able to add this as a bearer token in the https header in the call to the backend API.

    API Management는 토큰의 유효성을 검사 하 고, Azure ID (사용자)에서 발급 한 JWT의 주체와 호출자의 IP 주소 (API Management의 서비스 계층에 따라)를 사용 하 여 끝점에 대 한 호출의 유효성을 검사 합니다. 요청을 통해 수신 되는 Azure Function API에 전달 하기 전에 함수 보안 키를 추가 합니다.API Management will pre-validate the token, rate-limit calls to the endpoint by both the subject of the JWT issued by Azure ID (the user) and by IP address of the caller (depending on the service tier of API Management, see the note above), before passing through the request to the receiving Azure Function API, adding the functions security key.
    SPA는 브라우저에서 응답을 렌더링 합니다.The SPA will render the response in the browser.

    축 하 합니다. 완벽 한 조화에서 작동 하도록 Azure AD B2C, Azure API Management, Azure Functions, Azure App Service 권한 부여를 구성 했습니다.Congratulations, you’ve configured Azure AD B2C, Azure API Management, Azure Functions, Azure App Service Authorization to work in perfect harmony!

이제 간단한 보안 API를 사용 하 여 간단한 앱을 만들어 테스트 해 보겠습니다.Now we have a simple app with a simple secured API, let's test it.

클라이언트 응용 프로그램 테스트Test the client application

  1. 이전에 만든 저장소 계정에서 적어 둔 샘플 앱 URL을 엽니다.Open the sample app URL that you noted down from the storage account you created earlier.
  2. 오른쪽 위 모서리에서 "로그인"을 클릭 하면 Azure AD B2C 등록 또는 로그인 프로필을 팝업 합니다.Click “Sign In” in the top-right-hand corner, this click will pop up your Azure AD B2C sign up or sign in profile.
  3. 앱은 B2C 프로필 이름으로 시작 해야 합니다.The app should welcome you by your B2C profile name.
  4. 이제 "API 호출"을 클릭 하면 해당 페이지는 보안 API에서 다시 전송 된 값으로 업데이트 됩니다.Now Click "Call API" and the page should update with the values sent back from your secured API.
  5. API 호출 단추를 반복적 으로 클릭 하 고 API Management 개발자 계층 이상에서 실행 하는 경우, 솔루션은 api를 제한 하기 시작 하 고이 기능은 적절 한 메시지와 함께 앱에 보고 되어야 합니다.If you repeatedly click the Call API button and you're running in the developer tier or above of API Management, you should note that your solution will begin to rate limit the API and this feature should be reported in the app with an appropriate message.

완료 되었습니다.And we're done

위의 단계를 조정 하 고 편집 하 여 API Management와 Azure AD B2C를 다양 하 게 사용할 수 있습니다.The steps above can be adapted and edited to allow many different uses of Azure AD B2C with API Management.

다음 단계Next steps