Bagikan melalui


Memperoleh token akses (Python)

Contoh ini menunjukkan cara memanggil skrip Python eksternal untuk mendapatkan token OAuth2. Token akses OAuth2 yang valid diperlukan oleh delegasi otentikasi dalam implementasi.

Prasyarat

Untuk menjalankan sampel:

  • Instal Python 3.10 atau yang lebih baru.
  • Terapkan utils.h/cpp dalam proyek Anda.
  • Auth.py harus ditambahkan ke proyek Anda dan ada di direktori yang sama dengan biner yang sedang dibangun.
  • Selesaikan penyiapan dan konfigurasi SDK Microsoft Information Protection (MIP). Di antara tugas lain, Anda mendaftarkan aplikasi klien di penyewa Microsoft Entra Anda. MICROSOFT Entra ID menyediakan ID aplikasi, juga dikenal sebagai ID klien, yang digunakan dalam logika akuisisi token Anda.

Kode ini tidak ditujukan untuk penggunaan produksi. Ini hanya dapat digunakan untuk pengembangan dan pemahaman konsep autentikasi. Sampelnya adalah lintas platform.

sample::auth::AcquireToken()

Dalam contoh autentikasi sederhana, kami menunjukkan fungsi sederhana AcquireToken() yang tidak mengambil parameter dan mengembalikan nilai token yang dikodekan secara permanen. Dalam contoh ini, kami membebani AcquireToken() untuk menerima parameter autentikasi dan memanggil skrip Python eksternal untuk mengembalikan token.

auth.h

Dalam auth.h, AcquireToken() kelebihan beban dan fungsi yang kelebihan beban dan parameter yang diperbarui adalah sebagai berikut:

//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.
    }
}

Tiga parameter pertama disediakan oleh input pengguna atau dikodekan secara permanen ke aplikasi Anda. Dua parameter terakhir disediakan oleh SDK kepada delegasi autentikasi.

auth.cpp

Dalam auth.cpp, kita menambahkan definisi fungsi yang kelebihan beban, lalu menentukan kode yang diperlukan untuk memanggil skrip Python. Fungsi ini menerima semua parameter yang disediakan dan meneruskannya ke skrip Python. Skrip menjalankan dan mengembalikan token dalam format string.

#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;
    }
    }
}

Skrip Python

Skrip ini memperoleh token autentikasi secara langsung melalui Microsoft Authentication Library (MSAL) untuk Python. Kode ini hanya disertakan sebagai sarana untuk memperoleh token autentikasi untuk digunakan oleh aplikasi sampel dan tidak dimaksudkan untuk digunakan dalam produksi. Skrip hanya berfungsi terhadap penyewa yang mendukung autentikasi nama pengguna/kata sandi lama biasa. MFA atau autentikasi berbasis sertifikat tidak didukung melalui skrip ini.

Nota

Sebelum menjalankan sampel ini, Anda harus menginstal MSAL untuk Python dengan menjalankan salah satu perintah berikut:

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:])

Memperbarui AcquireOAuth2Token

Terakhir, perbarui fungsi AcquireOAuth2Token di AuthDelegateImpl untuk memanggil fungsi AcquireToken yang dipakai berlebih. URL sumber daya dan otoritas diperoleh dengan membaca challenge.GetResource() dan challenge.GetAuthority(). OAuth2Challenge diteruskan ke delegasi autentikasi saat mesin ditambahkan. Pekerjaan ini dilakukan oleh SDK dan tidak memerlukan pekerjaan tambahan pada bagian pengembang.

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;
}

Ketika engine ditambahkan, SDK memanggil fungsi "AcquireOAuth2Token", mengoper tantangan, menjalankan skrip Python, menerima token, lalu menyajikan token ke layanan.