Uzyskiwanie tokenu dostępu (Python)
W tym przykładzie pokazano, jak wywołać zewnętrzny skrypt języka Python w celu uzyskania tokenu OAuth2. Prawidłowy token dostępu OAuth2 jest wymagany przez implementację delegata uwierzytelniania.
Wymagania wstępne
Aby uruchomić przykład:
- Zainstaluj środowisko Python w wersji 3.10 lub nowszej.
- Zaimplementuj plik utils.h/cpp w projekcie.
- Auth.py należy dodać do projektu i istnieć w tym samym katalogu co pliki binarne podczas kompilacji.
- Ukończ konfigurowanie i konfigurację zestawu SDK usługi Microsoft Information Protection (MIP). Między innymi zadania rejestrują aplikację kliencją w dzierżawie firmy Microsoft Entra. Identyfikator entra firmy Microsoft udostępnia identyfikator aplikacji, znany również jako identyfikator klienta, który jest używany w logice pozyskiwania tokenu.
Ten kod nie jest przeznaczony do użytku produkcyjnego. Można go używać tylko do opracowywania i rozumienia pojęć dotyczących uwierzytelniania. Przykład jest międzyplatformowy.
sample::auth::AcquireToken()
W prostym przykładzie uwierzytelniania przedstawiliśmy prostą AcquireToken()
funkcję, która nie miała parametrów i zwróciła zakodowaną wartość tokenu. W tym przykładzie przeciążamy metodę AcquireToken(), aby akceptować parametry uwierzytelniania i wywoływać zewnętrzny skrypt języka Python w celu zwrócenia tokenu.
auth.h
W pliku auth.h jest przeciążona, AcquireToken()
a przeciążona funkcja i zaktualizowane parametry są następujące:
//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.
}
}
Pierwsze trzy parametry są dostarczane przez dane wejściowe użytkownika lub zakodowane w aplikacji. Ostatnie dwa parametry są dostarczane przez zestaw SDK do delegata uwierzytelniania.
auth.cpp
W auth.cpp dodamy definicję przeciążonej funkcji, a następnie zdefiniuj kod niezbędny do wywołania skryptu języka Python. Funkcja akceptuje wszystkie podane parametry i przekazuje je do skryptu języka Python. Skrypt wykonuje i zwraca token w formacie ciągu.
#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;
}
}
}
Skrypt języka Python
Ten skrypt uzyskuje tokeny uwierzytelniania bezpośrednio za pośrednictwem biblioteki Microsoft Authentication Library (MSAL) dla języka Python. Ten kod jest dołączany tylko jako środek do uzyskiwania tokenów uwierzytelniania do użycia przez przykładowe aplikacje i nie jest przeznaczony do użycia w środowisku produkcyjnym. Skrypt działa tylko w przypadku dzierżaw, które obsługują zwykłe stare uwierzytelnianie nazwy użytkownika/hasła. Uwierzytelnianie wieloskładnikowe lub uwierzytelnianie oparte na certyfikatach nie jest obsługiwane za pośrednictwem tego skryptu.
Uwaga
Przed uruchomieniem tego przykładu należy zainstalować bibliotekę MSAL dla języka Python, uruchamiając jedno z następujących poleceń:
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:])
Aktualizowanie tokenu AcquireOAuth2Token
Na koniec zaktualizuj AcquireOAuth2Token
funkcję w pliku AuthDelegateImpl
, aby wywołać przeciążonej AcquireToken
funkcji. Adresy URL zasobów i urzędu są uzyskiwane przez odczyt challenge.GetResource()
i challenge.GetAuthority()
. Element OAuth2Challenge
jest przekazywany do delegata uwierzytelniania po dodaniu aparatu. Ta praca jest wykonywana przez zestaw SDK i nie wymaga dodatkowej pracy ze strony dewelopera.
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
Po dodaniu zestawu SDK wywołuje funkcję "AcquireOAuth2Token, przekazując wyzwanie, wykonując skrypt języka Python, odbierając token, a następnie prezentując token do usługi.