How to configure the Partner Center API with MFA (App & User)?

177 Views Asked by At

I'm trying to follow the steps in this link: https://github.com/MicrosoftDocs/partner-rest/blob/docs/partner-rest/develop/api-authentication.md

But after the creation of the app and user access, it doesn't show how to call the API. I'm trying to connect using Python/Spark, but can't go further because there's no documentation that explains how to do it step-by-step.

The code below is an example from the app-only authentication, it works but it doesn't allow to get some data that requires the app+user auth.

import requests, json
from pyspark.sql import SparkSession
from pyspark.sql.types import StructField, StringType, IntegerType, StructType

access_var = {
    "auth_url": "https://login.microsoftonline.com/tenantid/oauth2/token",
    "resource": "https://graph.windows.net",
    "client_id": {mssparkutils.credentials.getSecret('https://vaultname.vault.azure.net/', 'KV-Client-ID')},
    "client_st": {mssparkutils.credentials.getSecret('https://vaultname.vault.azure.net/', 'KV-Client-Secret')},
    "grant_type": "client_credentials"
}

_schema = StructType([
    StructField("Tenant ID", StringType(), True),
    StructField("Domain", StringType(), True),
    StructField("Company", StringType(), True),
    StructField("URI", StringType(), True)
])

def get_access():
    _body = {
            "resource": access_var["resource"],
            "client_id": access_var["client_id"],
            "client_secret": access_var["client_st"],
            "grant_type": access_var["grant_type"]
    }

    _headers = {"Content-Type": "application/x-www-form-urlencoded"}
    response = requests.post(access_var["auth_url"], data=_body, headers=_headers)
    response.raise_for_status()
    return response.json()

response = get_access()
access_t = response["access_token"]

def catch(api_url):
    "https://api.partnercenter.microsoft.com/v1/customers"

def fetch():
    api_url = "https://api.partnercenter.microsoft.com/v1/customers"
    api_auth = {
        "Authorization": f"Bearer {access_t}",
        "Accept": "application/json"
    }
    api_response = requests.get(api_url, headers=api_auth)
    return api_response.json()

def create_df(spark, result_list):
    return spark.createDataFrame(result_list, schema=_schema)

if __name__ == "__main__":
    spark = SparkSession.builder.appName("API_CALL").getOrCreate()
    all_results = []

    data = fetch()
    result_list = data

    for item in result_list["items"]:
        tenant_id = item["companyProfile"].get("tenantId", "N/A").strip()
        domain = item["companyProfile"].get("domain", "N/A").strip()
        company_name = item["companyProfile"].get("companyName").strip()
        uri = item["links"]["self"]["uri"]

        all_results.append((tenant_id, domain, company_name, uri))
    
    df = create_df(spark, all_results)
    df.show()
1

There are 1 best solutions below

0
Naveen Sharma On

You need to use delegated flows like authorization code or interactive flow to generate token for Partner Center API when user's MFA is enabled.

Register Azure AD application and grant API permissions of Delegated type as below:

enter image description here

While using interactive flow, you must include redirect URI for the Mobile and Desktop applications platform:

enter image description here

Make sure to enable public client flows in your app registration like this:

enter image description here

Now, make use of below Python code to generate access token for Partner Center API using interactive flow that asks user to sign in:

import msal

tenant_id = "tenantId"
client_id = "appId"
authority = f'https://login.microsoftonline.com/{tenant_id}'

scope = ["https://api.partnercenter.microsoft.com/user_impersonation"]

app = msal.PublicClientApplication(
    client_id,
    authority=authority,
)

token_response = app.acquire_token_interactive(scopes=scope)
access_token = token_response['access_token']
print("Access token:", access_token)

Response:

enter image description here

You can decode the above token in jwt.ms and check whether aud & scp claims have valid values or not:

enter image description here

Using the above token, you can make requests to Partner Center API with below updated python code:

import msal

tenant_id = "tenantId"
client_id = "appId"
authority = f'https://login.microsoftonline.com/{tenant_id}'

scope = "https://api.partnercenter.microsoft.com/user_impersonation"

app = msal.PublicClientApplication(
    client_id,
    authority=authority,
)

token_response = app.acquire_token_interactive(scopes=scope)
access_token = token_response['access_token']

# Make a request to the Partner Center API
api_url = "https://api.partnercenter.microsoft.com/v1/customers"
headers = {
    'Authorization': 'Bearer ' + access_token,
    'Content-Type': 'application/json',
}

response = requests.get(api_url, headers=headers)

if response.status_code == 200:
    print("API request successful")
    print(response.json())
else:
    print(f"API request failed with status code {response.status_code}")
    print(response.text)

Reference: Partner Center authentication - Partner app developer | Microsoft