봇에 Single Sign-On 추가Add single sign on to a bot

적용 대상: SDK v4APPLIES TO: SDK v4

이 문서에서는 봇에서 SSO(Single Sign-On) 기능을 사용하는 방법을 보여 줍니다.This article shows how to use the Single sign on (SSO) feature in a bot. 이렇게 하려면 ‘루트 봇’이라고도 하는 ‘소비자’ 봇을 사용하여 ‘스킬’ 봇과 상호 작용합니다. To do so, it uses a consumer bot, also known as root bot, to interact with a skill bot.

사용자가 루트 봇에 로그인하면 루트 봇을 통해 사용할 수 있는 각 스킬 봇에 로그인할 필요가 없습니다.Once the users sign in the root bot, they are not required to sign into each skill bot they might use through the root bot. 이는 SSO 때문입니다.This is because of SSO. SSO가 없다면 사용자는 다른 스킬 봇과 통신할 때마다 로그인해야 합니다.Without it the users would have to sign in every time they communicate with a different skill bot.

참고

‘소비자’ 봇은 ‘루트’ 또는 ‘부모’ 봇이라고도 합니다. The consumer bot is also called root or parent bot. ‘스킬 봇’을 ‘자식 봇’이라고도 합니다.\ The skill bot is also called child bot.</span> 이 문서에서는 루트 봇 및 스킬 봇이라는 용어를 사용합니다.This article uses the terms root bot and skill bot.
스킬을 사용하여 루트와 스킬은 각기 다를 수 있는 서버에서 실행되는 별도의 봇이며 별도의 자체 메모리와 상태를 가집니다.With skills, the root and skill are separate bots, running on potentially different servers, each with its own separate memory and state.

웹 채팅 및 Direct Line 고려 사항Web Chat and Direct Line considerations

중요

웹 채팅에서 Azure Bot Service 인증을 사용하는 경우 주의해야 하는 몇 가지 중요한 보안 고려 사항이 있습니다.When you use Azure Bot Service authentication with Web Chat there are some important security considerations you must keep in mind. 자세한 내용은 REST 인증 문서의 보안 고려 사항 섹션을 참조하세요.For more information, see the security considerations section in the REST authentication article.

사전 요구 사항Prerequisites

샘플Sample BotBuilder 버전BotBuilder version 데모Demonstrates
CSharp에서 간단한 스킬 컨슈머 및 스킬에 사용하는 SSOSSO with Simple Skill Consumer and Skill in CSharp v4v4 SSO 지원SSO support

예제 정보About the samples

이 문서에서는 RootBotSkillBot 의 두 가지 샘플을 참조합니다.This article references two samples: the RootBot and the SkillBot. RootBotSkillBot 에 활동을 전달합니다.The RootBot forwards activities to the SkillBot. 다음과 같은 ‘일반적인’ 스킬 시나리오를 모델링합니다.They model this typical skill scenario:

  • ‘루트’ 봇은 하나 이상의 스킬 봇을 호출합니다.A root bot calls one or more skill bots.
  • 루트 및 스킬 봇은 모두 봇에 인증 추가 문서에 설명된 기본 인증을 구현합니다.Both the root and skill bots implement the basic authentication described in the Add authentication to a bot article.
  • 사용자가 루트 봇에 로그인합니다.The user logs into root bot.
  • SSO로 인해 루트 봇에 이미 로그인되어 있으므로 사용자 조작 없이 스킬 봇에 로그인됩니다.Because of the SSO and being already logged into the root bot, she is logged into the skill bot without requiring user interaction again.

Bot Framework에서 인증을 처리 하는 방법에 대 한 개요는 사용자 인증을 참조 하세요.For an overview of how the Bot Framework handles authentication, see User authentication. SSO 배경 정보는 Single Sign-On을 참조하세요.For SSO background information, see Single sign on.

RootBot 은 사용자의 SSO를 지원합니다.The RootBot supports user's SSO. 사용자를 대신하여 SkillBot 과 통신하므로 사용자는 SkillBot 에 다시 인증할 필요가 없습니다.It communicates with the SkillBot on behalf of the user, without the user being required to authenticate again into the SkillBot.

샘플의 각 프로젝트에 대해 다음이 필요합니다.For each project in the sample, you need the following:

  1. Azure에서 봇 리소스를 등록하기 위한 Azure AD 애플리케이션An Azure AD application to register a bot resource in Azure.
  2. 인증을 위한 Azure AD ID 공급자 애플리케이션An Azure AD identity provider application for authentication.

    참고

    현재 Azure AD v2 ID 공급자만 지원됩니다.Currently, only the Azure AD v2 identity provider is supported.

Azure RootBot 리소스 만들기Create the Azure RootBot resource

  1. 에 대 한 Azure Portal 에 Azure bot 리소스를 만듭니다 RootBot .Create an Azure bot resource in the Azure portal for the RootBot. Azure bot 리소스 만들기에 설명 된 단계를 따릅니다.Follow the steps described in Create an Azure bot resource.
  2. 봇 등록 앱 ID클라이언트 암호 를 복사하여 저장합니다.Copy and save the bot registration app ID and the client secret.

RootBot용 Azure AD ID 만들기Create the Azure AD identity for RootBot

Azure AD는 OAuth2.0과 같은 업계 표준 프로토콜을 사용하여 사용자가 안전하게 로그인하는 애플리케이션을 빌드할 수 있는 클라우드 ID 서비스입니다.The Azure AD is a cloud identity service that allows you to build applications that securely sign in users using industry standard protocols like OAuth2.0.

  1. Azure AD v2를 사용하여 사용자를 인증하는 RootBot용 ID 애플리케이션을 만듭니다.Create an identity application for the RootBot that uses Azure AD v2 to authenticate the user. AZURE AD id 공급자 만들기에 설명 된 단계를 따릅니다.Follow the steps described in Create the Azure AD identity provider.

  2. 왼쪽 창에서 매니페스트 를 클릭합니다.In the left pane, click Manifest.

  3. accessTokenAcceptedVersion을 2로 설정합니다.Set accessTokenAcceptedVersion to 2.

  4. 저장 을 클릭합니다.Click Save.

  5. 왼쪽 창에서 API 노출 을 클릭합니다.In the left pane, click Expose an API.

  6. 오른쪽 창에서 + 일정 추가 를 클릭합니다.In the right pane, click Add a scope.

  7. 맨 오른쪽에 있는 ‘범위 추가’ 섹션에서 저장하고 계속 을 클릭합니다.In the far right Add a scope section click Save and continue.

  8. 표시된 창에서 동의할 수 있는 ‘동의할 수 있는 사람’에서 관리자 및 사용자 를 선택합니다.In the displayed window, under Who can consent? select Admins and users.

  9. 나머지 필수 정보를 입력합니다.Enter the remaining required information.

  10. 범위 추가 를 클릭합니다.Click Add scope.

  11. 범위 값을 복사하여 저장합니다.Copy and save the scope value.

OAuth 연결 설정 만들기Create an OAuth connection settings

  1. RootBot 봇 등록에서 Azure AD v2 연결을 만들고 Azure AD v2에 설명된 값 및 아래 설명된 값을 입력합니다.Create an Azure AD v2 connection in the RootBot bot registration and enter values as described in Azure AD v2 and the value described below.

  2. 토큰 교환 URL 은 비워 둡니다.Leave the Token Exchange URL empty.

  3. 범위 상자에 이전 단계에서 저장한 RootBot 범위 값을 입력합니다.In the Scopes box enter the RootBot scope value you saved in the previous steps.

  4. 연결 이름을 복사하고 저장합니다.Copy and save the name of the connection.

Azure SkillBot 리소스 만들기Create the Azure SkillBot resource

  1. 에 대 한 Azure Portal 에 Azure bot 리소스를 만듭니다 SkillBot .Create an Azure bot resource in the Azure portal for the SkillBot. Azure bot 리소스 만들기에 설명 된 단계를 따릅니다.Follow the steps described in Create an Azure bot resource.
  2. 봇 등록 앱 ID클라이언트 암호 를 복사하여 저장합니다.Copy and save the bot registration app ID and the client secret.

SkillBot용 Azure AD ID 만들기Create the Azure AD identity for SkillBot

Azure AD는 OAuth2.0과 같은 업계 표준 프로토콜을 사용하여 사용자가 안전하게 로그인하는 애플리케이션을 빌드할 수 있는 클라우드 ID 서비스입니다.The Azure AD is a cloud identity service that allows you to build applications that securely sign in users using industry standard protocols like OAuth2.0.

  1. Azure AD v2를 사용하여 봇을 인증하는 SkillBot용 ID 애플리케이션을 만듭니다.Create an identity application for the SkillBot that uses Azure AD v2 to authenticate the bot. AZURE AD id 공급자 만들기에 설명 된 단계를 따릅니다.Follow the steps described in Create the Azure AD identity provider.

  2. 왼쪽 창에서 매니페스트 를 클릭합니다.In the left pane, click Manifest.

  3. accessTokenAcceptedVersion을 2로 설정합니다.Set accessTokenAcceptedVersion to 2.

  4. 저장 을 클릭합니다.Click Save.

  5. 왼쪽 창에서 API 노출 을 클릭합니다.In the left pane, click Expose an API.

  6. 오른쪽 창에서 + 일정 추가 를 클릭합니다.In the right pane, click Add a scope.

  7. 맨 오른쪽에 있는 ‘범위 추가’ 섹션에서 저장하고 계속 을 클릭합니다.In the far right Add a scope section click Save and continue.

  8. 표시된 창에서 동의할 수 있는 ‘동의할 수 있는 사람’에서 관리자 및 사용자 를 선택합니다.In the displayed window, under Who can consent? select Admins and users.

  9. 나머지 필수 정보를 입력합니다.Enter the remaining required information.

  10. 범위 추가 를 클릭합니다.Click Add scope.

  11. 범위 값을 복사하여 저장합니다.Copy and save the scope value.

  12. 클라이언트 애플리케이션 추가 를 클릭합니다.Click Add a client application. 맨 오른쪽 섹션의 클라이언트 ID 상자에 이전에 저장한 RootBot ID 앱 ID를 입력합니다.In the far right section, in the Client ID box, enter the RootBot identity app ID you saved before. 등록 앱 ID가 아닌 RootBot ID를 사용해야 합니다.Make sure you use the RootBot identity and not the registration app ID.

  13. 승인된 범위 에서 범위 값에 따라 확인란을 선택합니다.Under Authorized scope, check the box by the scope value.

  14. 애플리케이션 추가 를 클릭합니다.Click Add application.

  15. 왼쪽의 탐색 창에서 API 사용 권한 을 클릭합니다.In the navigation pane on the left, click API permissions. 앱의 API 사용 권한을 명시적으로 설정하는 것이 좋습니다.It is a best practice to explicitly set the API permissions for the app.

    1. 오른쪽 창에서 사용 권한 추가 를 클릭합니다.In the right pane, click Add a permission.

    2. Microsoft APIMicrosoft Graph 를 차례로 선택합니다.Select Microsoft APIs then Microsoft Graph.

    3. 위임된 권한 을 선택하고 필요한 사용 권한이 선택되어 있는지 확인합니다.Choose Delegated permissions and make sure the permissions you need are selected. 이 샘플에는 다음에 나열된 사용 권한이 필요합니다.This sample requires the permissions listed below.

      참고

      관리자 동의가 필요함 으로 표시된 모든 사용 권한에는 사용자와 테넌트 관리자가 모두 로그인되어 있어야 합니다.Any permission marked as ADMIN CONSENT REQUIRED will require both a user and a tenant admin to login.

      • openidopenid
      • profileprofile
      • User.ReadUser.Read
      • User.ReadBasic.AllUser.ReadBasic.All
    4. 권한 추가 를 클릭합니다.Click Add permissions.

OAuth 연결 설정 만들기Create an OAuth connection settings

  1. SkillBot 봇 등록에서 Azure AD v2 연결을 만들고 Azure AD v2에 설명된 값 및 아래 설명된 값을 입력합니다.Create an Azure AD v2 connection in the SkillBot bot registration and enter values as described in Azure AD v2 and the values described below.

  2. 토큰 교환 URL 상자에 이전 단계에서 저장한 SkillBot 범위 값을 입력합니다.In the Token Exchange URL box enter the SkillBot scope value you saved in the previous steps.

  3. 범위 상자에서 빈 공백으로 구분하여 다음 값을 입력합니다. profile User.Read User.ReadBasic.All openid.In the Scopes box enter the following values separated by blank space: profile User.Read User.ReadBasic.All openid.

  4. 연결 이름을 복사하고 파일에 저장합니다.Copy and save to a file the name of the connection.

연결 테스트Test the connection

  1. 연결 항목을 클릭하여 방금 만든 연결을 엽니다.Click on the connection entry to open the connection you just created.
  2. 서비스 공급자 연결 설정 창의 맨 위에 있는 연결 테스트 를 클릭합니다.Click Test Connection at the top of the Service Provider Connection Setting pane.
  3. 처음에 앱에서 요청하는 사용 권한을 나열하는 새 브라우저 탭을 열고 수락하라는 메시지를 표시해야 합니다.The first time, this should open a new browser tab listing the permissions your app is requesting and prompt you to accept.
  4. Accept 를 클릭합니다.Click Accept.
  5. 그러면 <your-connection-name>에 대한 연결 테스트가 성공했습니다 페이지로 리디렉션됩니다.This should then redirect you to a Test Connection to <your-connection-name> Succeeded page.

자세한 내용은 개발자용 Azure Active Directory(v1.0) 개요Microsoft IDentity platform(v2.0) 개요를 참조하세요.For more information, see the Azure Active Directory for developers (v1.0) overview and Microsoft identity platform (v2.0) overview. v1 및 v2 엔드포인트의 차이점에 대한 자세한 내용은 Microsoft ID 플랫폼(v2.0)으로 업데이트하는 이유를 참조하세요.For information about the differences between the v1 and v2 endpoints, see Why update to Microsoft identity platform (v2.0)?. 전체 내용은 Microsoft ID 플랫폼(이전의 개발자용 Azure Active Directory)을 참조하세요.For complete information, see Microsoft identity platform (formerly Azure Active Directory for developers).

샘플 코드 준비Prepare the samples code

아래에서 설명하는 두 샘플에서 appsettings.json 파일을 업데이트해야 합니다.You must update the appsettings.json file in both samples as described below.

  1. GitHub 리포지토리에서 간단한 스킬 컨슈머 및 스킬의 SSO 샘플을 복제합니다.From the GitHub repository clone the sample SSO with Simple Skill Consumer and Skill

  2. SkillBot프로젝트 appsettings.json 파일을 엽니다.Open the SkillBot project appsettings.json file. 저장된 파일에서 다음 값을 할당합니다.From the saved file, assign the following values:

    {
        "MicrosoftAppId": "<SkillBot registration app ID>",
        "MicrosoftAppPassword": "<SkillBot registration password>",
        "ConnectionName": "<SkillBot connection name>",
        "AllowedCallers": [ "<RootBot registration app ID>" ]
    }
    
    
  3. Open the RootBot project appsettings.json file. From the saved file, assign the following values:

    {
        "MicrosoftAppId": "<RootBot registration app ID>",
        "MicrosoftAppPassword": "<RootBot registration password>",
        "ConnectionName": "<RootBot connection name>",
        "SkillHostEndpoint": "http://localhost:3978/api/skills/",
        "BotFrameworkSkills": [
                {
                "Id": "SkillBot",
                "AppId": "<SkillBot registration app ID>",
                "SkillEndpoint": "http://localhost:39783/api/messages"
                }
            ]
    }
    

샘플 테스트Test the samples

테스트에는 다음을 사용합니다.Use the following for testing:

  • RootBot 명령RootBot commands

    • login으로 사용자가 RootBot를 사용하여 Azure AD 등록에 로그인할 수 있습니다.login allows the user to sign into the Azure AD registration using the RootBot. 로그인되면 SSO가 SkillBot 로그인도 처리합니다.Once signed in, SSO takes care of the sign in into the the SkillBot also. 사용자가 다시 로그인하지 않아도 됩니다.The user does not have to sign in again.
    • token은 사용자의 토큰을 표시합니다.token displays the user's token.
    • logoutRootBot에서 사용자를 로그아웃시킵니다.logout logs the user out of the RootBot.
  • SkillBot 명령SkillBot commands

    • skill login은 사용자를 대신하여 RootBotSkillBot에 로그인할 수 있도록 합니다.skill login allows the RootBot to sign into the SkillBot, on behalf of the user. SSO가 실패하지 않는 한, 이미 로그인되어 있는 경우 사용자에게 로그인 카드가 표시되지 않습니다.The user is not shown a sign in card, if already signed in, unless SSO fails.
    • skill tokenSkillBot에서 사용자의 토큰을 표시합니다.skill token displays the user's token from the SkillBot.
    • skill logoutSkillBot에서 사용자를 로그아웃시킵니다.skill logout logs the user out of the SkillBot

참고

사용자가 처음으로 스킬에서 SSO를 시도하면 로그인을 위한 OAuth 카드가 표시될 수 있습니다.The first time users try SSO on a skill, they may be presented with an OAuth card to log in. 스킬의 Azure AD 앱에 대한 동의가 아직 부여되지 않았기 때문입니다.This is because they have not yet given consent to the skill's Azure AD app. 이를 방지하기 위해 Azure AD 앱에서 요청하는 모든 그래프 사용 권한에 대해 관리자 동의를 부여할 수 있습니다.To avoid this, they can grant admin consent for any graph permissions requested by the Azure AD app.

에뮬레이터를 사용 하 여 테스트Test using the Emulator

아직 설치하지 않은 경우 Bot Framework Emulator를 설치합니다.If you have not done so already, install the Bot Framework Emulator. 또한 에뮬레이터를 사용 하 여 디버그를 참조 하세요.See also Debug with the Emulator.

봇 샘플 로그인이 작동 하려면 인증을 위해 에뮬레이터 구성에 표시 된 대로 에뮬레이터를 구성 해야 합니다.In order for the bot sample login to work you must configure the Emulator as shown in Configure the Emulator for authentication.

인증 메커니즘을 구성한 후 실제 봇 샘플 테스트를 수행할 수 있습니다.After you have configured the authentication mechanism, you can perform the actual bot sample testing.

  1. Visual Studio에서 SSOWithSkills.sln 솔루션을 열고 여러 프로세스로 디버깅을 시작하도록 구성합니다.In Visual Studio, open the SSOWithSkills.sln solution and configure it to start debugging with multiple processes.
  2. 컴퓨터에서 로컬로 디버깅을 시작합니다.Start debugging locally on your machine. RootBot 프로젝트 appsettings.json 파일에는 다음과 같은 설정이 있습니다.Notice that in theRootBot project appsettings.json file you have the following settings:
    "SkillHostEndpoint": "http://localhost:3978/api/skills/"
    "SkillEndpoint": "http://localhost:39783/api/messages"

참고

이러한 설정은 RootBotSkillBot 모두 로컬 컴퓨터에서 실행되는 것을 의미합니다.These settings imply that, with both RootBot and SkillBot are running on the local machine. 에뮬레이터는 RootBot 포트 3978에서와 통신 하 고 RootBot SkillBot 포트 39783에서와 통신 합니다.The Emulator communicates with RootBot on port 3978 and RootBot communicates with SkillBot on port 39783. 디버깅을 시작하는 즉시 두 개의 기본 브라우저 창이 열립니다.As soon as you start debugging, two default browser windows open. 하나는 포트 3978에 있고 다른 하나는 포트 39783에 있습니다.One on port 3978 and the other on port 39783.

  1. 에뮬레이터를 시작합니다.Start the Emulator.

  2. 봇에 연결할 때 RootBot 등록 앱 ID 및 암호를 제공해야 합니다.You need to provide your RootBot registration app ID and password when you connect to the bot.

  3. hi를 입력하여 대화를 시작합니다.Type hi to start the conversation.

  4. login 을 입력합니다.Enter login. RootBot에서 ‘AAD로 로그인’ 인증 카드가 표시됩니다.The RootBot will display a Sign In to AAD authentication card.

    루트 로그인

  5. 로그인 을 클릭합니다.Click Sign In. ‘URL 열기 확인’ 팝업 대화가 표시됩니다.The pop-up dialog Confirm Open URL is displayed.

    루트 확인 URL

  6. 확인 을 클릭합니다.Click Confirm. 로그인되고 RootBot 토큰이 표시됩니다.You will be logged in and the RootBot token is displayed.

  7. 토큰을 다시 표시하려면 token 을 입력합니다.Enter token to display the token again.

    루트 토큰 이미지

    이제 SkillBot과 통신할 준비가 되었습니다.Now you are ready to communicate with the SkillBot. RootBot을 사용하여 로그인하면 로그아웃할 때까지 자격 증명을 다시 제공할 필요가 없습니다. 이는 SSO가 작동하는 것을 보여 줍니다.Once you've signed using the RootBot, you don't need to provide your credentials again until you sign out. This demonstrates that SSO is working.

  8. 에뮬레이터 상자에 기술 로그인 을 입력 합니다.Enter skill login in the Emulator box. 다시 로그인하라는 메시지가 표시되지 않습니다.You will not be asked to login again. 대신 SkillBot 토큰이 표시됩니다.Instead the SkillBot token is displayed.

  9. 토큰을 다시 표시하려면 skill token 을 입력합니다.Go ahead enter skill token to display the token again.

    기술 토큰 이미지

  10. 이제 skill logout 을 입력하여 SkillBot에서 로그아웃할 수 있습니다.Now you can enter skill logout to sign out of the SkillBot. 그런 다음 logout 을 입력하여 SimpleRootBoot에서 로그아웃합니다.Then enter logout to sign out of the SimpleRootBoot.

추가 정보Additional information

다음 시간 시퀀스 다이어그램은 문서에서 사용된 샘플에 적용되며 관련된 다양한 구성 요소 간의 상호 작용을 보여 줍니다.The following time-sequence diagram applies to the samples used in the article and shows the interaction between the various components involved. ABSAzure Bot Service 를 나타냅니다.ABS stands for Azure Bot Service.

기술 토큰 흐름

  1. 처음인 사용자는 RootBot 에 대한 login 명령을 입력합니다.The first time, the user enters the login command for the RootBot.
  2. RootBot 은 사용자에게 로그인하도록 요청하는 OAuthCard 를 보냅니다.The RootBot sends an OAuthCard asking the user to sign in.
  3. 사용자는 ABS(Azure Bot Service)로 전송된 인증 자격 증명을 입력합니다.The user enters the authentication credentials that are sent to the ABS (Azure Bot Service).
  4. ABS 는 사용자의 자격 증명을 기반으로 생성된 인증 토큰을 RootBot 에 보냅니다.The ABS sends the authentication token, generated based on the user's credentials, to the RootBot.
  5. RootBot 은 사용자가 볼 수 있는 루트 토큰을 표시합니다.The RootBot displays the root token for the user to see.
  6. 사용자는 SkillBot 에 대한 skill login 명령을 입력합니다.The user enters the skill login command for the SkillBot.
  7. SkillBotOAuthCardRootBot 에 보냅니다.The SkillBot sends an OAuthCard to the RootBot.
  8. RootBotABS 에서 교환 가능한 토큰 을 요청합니다.The RootBot asks for an exchangeable token from ABS.
  9. 이 시점에서 SkillBot 에서 RootBot 으로 보낸 skill token 으로 끝나는 SSO “댄스”가 작동합니다.At this point the SSO "dance" comes into play which ends with the skill token sent by the SkillBot to the RootBot.
  10. RootBot 은 사용자가 볼 수 있는 스킬 토큰을 표시합니다.The RootBot displays the skill token for the user to see. 사용자가 SkillBot 에 로그인하지 않고 스킬 토큰이 생성된 것을 알 수 있습니다.Notice that the skill token was generated without the user having to sign in the SKillBot. 이는 SSO 때문입니다.This is because of the SSO.

토큰 교환이 어떻게 발생하는지 확인하려면 아래에 나와 있는 예제를 참조하세요.To see how the token exchange happens, please refer to the example shown below. 함수는 TokenExchangeSkillHandler.cs에서 찾을 수 있습니다.The function can be found in TokenExchangeSkillHandler.cs.

private async Task<bool> InterceptOAuthCards(ClaimsIdentity claimsIdentity, Activity activity)
{
    var oauthCardAttachment = activity.Attachments?.FirstOrDefault(a => a?.ContentType == OAuthCard.ContentType);
    if (oauthCardAttachment != null)
    {
        var targetSkill = GetCallingSkill(claimsIdentity);
        if (targetSkill != null)
        {
            var oauthCard = ((JObject)oauthCardAttachment.Content).ToObject<OAuthCard>();

            if (!string.IsNullOrWhiteSpace(oauthCard?.TokenExchangeResource?.Uri))
            {
                using (var context = new TurnContext(_adapter, activity))
                {
                    context.TurnState.Add<IIdentity>("BotIdentity", claimsIdentity);

                    // AAD token exchange
                    try
                    {
                        var result = await _tokenExchangeProvider.ExchangeTokenAsync(
                            context,
                            _connectionName,
                            activity.Recipient.Id,
                            new TokenExchangeRequest() { Uri = oauthCard.TokenExchangeResource.Uri }).ConfigureAwait(false);

                        if (!string.IsNullOrEmpty(result?.Token))
                        {
                            // If token above is null, then SSO has failed and hence we return false.
                            // If not, send an invoke to the skill with the token. 
                            return await SendTokenExchangeInvokeToSkill(activity, oauthCard.TokenExchangeResource.Id, result.Token, oauthCard.ConnectionName, targetSkill, default).ConfigureAwait(false);
                        }
                    }
                    catch
                    {
                        // Show oauth card if token exchange fails.
                        return false;
                    }

                    return false;
                }
            }
        }
    }
    return false;
}

추가 정보Further reading