Microsoft 365 커넥터¶
Microsoft 365 커넥터는 Microsoft Graph를 통해 Outlook 메일함과 일정에 접근하는데, Microsoft 로그인 한 번으로 두 백엔드가 함께 연결됩니다. 두 백엔드는 이메일 작업을 처리하는 Microsoft 365 메일(m365_mail)과 일정 작업을 처리하는 Microsoft 365 일정(m365_calendar)이고, 둘 다 Google 캘린더나 IMAP 이메일 커넥터와 같은 승인, 감사, 되돌리기 경로를 거칩니다. 그래서 실행한 작업은 감사 로그 페이지에 같은 되돌리기 버튼과 함께 남습니다.
회사 계정, 학교 계정, 개인 Microsoft 계정을 모두 사용할 수 있고, macOS, Windows, Linux와 헤드리스 서버에서 똑같이 동작합니다.
로그인¶
로그인에는 Microsoft의 디바이스 코드 방식이 사용되는데, 데스크탑에서도 브라우저가 없는 서버에서도 같은 순서로 진행됩니다.
- 로그인을 시작하면 Backend.AI GO가 Microsoft에 짧은 코드를 요청해, Microsoft 로그인 페이지 주소
https://microsoft.com/devicelogin과 함께 보여 줍니다. - 이 컴퓨터든 다른 기기든 아무 브라우저에서 해당 페이지를 열고 코드를 입력해 주세요.
- Microsoft 계정으로 로그인하고, 아래 표의 권한을 승인해 주세요.
- Backend.AI GO는 몇 초마다 Microsoft에 결과를 확인하다가, 승인이 끝나면 토큰을 운영체제 키체인에 저장하고 두 백엔드를 연결합니다.
코드는 15분쯤 지나면 만료됩니다. 만료됐거나 Microsoft 페이지에서 거절했다면 처음부터 다시 시작해 주세요.
로그인하려면 Microsoft Entra 앱 등록의 애플리케이션(클라이언트) ID가 필요합니다. 조직이 관리하는 ID가 있거나 빌드에 기본값이 들어 있으면 따로 묻지 않고, 둘 다 없으면 ID를 입력할 때까지 로그인이 MICROSOFT_CLIENT_ID_REQUIRED 오류로 멈춥니다. 앱 등록을 참고해 주세요.
요청하는 권한¶
| 권한 | 용도 |
|---|---|
openid, profile | 계정을 식별하는 oid와 tid가 담긴 ID 토큰을 받습니다 |
offline_access | 새로 고침 토큰을 받아, 한 시간마다 다시 로그인하지 않아도 됩니다 |
User.Read | 로그인한 사용자의 기본 프로필을 읽습니다 |
Calendars.ReadWrite | 일정 조회, 생성, 수정, 취소, 초대 응답에 사용합니다 |
Mail.ReadWrite | 폴더와 메일 조회, 임시 저장, 지운 편지함으로 이동에 사용합니다 |
Mail.Send | 메일과 답장을 보냅니다 |
연락처 권한은 이 로그인에 포함되지 않습니다. 연락처 커넥터가 별도의 동의 단계에서 Contacts.Read를 따로 요청합니다.
앱 등록¶
Microsoft Entra 앱을 직접 등록해 클라이언트 ID를 입력하거나 조직에서 제공한 ID를 사용합니다. Backend.AI GO는 기본 클라이언트 ID를 제공하지 않습니다. 앱을 등록하려면 다음 순서를 따라 주세요.
- Microsoft Entra 관리 센터에서 앱 등록으로 이동해 새 등록을 선택해 주세요.
- 이름을 입력해 주세요(예:
Backend.AI GO). - 지원되는 계정 유형에서 로그인할 수 있는 사용자를 고릅니다. 모든 조직 디렉터리의 계정과 개인 Microsoft 계정을 허용하면 기본 테넌트인
common으로 바로 사용할 수 있고, 단일 테넌트 앱이라면 해당 테넌트를 지정해야 합니다(아래 참고). - 리디렉션 URI는 비워 두세요. 디바이스 코드 방식에는 필요하지 않습니다.
- 등록한 뒤 개요 페이지의 애플리케이션(클라이언트) ID를 복사해 주세요.
- 인증에서 퍼블릭 클라이언트 흐름 허용을 예로 바꿔 주세요. Backend.AI GO는 클라이언트 비밀을 두지 않는 퍼블릭 클라이언트라, 이 설정이 없으면 Microsoft가
AADSTS7000218오류로 로그인을 거부합니다. - API 권한에서 권한 추가 > Microsoft Graph > 위임된 권한을 고르고
offline_access,openid,profile,User.Read,Calendars.ReadWrite,Mail.ReadWrite,Mail.Send를 추가해 주세요. - 조직이 관리자 동의를 요구한다면 관리자 동의 허용을 선택해 주세요. 그렇지 않으면 사용자마다 로그인할 때 동의합니다.
로그인이 클라이언트 ID를 물으면 복사한 값을 입력하고, API로 로그인을 시작할 때는 clientId에 넣어 주세요.
조직에서 클라이언트 ID 지정¶
클라이언트 ID는 다음 중 먼저 값이 있는 것이 사용됩니다.
- 조직이 관리하는 설정
connectors.microsoft.clientId - 사용자가 입력한 클라이언트 ID
- 빌드할 때
AIGO_MICROSOFT_CLIENT_ID환경 변수로 넣은 기본값
관리자는 엔터프라이즈 정책의 설정 재정의로 관리 값을 지정합니다.
{
"settingsOverrides": {
"connectors": {
"microsoft": {
"clientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"tenant": "contoso.onmicrosoft.com"
}
}
}
}
connectors는 정책 전용 영역이라 사용자가 바꿀 수 없고, 이 영역을 바꾸려는 설정 업데이트는 거부됩니다. clientId가 지정되면 사용자가 입력한 클라이언트 ID는 무시됩니다. tenant는 테넌트를 고정하는 값으로 테넌트 ID, 확인된 도메인, organizations, consumers 가운데 하나를 받으며, 다른 테넌트를 지정한 로그인은 거부됩니다. 지정하지 않으면 회사, 학교, 개인 계정을 모두 받는 common이 사용되고, 테넌트를 테넌트 ID로 고정했다면 다른 테넌트의 계정은 로그인한 직후에 거부됩니다.
Backend.AI GO를 소스에서 직접 빌드한다면 빌드 환경에 AIGO_MICROSOFT_CLIENT_ID를 넣어 해당 빌드의 기본값으로 지정할 수 있습니다. 컴파일할 때 읽는 값이라 이미 만든 빌드에는 나중에 바꿔도 반영되지 않습니다.
네트워크와 국가별 클라우드¶
로그인은 microsoftLogin 서비스 엔드포인트(https://login.microsoftonline.com/)로, 메일과 일정 호출은 모두 microsoftGraph 엔드포인트(https://graph.microsoft.com/)로 갑니다. 두 엔드포인트 모두 관리 서비스 엔드포인트 목록에 있어서, 조직이 국가별 클라우드로 바꾸거나, 외부 접속 허용 목록에 넣거나, 끌 수 있습니다. 둘 중 하나가 꺼져 있거나 설치가 에어갭 모드로 동작하면, 로그인과 모든 Microsoft 호출은 연결을 열기 전에 거부됩니다.
작업별 동작¶
메일과 일정 요청은 이메일과 일정 작업에 provider: "microsoft"를 붙인 것입니다. 메일 요청은 메일을 messageId로 가리키고 일반 텍스트 query로 검색하는데, Microsoft 계정에 IMAP 필드(uid, criteria, originalUid)를 보내거나 IMAP 계정에 Microsoft 필드를 보내면 거부됩니다. 메일과 일정의 id는 Microsoft의 변경 불가 id라서, 메일이 다른 폴더로 옮겨져도 그대로 유지됩니다.
| 작업 | 승인 | 되돌리기 |
|---|---|---|
| 캘린더 목록, 일정 목록, 일정 조회 | 없음 | 되돌릴 것 없음 |
| 일정 만들기 | 없음 | 일정을 취소합니다. 참석자가 있으면 Microsoft가 취소 알림을 보냅니다 |
| 일정 수정 | 요청 | 이전 값으로 되돌립니다(최선 노력) |
| 일정 취소 | 요청 | 일정을 다시 만듭니다. 회의는 [Cancelled in error] 표시와 함께 돌아오고 참석자는 새 초대를 받습니다 |
| 초대 응답 | 없음 | 이전 응답을 다시 보냅니다 |
| 폴더 목록, 메일 목록·조회·검색 | 없음 | 되돌릴 것 없음 |
| 보내기, 답장 | 처음 보내는 받는 사람일 때 요청 | 계정의 대기 시간 안이라면 보낸 편지함의 사본을 지운 편지함으로 옮깁니다. 받는 사람의 메일은 그대로 남습니다 |
| 임시 저장 | 없음 | 임시 저장 메일을 삭제합니다 |
| 메일 삭제 | 요청 | 원래 있던 폴더로 다시 옮깁니다 |
시작과 끝을 모두 지정한 일정 목록은 캘린더 보기로 조회되므로 반복 회의가 회차별로 나오고, 시간은 UTC로 돌아옵니다. Microsoft가 허용하지 않는 두 가지 요청은 무시하지 않고 거부되는데, 응답을 '응답 안 함'으로 되돌리는 요청과 내가 주최한 회의를 참석자에게 알리지 않고 취소하는 요청입니다(Microsoft는 항상 참석자에게 알립니다).
초대받은 일정은 내 캘린더에서 지울 수 있지만, 되돌려도 초대가 다시 생기지는 않습니다. 이때는 주최자에게 초대를 다시 보내 달라고 요청해 주세요.
다른 사람에게 가는 작업은 먼저 대기합니다¶
보내기, 답장, 그리고 참석자에게 알림이 가는 일정 변경(내가 주최한 회의의 초대, 수정, 취소)은 보낼 편지함(outbox)이 갖춰지면 계정의 대기 시간이 지난 뒤에 실행되므로, 대기 시간 안에 되돌리면 아무것도 보내지지 않습니다. 메일 대기 시간은 unsendWindowSecs, 일정 대기 시간은 cancelUnsendWindowSecs이고, 둘 다 기본 30초에 로그인하거나 연결할 때 300초까지 늘릴 수 있습니다. 메일 대기 시간은 메일이 나간 뒤 되돌리기를 제공하는 시간의 상한이기도 합니다.
계정과 토큰¶
토큰은 운영체제 키체인의 connector:microsoft:<계정 id> 아래에 저장되고, Backend.AI GO의 어떤 응답에도 담기지 않습니다. 한 계정의 두 백엔드는 세션 하나를 함께 사용하므로, 메일 때문에 새로 고친 토큰이 일정에도 그대로 사용됩니다. Microsoft는 새로 고침 토큰을 사용할 때마다 새 토큰으로 바꾸는데, 새 토큰은 다른 작업이 세션을 사용하기 전에 먼저 저장됩니다.
감사 로그의 각 항목에는 작업한 계정이 Microsoft 테넌트 ID와 개체 ID의 해시로 기록됩니다. 나중에 같은 계정 id로 다른 Microsoft 계정이 로그인하면, 이전 항목의 되돌리기는 새 계정의 메일함이나 일정에 손대지 않고 거부됩니다.
계정 연결을 끊으면 두 백엔드가 제거되고 키체인의 토큰이 삭제됩니다. 퍼블릭 클라이언트가 자기 새로 고침 토큰을 직접 폐기하는 방법을 Microsoft가 제공하지 않아서, 삭제된 토큰은 Microsoft 쪽에서 만료될 때까지 남습니다. 앱의 접근을 바로 막으려면 myapps.microsoft.com의 계정 앱 목록에서 해당 앱을 제거해 주세요.
앱을 다시 시작한 뒤에는 아래 연결 API로, 다시 로그인하지 않고 이미 로그인한 계정을 연결할 수 있습니다.
키체인에 갱신된 로그인 정보를 저장할 수 없으면 잠금을 해제하고 저장에 성공할 때까지 호출이 실패합니다. 저장된 로그인 정보에 검증된 계정 식별자가 없으면 다시 로그인해야 합니다.
REST API¶
헤드리스 서버도 같은 기능을 제공합니다. 상태 조회는 agent_read 범위가, 나머지 경로는 모두 agent_write 범위가 필요합니다.
| 경로 | 동작 |
|---|---|
POST /api/v1/connectors/microsoft/sign-in | 로그인을 시작합니다. 본문: accountId, 그리고 필요하면 clientId, tenant, unsendWindowSecs, cancelUnsendWindowSecs |
POST /api/v1/connectors/microsoft/sign-in/poll | loginSessionId로 결과를 한 번 확인합니다. status는 pending, approved, expired, cancelled, error 중 하나입니다 |
POST /api/v1/connectors/microsoft/sign-in/cancel | 로그인을 취소합니다 |
GET /api/v1/connectors/microsoft/accounts/{accountId} | 계정이 로그인·연결되어 있는지, 새 로그인의 클라이언트 ID를 어디서 가져오는지 알려 줍니다 |
POST /api/v1/connectors/microsoft/activate | 이미 로그인한 계정을 연결합니다 |
DELETE /api/v1/connectors/microsoft/accounts/{accountId} | 계정 연결을 끊고 토큰을 삭제합니다 |
메일과 일정 호출에는 이메일과 일정 경로를 사용해 주세요. 예를 들어 POST /api/v1/connectors/email/send에 "provider": "microsoft"를 붙이면 됩니다.
문제 해결¶
| 메시지 | 해결 방법 |
|---|---|
MICROSOFT_CLIENT_ID_REQUIRED | 앱 등록의 클라이언트 ID를 입력하거나, 관리자에게 관리 값을 지정해 달라고 요청해 주세요 |
MICROSOFT_PUBLIC_CLIENT_REQUIRED (AADSTS7000218) | 앱 등록에서 퍼블릭 클라이언트 흐름 허용을 켜 주세요 |
MICROSOFT_APPLICATION_NOT_FOUND (AADSTS700016) | 앱의 클라이언트 ID와 등록된 테넌트를 확인해 주세요 |
MICROSOFT_CONSENT_REQUIRED (AADSTS65001, AADSTS90094) | 위임 권한에 동의하고, 필요한 경우 관리자 동의를 받아 주세요 |
MICROSOFT_TENANT_MISMATCH | 설정된 테넌트에 속하는 계정과 앱 등록을 사용해 주세요 |
the sign-in ... expired or was revoked | 새로 고침 토큰이 더 이상 유효하지 않으니 다시 로그인해 주세요 |
permission denied | 로그인에 빠진 권한이 있습니다. 앱 등록에 권한을 추가한 뒤 다시 로그인해 주세요 |
operation 'connector' is disabled in air-gapped mode | 설치가 에어갭 모드라 Microsoft 365를 사용할 수 없습니다 |