(Flutter)Microsoft Graph API 개요 및 사용해 보기

BK·2023년 5월 2일
2
post-thumbnail

목적 : Flutter 프로젝트로 MS Graph API 사용해보기

마이크로소프트 사에서 제공하는 서비스 중에 Microsoft Graph 라는 서비스가 있는데, 이 놈이 무엇인지. 어떻게 활용할 수 있는지에 대해 조사한 내용입니다.

1. Microsoft 개요

마소에서는 다양한 서비스를 제공하고 있는데 이중에 Microsoft Graph 서비스와, Microsoft ID Platform 서비스를 사용하면 실제 MS365를 구독중인 회사에서는 업무 생산성 및 편의성을 향상 시킬 수 있음

1) 서비스 개요

(1) Microsoft 365

  • 온라인 구독 기반 종합 Office 프로그램 (PowerPoint, Excel, Word, Outlook 등)
  • 원래는 Office365 라는 서비스명에서 명칭이 변경됨
  • 비슷한 서비스로 Office2021 이 있음 (두 서비스의 큰 차이점은 Web/Mobile 버전의 Office 앱을 이용할 수 있냐 없냐의 차이다. 예전에는 Office를 사용했으나, MS 클라우드 서비스가 시작되면서 온라인 구독 기반의 Microsoft365 서비스가 생겨났다.)
  • 이후에 설명할 Microsoft Graph 및 Microsoft ID Platform 모두 Microsoft365와 관련이 있음
  • Microsoft 365 웹사이트

(2) Microsoft Graph

  • Microsoft 365 서비스에 저장된 데이터에 대한 액세스를 제공하는 서비스 (사용자 및 그룹, Teams 데이터, 작업, 파일, 메일, 모임 및 일정, 조직도 등)
  • 즉, 365 구독중인 서비스에서 나오는 거의 모든 데이터를 액세스할 수 있는 서비스이다.
  • Graph API 형식으로 제공된다.

(3) Microsoft ID Platform

  • Microsoft 계정 혹은 소셜 계정을 통해 로그인하고 인증 및 권한을 부여하는 통합 플랫폼
  • 간단하게 말하면 MS용 통합 로그인 인증 서비스이다
  • Graph API를 활용하기 위해서는 ID 인증 후 액세스 토큰을 발급받아 사용해야 함

2. Microsoft ID Platfom

1) 설명 및 동작 방식

  • Microsoft ID Platform 학습 사이트
  • 마이크로소프트 계정 혹은 소셜 계정을 통해 로그인하고 인증 및 권한을 부여하는 통합 플랫폼.
  • 다양한 애플리케이션에 호환
  • 구성요소
    • OAuth 2.0 및 OpenID Connect 표준 규격 인증 서비스.
    • MSAL 오픈 소스 라이브러리.
    • Azure Portal 내 관리 기능.
  • 로그인 흐름 이미지

(1) MSAL 설명

(2) MSAL Flutter Module

  • MSAL Flutter Pub Dev
  • Flutter용 모듈. (이 외에도 다양한 플랫폼 별 모듈을 지원하고 있다)
  • Pub.dev에서 보면 MSAL Flutter, Azure AD Authentication 이렇게 두개의 라이브러리가 공존하고 있는데, 필자는 최신까지도 업데이트 되고 있는 Azure AD Authentication를 이용했음

2) 통합 로그인 방식

  • 회사에 사내 앱이 있는 경우 통합 로그인 기능을 Microsoft ID Platform을 통해 구현할 수 있음
  • 365 서비스를 이미 사용중인 회사의 경우 이미 서비스 사용자들(조직원들) 등록이 완료되었을 테고, 이 사용자 로그인 정보를 토대로 OAuth 방식을 통해 통합 로그인을 구현한다.
  • 통합로그인 흐름 이미지

1) Front 개발

  • Front-End 혹은 App 개발에서 MSAL 모듈을 적용 후 ID Platform을 호출하여 로그인 인증을 받음

2) Back-End 개발

  • Back-End에서는 별도의 배치 프로그램을 이용하여 정기적으로 전체 조직원에 대한 데이터를 확보함
  • 이 때는 로그인 인증이 아닌 별도의 SecretKey를 이용하여 사용자 없이 자격증명으로 처리함

3. Microsoft Graph

1) 설명 및 동작 방식

(1) Graph API 설명

  • Microsoft Graph 설명 사이트
  • Microsoft 365 서비스에 저장된 데이터에 대한 액세스를 제공하는 서비스 (사용자 및 그룹, Teams 데이터, 작업, 파일, 메일, 모임 및 일정, 조직도 등 모든 데이터에 대해 읽기, 쓰기 혹은 조회 서비스 제공)
  • Graph 설명 이미지

(2) Graph API 동작 방식

  • Microsoft ID Platform을 통해 인증 후, 발급받은 Access Token을 이용하여 Microsoft Graph API를 호출
  • 사용자 직접 로그인을 통해 ID Platform을 인증하는 방식이 있지만, 데몬 등의 서버 동작방식에서는 별도의 Secret 키를 발급받아 ID Platform 인증을 처리하여 사용함

(3) 예시 활용 사례

  • 모바일 환경 뿐 아니라 전체 영역에 대한 Microsoft Graph 활용 사례로는 워크플로 자동화를 관리하는 방안, 일정 공유, 업무 공유, 파일 공유 등 공동 업무의 생산성 향상 방안, 인사이트 도출을 위한 업무 방향 제시 등의 활용 사례가 있음

(4) 관련 사이트

4. Flutter로 MS Login 및 사용자 정보 가져와보기

0) 선행사항

1) Azure Portal에서 앱 등록

(1) 테넌트

  • 이미 로그인 시에 Directory를 만들면서 본인의 Tenent(테넌트)가 한개 생성되었을 것이므로, 또 다른 Directory를 만들 필요는 없음

(2) Azure AD 앱 등록

  • 애저 포털에 로그인 후 대시보드를 보면 서비스 목록 중에 Azure Active Directory 로 진입한다. (좌측의 메뉴바에서도 진입 가능)
  • 진입 후 좌측 메뉴에 앱 등록 항목으로 다시 한 번 진입
  • 상단 탭 바에 있는 +새등록 클릭
  • 본인의 앱 명칭을 작성, 계정 유형은 사내용으로 진행하므로 단일 테넌트,. 그 후 등록 버튼 클릭
  • (중요) 등록 후 나오는 애플리케이션(클라이언트) ID 문자열 값을 사용해야 한다. 복사 해놓고 기억하기

(3) Azure AD 앱 API 사용권한 등록

  • 앱 등록 후 API 사용권한을 등록해주어야 한다.
  • 왼쪽 메뉴탭에서 API 사용권한 > +권한 추가 > Microsoft Graph 선택
  • 위임된 권한 > 권한 선택 항목에서 검색으로 user.read 검색 후 선택 및 권한 추가 버튼 클릭
  • (중요) 소스코드와 동일한 Scope를 주기 위해 User.Read, User.Read.All 권한을 찾아서 선택하고 추가함.
  • 권한 두개 등록 된 후 해당 앱에 대한 API 사용 권한을 관리자 동의 허용 선택

(4) 사용 플랫폼 등록

  • 다시 앱 등록 화면 좌측 메뉴에서 인증 항목 선택 및 Android 플랫폼 추가
  • 패키지 이름과 서명 해시를 필수로 입력해야 하므로, 주어진 내용을 따라하여 값을 입력
  • (중요) 이때 서명 해시는 debug/release 구분해서 작성해야 하며, 혹시 디버그키도 별도로 지정하여 사용하는 경우 해당 디버그키의 경로를 확인하여 키 해시를 뽑아야 한다. 만약 올바른 경로가 아니면, 컴파일 상에서는 잡을수가 없음..
  • (중요) 완료 후에 구성된 리디렉션 URI 문자열 값을 사용해야 한다. 복사 해놓고 기억하기

(5) Azure AD 사용자 계정 확인

  • 이제 좌측 상단 네비 경로 중 한칸 뒤로 이동하여 다시 Azure AD 화면으로 돌아온 뒤에 메뉴 탭 사용자 항목을 선택
  • (중요) 한 개의 계정이 있을텐데 해당 계정으로 로그인 인증 테스트를 해볼 수 있다. 기억 해놓거나 사용하기 쉽게 아이디를 바꿔 놓아도 된다. (비밀번호는 원래 Azure 계정 비번과 동일하다)

2) 프로젝트 설정

  • Azure AD 앱 등록 설정이 끝난 후 Flutter 프로젝트를 신규로 만들어 설정해준다.

(1)프로젝트에 모듈 의존성 추가

  • pubspec.yaml 얌 파일에 모듈 추가 ( azure_ad_authentication, http(이건 rest 통신시 사용))
dependencies:
  azure_ad_authentication: ^1.0.5
  http: ^0.13.5
  flutter:
    sdk: flutter
  • 추가 후 pub get 수행

(2) package 명 설정

  • android 소스 build.gradle에서 아까 Azure 앱등록시 사용한 패키지명을 사용한다(아니면 프로젝트 패키지 아이디를 Azure에 다시 넣고 새로운 리디렉션URI를 받아도 상관없음)
android {
	defaultConfig {
        // TODO: Specify your own unique Application ID
        applicationId "아까 사용한 패키지명 입력"
        ...
        ...
    }
}
  • AndroidManifest.xml 에도 package명을 바꿔준다. 이때 debug, profile 폴더에 있는 다른경로의 AndroidManifest.xml 파일이 있으면 거기에도 모두 동일하게 바꿔준다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="아까 사용한 패키지명 입력">
}
  • Android의 경우 패키지명을 변경시 메인액티비티 패키지 경로도 실제 패키지명과 동일하게 바꿔주어야 한다.

(2) 샘플 코드 가져오기

  • MSAL 샘플코드 에서 코드 통째로 복사한 후, 프로젝트 main.dart 코드에 통째로 붙여넣기
  • 이 코드 중 상단에 있는 변수 _authority, _redirectUriMacos, _redirectUriIos, _clientId 값을 본인 값으로 바꾸어주어야 함
  static const String _authority =
      "https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize";
  static const String _redirectUriMacos = "msauth.msal2794d211-4e3f-4010-9f37-250f928d19c5://auth";
  //static const String _redirectUriIos = "msal2794d211-4e3f-4010-9f37-250f928d19c5";

  static const String _clientId = "2794d211-4e3f-4010-9f37-250f928d19c5";

  String _output = 'NONE';
  static const List<String> kScopes = [
    "https://graph.microsoft.com/user.read",
    "https://graph.microsoft.com/Calendars.ReadWrite",
  ];
  • _authority 값을 아래 경로 값으로 변경
  • 단일 테넌트 인증용 Authority 경로 (authority 경로는 다중 혹은 단일 인증 등 방식에 따라서 다르게 지정해줘야 함)
"https://login.microsoftonline.com/organizations"; // 단일 테넌트용 경로
  • _redirectUriMacos, _redirectUriIos 사용하지 않을 값이라 그대로 두어도 상관없음
  • _clientId 아까 AzureAD에서 App 등록하면서 발급받은 애플리케이션(클라이언트) ID 값을 넣는다.

(3) 추가 config 설정

  • Resource 경로의 raw 폴더에 config 파일을 추가한다. pub dev 모듈 페이지 참조
    (res > raw > msal_default_config.json )
  • 위 경로에 msal_default_config.json 파일을 만들어 아래 내용을 통째로 붙여넣는다.
  • 아래 client_id, redirect_uri 에 위에 기록해두었던 문자열을 추가한다
{
  "client_id" : "여기에 클라이언트 아이디를 넣는다",
  "authorization_user_agent" : "DEFAULT",
  "redirect_uri" : "msauth://xxxxxxxxxx/U5rbvBLdFUbEazWhQfDgt6oRa24%3D",
  "account_mode" : "MULTIPLE",
  "minimum_required_broker_protocol_version": "3.0",
  "multiple_clouds_supported": false,
  "broker_redirect_uri_registered": true,
  "web_view_zoom_controls_enabled": true,
  "web_view_zoom_enabled": true,
  "environment": "Production",
  "power_opt_check_for_network_req_enabled": true,
  "handle_null_taskaffinity": false,
  "authorization_in_current_task": false,
  "authorities" : [
    {
      "type": "AAD",
      "authority_url": "https://login.microsoftonline.com/organizations",
      "audience": {
        "type": "AzureADMyOrg",
        "tenant_id": "organizations"
      },
      "default": true
    }
  ],
  "browser_safelist": [
    {
      "browser_package_name": "com.android.chrome",
      "browser_signature_hashes": [
        "7fmduHKTdHHrlMvldlEqAIlSfii1tl35bxj1OXN5Ve8c4lU6URVu4xtSHc3BVZxS6WWJnxMDhIfQN0N0K2NDJg=="
      ],
      "browser_use_customTab" : true,
      "browser_version_lower_bound": "45"
    },
    {
      "browser_package_name": "com.android.chrome",
      "browser_signature_hashes": [
        "7fmduHKTdHHrlMvldlEqAIlSfii1tl35bxj1OXN5Ve8c4lU6URVu4xtSHc3BVZxS6WWJnxMDhIfQN0N0K2NDJg=="
      ],
      "browser_use_customTab" : false
    },
    {
      "browser_package_name": "org.mozilla.firefox",
      "browser_signature_hashes": [
        "2gCe6pR_AO_Q2Vu8Iep-4AsiKNnUHQxu0FaDHO_qa178GByKybdT_BuE8_dYk99G5Uvx_gdONXAOO2EaXidpVQ=="
      ],
      "browser_use_customTab" : false
    },
    {
      "browser_package_name": "org.mozilla.firefox",
      "browser_signature_hashes": [
        "2gCe6pR_AO_Q2Vu8Iep-4AsiKNnUHQxu0FaDHO_qa178GByKybdT_BuE8_dYk99G5Uvx_gdONXAOO2EaXidpVQ=="
      ],
      "browser_use_customTab" : true,
      "browser_version_lower_bound": "57"
    },
    {
      "browser_package_name": "com.sec.android.app.sbrowser",
      "browser_signature_hashes": [
        "ABi2fbt8vkzj7SJ8aD5jc4xJFTDFntdkMrYXL3itsvqY1QIw-dZozdop5rgKNxjbrQAd5nntAGpgh9w84O1Xgg=="
      ],
      "browser_use_customTab" : true,
      "browser_version_lower_bound": "4.0"
    },
    {
      "browser_package_name": "com.sec.android.app.sbrowser",
      "browser_signature_hashes": [
        "ABi2fbt8vkzj7SJ8aD5jc4xJFTDFntdkMrYXL3itsvqY1QIw-dZozdop5rgKNxjbrQAd5nntAGpgh9w84O1Xgg=="
      ],
      "browser_use_customTab" : false
    },
    {
      "browser_package_name": "com.cloudmosa.puffinFree",
      "browser_signature_hashes": [
        "1WqG8SoK2WvE4NTYgr2550TRhjhxT-7DWxu6C_o6GrOLK6xzG67Hq7GCGDjkAFRCOChlo2XUUglLRAYu3Mn8Ag=="
      ],
      "browser_use_customTab" : false
    },
    {
      "browser_package_name": "com.duckduckgo.mobile.android",
      "browser_signature_hashes": [
        "S5Av4cfEycCvIvKPpKGjyCuAE5gZ8y60-knFfGkAEIZWPr9lU5kA7iOAlSZxaJei08s0ruDvuEzFYlmH-jAi4Q=="
      ],
      "browser_use_customTab" : false
    },
    {
      "browser_package_name": "com.explore.web.browser",
      "browser_signature_hashes": [
        "BzDzBVSAwah8f_A0MYJCPOkt0eb7WcIEw6Udn7VLcizjoU3wxAzVisCm6bW7uTs4WpMfBEJYf0nDgzTYvYHCag=="
      ],
      "browser_use_customTab" : false
    },

    {
      "browser_package_name": "com.ksmobile.cb",
      "browser_signature_hashes": [
        "lFDYx1Rwc7_XUn4KlfQk2klXLufRyuGHLa3a7rNjqQMkMaxZueQfxukVTvA7yKKp3Md3XUeeDSWGIZcRy7nouw=="
      ],
      "browser_use_customTab" : false
    },

    {
      "browser_package_name": "com.microsoft.emmx",
      "browser_signature_hashes": [
        "Ivy-Rk6ztai_IudfbyUrSHugzRqAtHWslFvHT0PTvLMsEKLUIgv7ZZbVxygWy_M5mOPpfjZrd3vOx3t-cA6fVQ=="
      ],
      "browser_use_customTab" : false
    },

    {
      "browser_package_name": "com.opera.browser",
      "browser_signature_hashes": [
        "FIJ3IIeqB7V0qHpRNEpYNkhEGA_eJaf7ntca-Oa_6Feev3UkgnpguTNV31JdAmpEFPGNPo0RHqdlU0k-3jWJWw=="
      ],
      "browser_use_customTab" : false
    },

    {
      "browser_package_name": "com.opera.mini.native",
      "browser_signature_hashes": [
        "TOTyHs086iGIEdxrX_24aAewTZxV7Wbi6niS2ZrpPhLkjuZPAh1c3NQ_U4Lx1KdgyhQE4BiS36MIfP6LbmmUYQ=="
      ],
      "browser_use_customTab" : false
    },

    {
      "browser_package_name": "mobi.mgeek.TunnyBrowser",
      "browser_signature_hashes": [
        "RMVoXuK1sfJZuGZ8onG1yhMc-sKiAV2NiB_GZfdNlN8XJ78XEE2wPM6LnQiyltF25GkHiPN2iKQiGwaO2bkyyQ=="
      ],
      "browser_use_customTab" : false
    },

    {
      "browser_package_name": "org.mozilla.focus",
      "browser_signature_hashes": [
        "L72dT-stFqomSY7sYySrgBJ3VYKbipMZapmUXfTZNqOzN_dekT5wdBACJkpz0C6P0yx5EmZ5IciI93Q0hq0oYA=="
      ],
      "browser_use_customTab" : false
    }
  ]
}

(4) AndroidManifest.xml

  • BrowserTabActivity 항목 추가
<activity
          android:name="com.microsoft.identity.client.BrowserTabActivity"
          android:exported="true">
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
          android:scheme="msauth"
          android:host="패키지명 입력"
          android:path="/서명해시 입력" />
  </intent-filter>
</activity>
  • 위 host 입력란에 패키지명 입력
  • 위 서명해시 입력란에 /서명해시 입력

3) 프로젝트 Build & Run

  • 이제 모든 준비가 완료 되었다. 소스를 build 해 본다.

(1) 실행상태

(2) AcquireToken 버튼 터치

(3) 사용자 정보 입력

  • 아까 위에서 확인했던 사용자 정보(실제 Azure로그인 계정과는 다르다. 허나 비밀번호는 똑같다)를 입력한다.

(4) 성공 후 응답 값

  • 응답 데이터가 보이면 성공

5. 마무리

  • 이제 Microsoft ID Platform 및 Graph API를 활용하여 앱을 개발 할 수 있다!!
  • iOS는 Config 설정을 다르게 해주어야 하는데, 이것도 Microsoft 레퍼런스 문서를 확인해보면 알 수 있다.

관련사이트

profile
k-힙합을 사랑하는 개발자

0개의 댓글