이 문서의 내용
Copilot Studio는 SSO(Single Sign-On)를 지원합니다. SSO를 사용하면 웹사이트의 에이전트가 에이전트가 배포된 페이지나 앱에 이미 로그인한 고객을 등록할 수 있습니다.
예를 들어, 에이전트는 회사 인트라넷이나 사용자가 이미 로그인한 앱에 호스팅됩니다.
Copilot Studio용 SSO를 구성하기 위한 4 가지 주요 단계가 있습니다.
사용자 지정 캔버스에 대한 Microsoft Entra ID에서 앱 등록을 만듭니다.
에이전트에 대한 사용자 정의 범위를 정의하세요.
SSO를 활성화하려면 Copilot Studio에서 인증을 구성합니다.
SSO를 활성화하도록 사용자 지정 캔버스 HTML 코드를 구성합니다.
사전 요구 사항
지원 채널
다음 표는 현재 SSO를 지원하는 채널 에 대해 자세히 설명합니다. 추가 채널에 대한 지원을 제안하려면 아이디어 포럼 에서 Copilot Studio 제안하실 수 있습니다 .
1 Teams 채널도 활성화한 경우, 설명서의 에이전트 ID를 사용하여 단일 로그인 구성 에 있는 구성 지침을 따라와해야 합니다. Microsoft Entra Microsoft Teams 해당 페이지에 설명된 대로 Teams SSO 설정을 구성하지 못하면 사용자가 Teams 채널을 사용할 때 항상 인증에 실패하게 됩니다.
2 라이브 채팅 채널만 지원됩니다. 자세한 내용은 Dynamics 365 Customer Service로 핸드오프 구성 을 참조하십시오.
맞춤형 웹 사이트를 위한 앱 등록 생성
SSO를 사용하도록 설정하려면 두 개의 별도 앱 등록을 만들어야 합니다.
에이전트에 대한 ID 사용자 인증을 가능하게 하는 인증 앱 등록 Microsoft Entra
사용자 정의 웹 페이지에 대한 SSO를 활성화하는 캔버스 앱 등록 .
보안상의 이유로 에이전트와 사용자 지정 웹사이트에 동일한 앱 등록을 재사용하는 것은 권장하지 않습니다.
인증 앱 등록을 생성하려면 Microsoft Entra ID로 사용자 인증 구성 의 지침을 따르세요.
지침에 따라 인증 앱 등록을 다시 만들고, 캔버스 앱 등록으로 사용되는 두 번째 앱 등록을 만듭니다.
캔버스 앱 등록 ID를 인증 앱 등록에 추가합니다.
토큰 교환 URL 추가
Copilot Studio에서 Microsoft Entra ID 인증 설정을 업데이트하려면 앱과 Copilot Studio가 정보를 공유할 수 있도록 토큰 교환 URL을 추가해야 합니다.
인증 앱 등록 블레이드의 Azure Portal에서 API 노출 로 이동합니다.
범위 에서 클립보드에 복사 아이콘을 선택합니다.
Copilot Studio의 탐색 메뉴에서 설정 아래의 보안 을 선택한 다음 인증 타일을 선택합니다.
토큰 교환 URL(SSO에 필요) 에 앞서 복사한 범위를 붙여넣습니다.
저장 을 선택합니다.
캔버스 앱 등록을 생성한 후 인증 으로 이동한 다음 플랫폼 추가 를 선택합니다.
플랫폼 구성 에서 플랫폼 추가 를 선택한 후 Web 을 선택합니다.
리디렉션 URI 아래에 웹 페이지의 URL을 입력합니다(예: http://contoso.com/index.html
).
암시적 권한 부여 및 하이브리드 흐름 섹션에서 액세스 토큰(암시적 흐름에 사용됨) 과 ID 토큰(암시적 및 하이브리드 흐름에 사용됨) 을 모두 켭니다.
구성 을 선택합니다.
에이전트의 토큰 끝점 URL을 찾으세요
Copilot Studio에서 에이전트를 열고 채널 을 선택하세요.
모바일 앱 을 선택합니다.
토큰 엔드포인트 에 있는 복사 를 선택합니다.
웹 페이지에서 SSO 구성
Copilot Studio GitHub 리포지토리 에 제공된 코드를 사용하여 리디렉션 URL에 대한 웹 페이지를 만들 수 있습니다. GitHub 리포지토리에서 코드를 복사하고 다음 지침에 따라 수정합니다.
참고
GitHub 리포지토리의 코드는 사용자가 로그인 버튼을 선택하거나 다른 사이트에서 로그인해야 합니다. 자동 로그인을 활성화하려면 aysnc function main()
의 시작 부분에 다음 코드를 추가하세요.
(async function main() {
if (clientApplication.getAccount() == null) {
await clientApplication.loginPopup(requestObj).then(onSignin).catch(function (error) {console.log(error) });
}
// Add your BOT ID below
var theURL =
Azure Portal의 개요 페이지로 이동하고 캔버스 앱 등록에서 애플리케이션(클라이언트) ID 및 디렉터리(테넌트) ID 를 복사합니다.
MSAL(Microsoft 인증 라이브러리)을 구성하려면:
애플리케이션(클라이언트) ID 에 clientId
를 할당합니다.
https://login.microsoftonline.com/
에 authority
를 할당하고 끝에 디렉터리(테넌트) ID 를 추가합니다.
예:
var clientApplication;
(function (){
var msalConfig = {
auth: {
clientId: '00001111-aaaa-2222-bbbb-3333cccc4444',
authority: 'https://login.microsoftonline.com/7ef988bf-xxxx-51af-01ab-2d7fd011db47'
},
이전에 복사한 토큰 엔드포인트 URL로 theURL
변수를 설정합니다. 예:
(async function main() {
var theURL = "https://<token endpoint URL>"
사용자 지정 접두사를 포함하도록 userId
값을 편집합니다. 예:
var userId = clientApplication.account?.accountIdentifier != null ?
("My-custom-prefix" + clientApplication.account.accountIdentifier).substr(0, 64)
: (Math.random().toString() + Date.now().toString()).substr(0,64);
변경 내용을 저장합니다.
웹 페이지를 사용하여 에이전트를 테스트하세요
브라우저에서 웹 페이지를 엽니다.
로그인 을 선택합니다.
노트
브라우저가 팝업을 차단하거나 시크릿 모드 또는 비공개 탐색 창을 사용하는 경우 로그인하라는 메시지가 표시됩니다. 그렇지 않으면 인증 코드를 사용하여 로그인이 완료됩니다.
새 브라우저 탭이 열립니다.
새 탭으로 전환하고 유효성 검사 코드를 복사합니다.
에이전트 탭으로 돌아가서 검증 코드를 에이전트 대화에 붙여넣으세요.
관련 콘텐츠
기술 개요
다음 그림은 Copilot Studio에서 로그인 프롬프트(SSO)를 보지 않고 사용자가 로그인하는 방법을 보여줍니다.
에이전트 사용자가 토픽 로그인을 유발하는 문구를 입력합니다. 로그인 토픽은 사용자를 로그인하고 사용자의 인증된 토큰(User.AccessToken
변수) 를 사용하도록 설계되었습니다.
Copilot Studio는 사용자가 구성된 ID 공급자로 로그인할 수 있도록 로그인 프롬프트를 보냅니다.
에이전트의 사용자 정의 캔버스 는 로그인 프롬프트를 가로채서 Microsoft Entra ID에서 OBO(대리인) 토큰을 요청합니다. 캔버스는 토큰을 에이전트로 보냅니다.
OBO 토큰을 받으면 에이전트는 OBO 토큰을 "액세스 토큰"로 교환하고 액세스 토큰의 값을 사용하여 AuthToken
변수를 채웁니다. 이때 IsLoggedIn
변수도 설정됩니다.
사용자 지정 캔버스에 대한 Microsoft Entra ID에서 앱 등록 만들기
SSO를 활성화하려면 두 개의 개별 앱 등록이 필요합니다.
중요
에이전트의 사용자 인증과 사용자 정의 캔버스에 동일한 앱 등록을 재사용할 수 없습니다.
에이전트의 캔버스에 대한 앱 등록을 생성하세요
Azure Portal 에 로그인합니다.
아이콘을 선택하거나 상단 검색 창에서 검색하여 앱 등록 으로 이동합니다.
새 등록 을 선택합니다.
등록의 이름을 입력하십시오. 등록하려는 캔버스의 에이전트 이름을 사용하고 "canvas"를 포함하면 인증을 위한 앱 등록과 구분하는 데 도움이 될 수 있습니다.
예를 들어, 에이전트의 이름이 "Contoso 영업 지원"인 경우 앱 등록의 이름을 "ContosoSalesCanvas" 또는 이와 유사한 이름으로 지정할 수 있습니다.
지원되는 계정 유형 에서 모든 조직 테넌트의 계정(모든 Microsoft Entra ID 디렉터리 - 멀티테넌트) 및 개인 Microsoft 계정(예: Skype, Xbox) 의 계정을 선택합니다.
다음 단계에서 해당 정보를 입력하므로 지금은 리디렉션 URI 섹션을 비워 두십시오. 등록 을 선택합니다.
등록이 완료되면 개요 페이지에서 열립니다. 매니페스트 로 이동합니다. accessTokenAcceptedVersion
이 2
로 설정되었는지 확인합니다. 그렇지 않으면 2
로 변경하고 저장 을 선택합니다.
리디렉션 URL 추가
등록이 열린 상태에서 인증 으로 이동하고 플랫폼 추가 를 선택합니다.
플랫폼 구성 블레이드에서 웹 을 선택합니다.
리디렉션 URI 아래에서 채팅 캔버스가 호스팅되는 페이지에 전체 URL을 추가하세요해결 방법: 주제를 다시 활성화하거나 리디렉션 노드를 제거하십시오.. 암시적 허용 섹션에서 ID 토큰 과 액세스 토큰 확인란을 선택합니다.
구성 을 선택하여 변경 내용을 확인합니다.
API 권한 으로 이동합니다. <자신의 테넌트 이름>에 대해 관리자 동의 부여 와 예 를 차례로 선택합니다.
중요
사용자가 각 애플리케이션에 동의하해야 하는 것을 방지하려면 전역 관리자, 애플리케이션 관리자 또는 클라우드 애플리케이션 관리자가 앱 등록에 테넌트 수준 동의를 부여 해야 합니다.
에이전트에 대한 사용자 정의 범위를 정의하세요
인증 앱 등록 내에서 캔버스 앱 등록에 대한 API를 노출하여 사용자 지정 범위를 정의하십시오. 범위 를 사용하여 사용자 및 관리자 역할과 액세스 권한을 결정할 수 있습니다.
이 단계에서는 인증용 인증 앱 등록과 사용자 지정 캔버스의 앱 등록 간에 신뢰 관계를 생성합니다.
인증을 구성할 때 만든 앱 등록을 엽니다.
API 권한 으로 이동하여 에이전트에 대한 올바른 권한이 추가되었는지 확인하세요. <자신의 테넌트 이름>에 대해 관리자 동의 부여 와 예 를 차례로 선택합니다.
중요
사용자가 각 애플리케이션에 동의하해야 하는 것을 방지하려면 전역 관리자, 애플리케이션 관리자 또는 클라우드 애플리케이션 관리자가 앱 등록에 테넌트 수준 동의를 부여 해야 합니다.
API 노출 로 이동하여 범위 추가 를 선택합니다.
사용자가 SSO 화면을 볼 때 표시되어야 하는 표시 정보와 함께 범위 이름을 입력하십시오. 범위 추가 를 선택합니다.
클라이언트 애플리케이션 추가 를 선택합니다.
캔버스 앱 등록에 대한 개요 페이지의 애플리케이션(클라이언트) ID 를 클라이언트 ID 필드에 입력합니다. 생성한 나열된 범위의 확인란을 선택하십시오.
애플리케이션 추가 를 선택합니다.
Copilot Studio 인증 구성 페이지의 토큰 교환 URL 는 Bot Framework를 통해 요청된 액세스 토큰에 대한 OBO 토큰을 교환하는 데 사용됩니다.
Copilot Studio는 Microsoft Entra ID가 실제 교환을 수행하도록 합니다.
Copilot Studio에 로그인합니다.
상단 메뉴에서 에이전트 아이콘을 선택하고 올바른 에이전트를 선택하여 인증을 활성화하려는 에이전트를 선택했는지 확인하세요.
탐색 메뉴에서 설정 아래의 보안 을 선택합니다. 그런 다음 인증 카드를 선택합니다.
에이전트 인증 앱 등록을 위한 API 노출 블레이드에서 전체 범위 URI를 토큰 교환 URL 필드에 입력합니다. URI는 api://1234-4567/scope.name
형식입니다.
저장 을 선택한 후 에이전트 콘텐츠를 게시합니다.
에이전트가 있는 사용자 지정 캔버스 페이지를 업데이트하여 로그인 카드 요청을 가로채고 OBO 토큰을 교환합니다.
<head> 섹션의 <script> 태그에 다음 코드를 추가하여 Microsoft 인증 라이브러리(MSAL)를 구성합니다.
캔버스 앱 등록을 위해 응용 프로그램(클라이언트) ID 로 clientId
를 업데이트합니다. <Directory ID>
를 디렉터리(테넌트) ID 로 교체합니다. 이 ID는 캔버스 앱 등록의 개요 페이지에서 얻을 수 있습니다.
<head>
<script>
var clientApplication;
(function () {
var msalConfig = {
auth: {
clientId: '<Client ID [CanvasClientId]>',
authority: 'https://login.microsoftonline.com/<Directory ID>'
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: false
}
};
if (!clientApplication) {
clientApplication = new Msal.UserAgentApplication(msalConfig);
}
} ());
</script>
</head>
<body> 섹션에 다음 <script>를 삽입합니다. 이 스크립트는 메서드를 호출하여 resourceUrl
을 검색하고 현재 토큰을 OAuth 프롬프트에서 요청한 토큰으로 교환합니다.
<script>
function getOAuthCardResourceUri(activity) {
if (activity &&
activity.attachments &&
activity.attachments[0] &&
activity.attachments[0].contentType === 'application/vnd.microsoft.card.oauth' &&
activity.attachments[0].content.tokenExchangeResource) {
// asking for token exchange with Microsoft Entra ID
return activity.attachments[0].content.tokenExchangeResource.uri;
}
}
function exchangeTokenAsync(resourceUri) {
let user = clientApplication.getAccount();
if (user) {
let requestObj = {
scopes: [resourceUri]
};
return clientApplication.acquireTokenSilent(requestObj)
.then(function (tokenResponse) {
return tokenResponse.accessToken;
})
.catch(function (error) {
console.log(error);
});
}
else {
return Promise.resolve(null);
}
}
</script>
<body> 섹션에 다음 <script>를 삽입합니다. main
메서드 내에서 이 코드는 에이전트의 고유 식별자를 사용하여 store
에 조건을 추가합니다. 또한 고유 ID를 userId
변수로 생성합니다.
에이전트의 ID를 업데이트하세요. <COPILOT ID>
사용 중인 에이전트의 채널 탭 으로 이동하여 포털에서 모바일 앱 을 선택하면 에이전트의 ID를 확인할 수 있습니다. Copilot Studio
<script>
(async function main() {
// Add your AGENT ID below
var BOT_ID = "<BOT ID>";
var theURL = "https://powerva.microsoft.com/api/botmanagement/v1/directline/directlinetoken?botId=" + BOT_ID;
const {
token
} = await fetchJSON(theURL);
var directline = await fetchJSON(regionalChannelSettingsURL).then(res=> res.channelUrlsById.directline);
const directLine = window.WebChat.createDirectLine({
domain: `${directline}v3/directline`,
token
});
var userID = clientApplication.account?.accountIdentifier != null ?
("Your-customized-prefix-max-20-characters" + clientApplication.account.accountIdentifier).substr(0, 64) :
(Math.random().toString() + Date.now().toString()).substr(0, 64); // Make sure this will not exceed 64 characters
const store = WebChat.createStore({}, ({
dispatch
}) => next => action => {
const {
type
} = action;
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'startConversation',
type: 'event',
value: {
text: "hello"
}
}
});
return next(action);
}
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
const activity = action.payload.activity;
let resourceUri;
if (activity.from && activity.from.role === 'bot' &&
(resourceUri = getOAuthCardResourceUri(activity))) {
exchangeTokenAsync(resourceUri).then(function(token) {
if (token) {
directLine.postActivity({
type: 'invoke',
name: 'signin/tokenExchange',
value: {
id: activity.attachments[0].content.tokenExchangeResource.id,
connectionName: activity.attachments[0].content.connectionName,
token,
},
"from": {
id: userID,
name: clientApplication.account.name,
role: "user"
}
}).subscribe(
id => {
if (id === 'retry') {
// The agent was not able to handle the invoke, so display the oauthCard
return next(action);
}
// else: tokenexchange successful and we do not display the oauthCard
},
error => {
// an error occurred to display the oauthCard
return next(action);
}
);
return;
} else
return next(action);
});
} else
return next(action);
} else
return next(action);
});
const styleOptions = {
// Add styleOptions to customize Web Chat canvas
hideUploadButton: true
};
window.WebChat.renderWebChat({
directLine: directLine,
store,
userID: userID,
styleOptions
},
document.getElementById('webchat')
);
})().catch(err => console.error("An error occurred: " + err));
</script>
전체 샘플 코드
자세한 내용은 GitHub 리포지토리에 이미 포함된 MSAL 및 저장소 조건부 스크립트와 함께 전체 샘플 코드를 찾을 수 있습니다.