Dela via


Hämta en åtkomsttoken (Python)

Det här exemplet visar hur du anropar ett externt Python-skript för att hämta en OAuth2-token. En giltig OAuth2-åtkomsttoken krävs av implementeringen av autentiseringsdelegaten.

Förutsättningar

Så här kör du exemplet:

  • Installera Python 3.10 eller senare.
  • Implementera utils.h/cpp i projektet.
  • Auth.py ska läggas till i projektet och finnas i samma katalog som binärfilerna i bygget.
  • Slutför installation och konfiguration av Microsoft Information Protection (MIP) SDK. Du kan bland annat registrera klientprogrammet i din Microsoft Entra-klientorganisation. Microsoft Entra ID tillhandahåller ett program-ID, även kallat klient-ID, som används i din tokenanskaffningslogik.

Den här koden är inte avsedd för produktionsanvändning. Den får endast användas för utveckling och förståelse av autentiseringsbegrepp. Exemplet är plattformsoberoende.

sample::auth::AcquireToken()

I det enkla autentiseringsexemplet demonstrerade vi en enkel AcquireToken() funktion som inte tog några parametrar och returnerade ett hårdkodat tokenvärde. I det här exemplet överbelastar vi AcquireToken() för att acceptera autentiseringsparametrar och anropar ett externt Python-skript för att returnera token.

auth.h

I auth.h AcquireToken() är överlagrade och den överlagrade funktionen och uppdaterade parametrar är följande:

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

De första tre parametrarna tillhandahålls av användarindata eller hårdkodade i ditt program. De två sista parametrarna tillhandahålls av SDK till autentiseringsdelegaten.

auth.cpp

I auth.cpp lägger vi till den överlagrade funktionsdefinitionen och definierar sedan den kod som krävs för att anropa Python-skriptet. Funktionen accepterar alla angivna parametrar och skickar dem till Python-skriptet. Skriptet kör och returnerar token i strängformat.

#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-skript

Det här skriptet hämtar autentiseringstoken direkt via Microsoft Authentication Library (MSAL) för Python. Den här koden ingår endast som ett sätt att hämta autentiseringstoken för användning av exempelapparna och är inte avsedd att användas i produktion. Skriptet fungerar endast mot klienter som stöder vanlig gammal användarnamn-/lösenordsautentisering. MFA eller certifikatbaserad autentisering stöds inte via det här skriptet.

Kommentar

Innan du kör det här exemplet måste du installera MSAL för Python genom att köra något av följande kommandon:

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

Uppdatera AcquireOAuth2Token

AcquireOAuth2Token Uppdatera slutligen funktionen i AuthDelegateImpl för att anropa den överlagrade AcquireToken funktionen. Resurs- och utfärdar-URL:erna hämtas genom att läsa challenge.GetResource() och challenge.GetAuthority(). OAuth2Challenge Skickas till autentiseringsdelegaten när motorn läggs till. Det här arbetet utförs av SDK och kräver inget extra arbete från utvecklarens sida.

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

När läggs engine till anropar SDK:et funktionen AcquireOAuth2Token, skickar uppgiften, kör Python-skriptet, tar emot en token och presenterar sedan token för tjänsten.