다음을 통해 공유


액세스 토큰 획득(Python)

이 예제에서는 외부 Python 스크립트를 호출하여 OAuth2 토큰을 가져오는 방법을 보여 줍니다. 인증 대리자를 구현하려면 유효한 OAuth2 액세스 토큰이 필요합니다.

필수 조건

샘플을 실행하려면:

  • Python 3.10 이상 설치
  • 프로젝트에서 utils.h/cpp를 구현합니다.
  • Auth.py는 프로젝트에 추가되어야 하며, 빌드 시 이진 파일과 동일한 디렉토리에 있어야 합니다.
  • MIP(Microsoft Information Protection) SDK 설정 및 구성을 완료합니다. 다른 작업 중에는 Microsoft Entra 테넌트에 클라이언트 애플리케이션을 등록합니다. Microsoft Entra ID는 토큰 획득 논리에 사용되는 클라이언트 ID라고도 하는 애플리케이션 ID를 제공합니다.

이 코드는 프로덕션 용도로 사용하기 위한 것이 아닙니다. 인증 개념을 개발 및 이해하는 데만 사용할 수 있습니다. 샘플은 플랫폼 간입니다.

sample::auth::AcquireToken()

간단한 인증 예시에서 매개변수를 사용하지 않고 하드 코딩된 토큰 값을 반환하는 간단한 AcquireToken() 함수를 시연했습니다. 이 예제에서는 AcquireToken()을 오버로드하여 인증 매개 변수를 수락하고 외부 Python 스크립트를 호출하여 토큰을 반환합니다.

auth.h

auth.h AcquireToken() 에서 오버로드되고 오버로드된 함수 및 업데이트된 매개 변수는 다음과 같습니다.

//auth.h
#include <string>

namespace sample {
  namespace auth {
    std::string AcquireToken(
        const std::string& userName, //A string value containing the user's UPN.
        const std::string& password, //The user's password in plaintext
        const std::string& clientId, //The Azure AD client ID (also known as Application ID) of your application.
        const std::string& resource, //The resource URL for which an OAuth2 token is required. Provided by challenge object.
        const std::string& authority); //The authentication authority endpoint. Provided by challenge object.
    }
}

처음 세 개의 매개 변수는 사용자 입력에 의해 제공되거나 애플리케이션에 하드 코딩됩니다. 마지막 두 매개 변수는 SDK에서 인증 대리자에게 제공합니다.

auth.cpp

auth.cpp 오버로드된 함수 정의를 추가한 다음 Python 스크립트를 호출하는 데 필요한 코드를 정의합니다. 함수는 제공된 모든 매개 변수를 수락하고 Python 스크립트에 전달합니다. 스크립트는 문자열 형식으로 토큰을 실행하고 반환합니다.

#include "auth.h"
#include "utils.h"

#include <fstream>
#include <functional>
#include <memory>
#include <string>

using std::string;
using std::runtime_error;

namespace sample {
    namespace auth {

    //This function implements token acquisition in the application by calling an external Python script.
    //The Python script requires username, password, clientId, resource, and authority.
    //Username, Password, and ClientId are provided by the user/developer
    //Resource and Authority are provided as part of the OAuth2Challenge object that is passed in by the SDK to the AuthDelegate.
    string AcquireToken(
        const string& userName,
        const string& password,
        const string& clientId,
        const string& resource,
        const string& authority) {

    string cmd = "python";
    if (sample::FileExists("auth.py"))
        cmd += " auth.py -u ";

    else
        throw runtime_error("Unable to find auth script.");

    cmd += userName;
    cmd += " -p ";
    cmd += password;
    cmd += " -a ";
    cmd += authority;
    cmd += " -r ";
    cmd += resource;
    cmd += " -c ";
    // Replace <application-id> with the Application ID provided during your Azure AD application registration.
    cmd += (!clientId.empty() ? clientId : "<application-id>");

    string result = sample::Execute(cmd.c_str());
    if (result.empty())
        throw runtime_error("Failed to acquire token. Ensure Python is installed correctly.");

    return result;
    }
    }
}

Python 스크립트

이 스크립트는 Python용 MSAL(Microsoft 인증 라이브러리)을 통해 직접 인증 토큰을 획득합니다. 이 코드는 샘플 앱에서 사용할 인증 토큰을 획득하는 수단으로만 포함되며 프로덕션 환경에서는 사용할 수 없습니다. 이 스크립트는 일반 이전 사용자 이름/암호 인증을 지원하는 테넌트에 대해서만 작동합니다. MFA 또는 인증서 기반 인증은 이 스크립트를 통해 지원되지 않습니다.

참고 항목

이 샘플을 실행하기 전에 다음 명령 중 하나를 실행하여 Python용 MSAL을 설치해야 합니다.

pip install msal
pip3 install msal
import getopt
import sys
import json
import re
from msal import PublicClientApplication

def printUsage():
  print('auth.py -u <username> -p <password> -a <authority> -r <resource> -c <clientId>')

def main(argv):
  try:
    options, args = getopt.getopt(argv, 'hu:p:a:r:c:')
  except getopt.GetoptError:
    printUsage()
    sys.exit(-1)

  username = ''
  password = ''
  authority = ''
  resource = ''

  clientId = ''
    
  for option, arg in options:
    if option == '-h':
      printUsage()
      sys.exit()
    elif option == '-u':
      username = arg
    elif option == '-p':
      password = arg
    elif option == '-a':
      authority = arg
    elif option == '-r':
      resource = arg
    elif option == '-c':
      clientId = arg

  if username == '' or password == '' or authority == '' or resource == '' or clientId == '':
    printUsage()
    sys.exit(-1)

  # ONLY FOR DEMO PURPOSES AND MSAL FOR PYTHON
  # This shouldn't be required when using proper auth flows in production.  
  if authority.find('common') > 1:
    authority = authority.split('/common')[0] + "/organizations"
   
  app = PublicClientApplication(client_id=clientId, authority=authority)  
  
  result = None  

  if resource.endswith('/'):
    resource += ".default"    
  else:
    resource += "/.default"
  
  # *DO NOT* use username/password authentication in production system.
  # Instead, consider auth code flow and using a browser to fetch the token.
  result = app.acquire_token_by_username_password(username=username, password=password, scopes=[resource])  
  print(result['access_token'])

if __name__ == '__main__':  
  main(sys.argv[1:])

AcquireOAuth2Token 업데이트

마지막으로, 오버로드된 AcquireToken 함수를 호출하도록 함수 AuthDelegateImpl 를 업데이트 AcquireOAuth2Token 합니다. 리소스 및 권한 URL은 읽 challenge.GetResource()challenge.GetAuthority()은 후 . OAuth2Challenge 엔진이 추가되면 인증 대리자에게 전달됩니다. 이 작업은 SDK에서 수행되며 개발자 쪽에서 추가 작업이 필요하지 않습니다.

bool AuthDelegateImpl::AcquireOAuth2Token(
    const mip::Identity& /*identity*/,
    const OAuth2Challenge& challenge,
    OAuth2Token& token) {

    //call our AcquireToken function, passing in username, password, clientId, and getting the resource/authority from the OAuth2Challenge object
    string accessToken = sample::auth::AcquireToken(mUserName, mPassword, mClientId, challenge.GetResource(), challenge.GetAuthority());
    token.SetAccessToken(accessToken);
    return true;
}

이 함수가 engine 추가되면 SDK는 'AcquireOAuth2Token 함수를 호출하고, 챌린지를 전달하고, Python 스크립트를 실행하고, 토큰을 받은 다음, 토큰을 서비스에 제공합니다.